尽管80和443是系统端口,但是大多数Web服务器如何能够绑定到它们?


Answers:


29

基本上有两种不同的方法:

  1. 最初以root用户身份开始运行,绑定到特权端口,然后下降到非特权用户。

  2. inetd或xinetd特权运行,并将请求转发到非特权运行的Web服务器。


3
在Linux上,您还可以将CAP_NET_BIND_SERVICE功能应用到程序,或者可以使用iptables将系统端口重定向到常规端口。
Zan Lynx 2015年

10
并为OP澄清一下:选项#1起作用的原因是因为当进程放弃特权时,它们被允许保留打开的文件描述符-即使不允许它们第二次打开它们。
2015年


5

由于端口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以root身份从init启动,然后放弃root特权并成为用户www-data或绑定端口80的类似用户。尝试/etc/init.d/apache start以非root身份运行,Apache可能无法启动。


问题是“绑定到这些端口”。你为什么认为他错了?
Barmar 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.