运行绑定到端口 80 的 Web 服务通常不需要 sudoer 权限。由于端口 80/443 是系统端口,这意味着它们只能由特权用户使用,那么这些服务如何仍然能够绑定到这些端口呢?
答案1
基本上有两种不同的方法:
最初以 root 身份运行,绑定到特权端口,然后降为非特权用户。
inetd 或 xinetd 以特权运行,并将请求转发到以非特权运行的 Web 服务器。
答案2
由于端口 80/443 是系统端口,这意味着它们只能由特权用户使用
我认为你错了。任何人都可以使用这些端口。捆绑对他们来说这是一项特权操作。
这里的理由是,某些用户 Joe 不应该能够编写恶意 Web 服务器,然后创建一些他没有任何管理权限的主机。当然,这是一个相当薄弱的模型,通常没有什么可以阻止 Joe 将自己的计算机放在网络上,并且他可以对他有物理访问权限的任何机器拥有管理权限。
我将用 netcat 做一个演示。
作为普通用户,我无法绑定到80端口:
$ nc -l -p 80
Can't grab 0.0.0.0:80 with bind : Permission denied
我可以绑定到端口 8080:
$ nc -l -p 8080
同时在另一个终端,我可以连接到端口 80 并发送一些数据,并看到它出现在我刚刚启动的服务器端:
$ nc 127.0.0.1 8080 <<<"Hello world"
如果我想绑定到端口 80,我需要成为 root :
$ sudo nc -l -p 80
或者我可以将CAP_NET_BIND_SERVICE
功能分配给nc
二进制文件:
$ cp `which nc` .
$ sudo setcap 'cap_net_bind_service=+ep' ./nc
$ ./nc -l -p 80
另一种选择是编写服务器程序,使其在调用后listen()
放弃 root 权限。这是一种非常常见的解决方案,您会在大多数守护进程中看到它。例如,Apache 从 init 以 root 身份启动,然后在绑定到端口www-data
80 后放弃 root 权限并成为用户或类似角色。尝试/etc/init.d/apache start
以非 root 身份运行,Apache 可能会启动失败。