我在C中编写了自己的Web服务器。如何将其绑定到端口80而不是root用户,这样安全性不会受到影响(缓冲区溢出等)?
我应该简单地转发来自在端口80上运行的另一个“稳定”服务器的任何流量吗?
答案 0 :(得分:5)
使用转发代理确实是最简单和最推荐的解决方案。它还具有在甚至到达您自己编写的服务器之前过滤可怕无效请求的优点
如果您的应用程序使用用户的IP地址记住从Web服务器使用的任何标头中检索它(X-Client-IP
等)。但是,仅对来自您的Web服务器的请求执行此操作,否则用户可以欺骗其IP。您可以通过检查请求是否来自您的IP并在此情况下仅检查标头或仅将应用程序绑定到localhost来执行此操作。
另一种解决方案是授予程序CAP_NET_BIND_SERVICE
能力。这要求root使用setcap cap_net_bind_service=ep /path/to/the/executable
- 因为标志存储在filesystem属性中,所以当将文件复制到另一个系统或重新编译应用程序时,它将丢失。
当然,你也可以让你的程序setuid root,然后在调用bind()
后立即切换到非特权用户。但是,根据您的程序如何工作以及它的作用,这可能不是一个好主意 - 例如,如果由于某种原因需要关闭并重新打开侦听套接字,则需要完全重新启动该进程。
答案 1 :(得分:3)
以root身份调用bind()
,然后删除权限的替代方法是创建套接字并绑定它的根进程,然后通过UNIX域套接字连接将侦听套接字传递给非特权进程使用SCM_RIGHTS
消息。
答案 2 :(得分:2)
如果要将服务器绑定到端口80,则必须以root身份执行此操作,然后删除权限。
bind(sockfd, addr, addrlen);
/* process is running as root, drop privileges after bind*/
if (setgid(groupid) != 0)
errx(1, "setgid: Unable to drop group privileges: %s", strerror(errno));
if (setuid(userid) != 0)
errx(1, "setuid: Unable to drop user privileges: %S", strerror(errno));
如何在不成为root用户的情况下将其绑定到端口80,以确保安全性不受损害(缓冲区溢出等)。
不以root身份运行不使您的系统更安全,只需添加另一层即可利用。
因此,请确保不要使用任何已知不安全的函数,例如strcpy()
,sprintf()
等,而是使用strncpy()
,{snprintf()
,而不是考虑如何不以root用户身份运行。 1}}等等。
答案 3 :(得分:2)
您知道Unix中1024以下的所有端口都需要root权限才能打开。 在Unix系统上,您不希望尽可能少的应用程序以root权限运行。 这将是一个很大的安全风险。
另一种方法是使用iptables将端口80流量重定向到更加无害的端口,如8080.这是一个关于如何设置它的description。
Iptables不是最容易设置的工具,但是一旦掌握了它,它就非常有用且功能强大(并且安全)。
答案 4 :(得分:0)
我在这个问题上工作了很长时间,得出的结论是systemd
+ iptables
是解决方案,而不是功能,elaborated in great detail here