it-swarm.cn

如何在Linux上以普通用户身份在端口80上运行服务器?

我已经用Google搜索了很长时间的解决方案,但是找不到答案。

我在Ubuntu Linux上并想在端口80上运行服务器,但是由于Ubuntu的安全性机制,出现以下错误:

Java.net.BindException:权限被拒绝:80

我认为应该很简单,要么禁用此安全机制,以使端口80可供所有用户使用,要么为当前用户分配所需的特权以访问端口80。

324
Deepak Mittal

简短的答案:您不能。低于1024的端口只能由root用户打开。根据评论-好吧,您可以使用 CAP_NET_BIND_SERVICE ,但是将这种方法应用于Java bin会生成任何Java使用此设置运行,如果不存在安全隐患,这是不希望的。

答案很长:您可以将端口80上的连接重定向到可以以普通用户身份打开的其他端口。

以root身份运行:

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

由于回送设备(例如localhost)不使用预路由规则,因此,如果您需要使用localhost等,请同时添加此规则( (感谢@Francesco )):

# iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080

注意:上面的解决方案并不非常适合多用户系统,因为任何用户都可以打开端口8080(或您决定使用的任何其他高端口),从而拦截流量。 (贷方 (CesarB )。

编辑:根据评论问题-删除上述规则:

# iptables -t nat --line-numbers -n -L

这将输出类似:

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 redir ports 8088
2    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 redir ports 8080

您感兴趣的规则是nr。 2,所以删除它:

# iptables -t nat -D PREROUTING 2
366
Sunny

使用 authbind

它甚至可以与Java一起使用,如果您启用Java的仅IPv4的堆栈。我使用:

authbind --deep $Java_HOME/bin/Java -Djava.net.preferIPv4Stack=true …
81
geocar

如果您的系统支持,则可以使用功能。查看人员功能,您需要的是CAP_NET_BIND_SERVICE。

在较新的Debian/Ubuntu上,您可以运行:

Sudo apt-get install libcap2-bin 
Sudo setcap 'cap_net_bind_service=+ep' /path/to/program
60
Otto Kekäläinen

另一个解决方案是使您的应用程序setuid可以与端口80绑定。以root身份执行以下操作

chown root ./myapp
chmod +S ./myapp

请记住,除非绝对正确,否则这样做将使您面临潜在的安全漏洞,因为您的应用程序将与网络进行通信,并且将以完全根特权运行。如果采用此解决方案,则应查看Apache或Lighttpd或类似内容的源代码,在这些源代码中,它们使用root特权打开端口,但随后立即放弃这些priv,并“成为”特权较低的用户,以便劫机者无法接管您的整个计算机。

更新:从 此问题 中可以看出,自2.6.24起,Linux内核似乎具有一项新功能,可让您将可执行文件(当然不是脚本)标记为具有“ CAP_NET_BIND_SERVICE”功能。如果您安装了debian软件包“ libcap2-bin”,则可以通过发出以下命令来实现

setcap 'cap_net_bind_service=+ep' /path/to/program
42
Paul Tomblin

我只是在前面使用Nginx。它也可以在本地主机上运行。

  • apt-get install nginx

.. 要么 ..

  • pkg_add -r nginx

..或适合您的操作系统的内容。

如果在localhost上运行,则在nginx.conf中需要的全部是:

服务器{
侦听80; 
 server_name some.domain.org; 
 location/{
 proxy_set_header Host $ Host; 
 proxy_set_header X-Real-IP $ remote_addr; 
 proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; 
 proxy_pass http://127.0.0.1:8081;
} 
 } 
41
CosmicB

Sunny和CesarB提出的方法:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

可以正常工作,但是有一个小缺点-它不会阻止用户直接连接到端口8080而不是80。

当这可能是一个问题时,请考虑以下情形。

假设我们有一个服务器,该服务器在端口8080上接受HTTP连接,并在端口8181上接受HTTPS连接。

我们使用iptables建立以下重定向:

80  ---> 8080
443 ---> 8181

现在,假设我们的服务器决定将用户从HTTP页面重定向到HTTPS页面。除非我们仔细重写响应,否则它将重定向到https://Host:8181/。至此,我们被搞砸了:

  • 有些用户会将https://Host:8181/ URL,我们将需要维护此URL,以免破坏其书签。
  • 其他用户将无法连接,因为他们的代理服务器不支持非标准SSL端口。

我使用以下方法:

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8181
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -m mark --mark 1 -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8181 -m mark --mark 1 -j ACCEPT

结合INPUT链上的默认REJECT规则,此方法可防止用户直接连接到端口8080、8181

36
Misha

传统上,在Unix上,只有root可以绑定到低端口(<1024)。

解决此问题的最简单方法是在high端口(例如8080)上运行服务器,并使用简单的iptables规则将连接从端口80转发到端口8080。请注意,低端端口会失去额外的保护;您计算机上的任何用户都可以绑定到端口8080。

29
CesarB

如果您的系统支持,则可以使用功能。见man capabilities,您需要的是CAP_NET_BIND_SERVICE。不,我从来没有亲自使用过它们,也不知道它们是否真的起作用:-)

23
WMR

在应用程序服务器之前使用反向代理(nginx,Apache + mod_proxy)或缓存反向代理(Squid,Varnish)!

使用反向代理,您可以实现很多有趣的事情,例如:

  • 负载均衡
  • 在用户收到异常错误页面的情况下重新启动应用程序服务器
  • 利用缓存加快处理速度
  • 通常使用反向代理而不是应用程序服务器进行的细粒度设置
12
Giovanni Toraldo

您可以使用redir程序:

Sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
6
user340994

sunny的答案是正确的,但是您可能会遇到其他问题,因为回送接口不使用PREROUTING表,

因此要添加的iptables规则有两个:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
4
Francesco

使用Sudo。

配置Sudo,以便普通用户可以运行适当的命令:

/etc/init.d/httpd start

要么

apachectl stop

要么

/usr/local/Apache2/apachectl restart

要么

/myapp/myappbin start

(或者您用于启动/停止特定Web服务器/应用程序的任何其他命令/脚本)

4
Not Now

使用Linux,您还有另外两个选择:

Linux内核的两个扩展都允许在非常精细的级别上授予访问权限。这将允许您授予此过程以打开端口80,但它不会继承任何其他根权限。

据我所知,grsecurity使用起来更简单,但SELinux更安全。

3
Aaron Digulla

我认为最好的解决方案是引导您的应用程序,一旦其端口绑定,它应该通过切换到另一个用户来放弃特权。

2
Anxy Dicy

一种解决方案是使用iptables对端口80的数据包执行PAT。例如,可以使用iptables将数据包路由到本地端口8080。确保将传出数据包调整回端口80。

以我的经验,由于安全问题,Linux的细粒度权限功能没有编译到标准内核中。

2
Darron

如果您尝试这样做,以便用户运行的命令可以使用端口80,那么您唯一的解决方案是iptables技巧或将可执行的setuid-to-root设置。

像Apache这样的方式(它绑定到端口80,但是以除root以外的身份运行)的方式是:以root身份运行,绑定到端口,然后在端口之后将进程的所有权更改为非特权用户设置好了。如果您正在编写的应用程序可以通过根目录run进行设置,则可以在设置端口后将其更改为非私有用户。但是,如果这仅是让普通用户从命令行运行,则必须使用其他解决方案之一。

2
rjray

当我不想以root用户身份运行各种Web服务应用程序(Python脚本,Tomcat引擎等)时,通常会在它们前面配置一个Apache Web服务器。 Apache监听端口80,而Tomcat监听8080。

在Apache:s的配置中:

ProxyPass /webapp http://localhost:8080/webapp
ProxyPassReverse /webapp http://localhost:8080/webapp

有关更多信息,请参见mod-proxy文档: http://httpd.Apache.org/docs/2.2/mod/mod_proxy.html

2
Anders Westrup

某些主机系统不允许使用NAT模块,在这种情况下,'iptables'无法解决问题。

Xinetd怎么样?

就我而言(ubuntu 10.04)

# apt-get install xinetd
# touch /etc/xinetd.d/my_redirect
# vim /etc/xinetd.d/my_redirect

粘贴配置:

service my_redirector_80
{
 disable = no
 socket_type = stream
 protocol = tcp
 user = root
 wait = no
 port = 80
 redirect = localhost 8080
 type = UNLISTED
}

然后:

# service xinetd restart

http://docs.codehaus.org/display/JETTY/port8 解释得更好。

1
Thomas

顺便说一句,FreeBSD和Solaris(有人记得那个一个?)使您无需特权升级(即使用程序切换到根目录)即可执行此操作(绑定到低端端口)。由于您已指定Linux,因此我只是将其发布给其他可能会发现此问题的人。

0
Daniel C. Sobral