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

我已经search了一段时间,但找不到它。

我在Ubuntu Linux上,并希望在端口80上运行服务器,但由于Ubuntu的安全机制,我得到以下错误:

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

我认为它应该很简单,要么禁用这个安全机制,以便所有用户都可以使用端口80,或者为当前用户分配所需的权限来访问端口80。

简短的回答:你不能。 低于1024的端口只能由root打开。 按照评论 – 你可以使用CAP_NET_BIND_SERVICE ,但是这种方法应用于java bin,将使得任何java程序都可以用这个设置来运行,如果没有安全风险的话,湿润可能是不可取的。

漫长的回答:您可以将端口80上的连接redirect到您可以以普通用户身份打开的其他端口。

以root身份运行:

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

由于环回设备(如localhost)不使用预路由规则,所以如果您需要使用本地主机等,请添加此规则( 谢谢@Francesco ):

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

注意:上述解决scheme适合多用户系统,因为任何用户都可以打开端口8080(或您决定使用的任何其他高端口),从而拦截stream量。 (学分塞萨尔B )。

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

 # 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 

使用authbind 。

如果启用Java的仅IPv4栈,它甚至可以与Java协同工作。 我用:

 authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true … 

另一个解决scheme是使您的应用程序setuid,以便它可以绑定到端口80.作为根,执行以下操作

 chown root ./myapp chmod +S ./myapp 

请记住,这样做除非完全正确,否则会使您面临潜在的安全漏洞,因为您的应用程序将与networking交谈,并且将以完全的root权限运行。 如果你采取这个解决scheme,你应该看看Apache或Lighttpd的源代码或类似的东西,在那里他们使用root权限来打开端口,但是立即放弃这些priv并成为一个较低特权用户,劫机者不能接pipe你的整个电脑。

更新:从这个问题可以看出,自2.6.24版本以来,Linux内核似乎具有一种新的function,允许您将可执行文件(当然不是脚本)标记为具有“ CAP_NET_BIND_SERVICE ”function。 如果你安装了debian软件包“libcap2-bin”,你可以通过发出这个命令来完成

 setcap 'cap_net_bind_service=+ep' /path/to/program 

如果你的系统支持它,你可以使用function。 看到人的能力,你需要的就是CAP_NET_BIND_SERVICE。

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

 sudo apt-get install libcap2-bin sudo setcap 'cap_net_bind_service=+ep' /path/to/program 

Sunny和CesarB提出的方法:

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

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

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

比方说,我们有一台服务器,它接受端口8080上的HTTP连接和端口8181上的HTTPS连接。

我们使用iptables来build立以下redirect:

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

现在,假设我们的服务器决定将用户从HTTP页面redirect到HTTPS页面。 除非我们仔细地重写响应,否则会redirect到https://host:8181/ 。 在这一点上,我们搞砸了:

  • 有些用户会将https://host:8181/ URLjoin书签,我们需要维护此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

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

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

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

  • apt-get install nginx

.. 要么 ..

  • pkg_add -r nginx

..或什么适合您的操作系统。

所有你需要在nginx.conf,如果在本地主机上运行,​​是:

服务器{
        听80;
         server_name some.domain.org;
        位置 / {
             proxy_set_header主机$主机;
             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;
         }
 }

如果你的系统支持它,你可以使用function。 看到man capabilities ,你需要的就是CAP_NET_BIND_SERVICE 。 不,我从来没有用过他们,我不知道他们是否真的工作:-)

在应用程序服务器前面使用反向代理(nginx,apache + mod_proxy)或caching反向代理(Squid,Varnish)!

使用反向代理,您可以实现许多有趣的function,例如:

  • 负载均衡
  • 重新启动您的应用程序服务器与用户收到一个奇特的错误页面
  • 加快与caching的东西
  • 通常使用反向代理而不是应用程序服务器的细粒度设置

你可以使用redir程序:

 sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1 

使用sudo。

configurationsudo,以便常规用户可以运行适当的命令:

 /etc/init.d/httpd start 

要么

 apachectl stop 

要么

 /usr/local/apache2/apachectl restart 

要么

 /myapp/myappbin start 

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

有了Linux,你还有其他两个select:

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

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

阳光的答案是正确的,但是你可能会面临额外的问题,因为回送接口不使用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 

一种解决scheme是使用iptables对端口80的数据包执行PAT。例如,可以使用此命令将数据包路由到本地端口8080。 请确保将输出数据包重新调回到端口80。

根据我的经验,由于安全问题,Linux的细粒度权限function并未编译到标准内核中。

如果你正在试图这样做,以便用户运行的命令可以使用端口80,那么你唯一的解决scheme是iptables技巧或设置可执行setuid到根。

像Apache这样的方式(它绑定到端口80,但作为非超级用户运行)是以root身份运行,绑定到端口,然后将该进程的所有权更改为端口后的非特权用户成立。 如果您正在编写的应用程序可以以root身份运行 ,则可以在设置端口后将其更改为非priv用户。 但是,如果这只是一般用户从命令行运行,那么您将不得不使用其他解决scheme之一。

当我有不同的web服务应用程序(python脚本,tomcat引擎,…),我不想以root身份运行,我通常在他们面前configuration一个Apache Web服务器。 Apache监听端口80,而tomcat监听8080。

在apache:s config中:

 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

我认为最好的解决scheme是让你的应用程序很好,一旦有了它的端口,它就应该通过切换到另一个用户来放弃权限。

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

xinetd怎么样?

在我的情况(Ubuntu 10.04)

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

粘贴configuration:

 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/port80解释更好&#x3002;

顺便说一句,FreeBSD和Solaris(任何人都记得那个 ?)让你这样做(绑定到低端口)没有特权升级(即使用程序切换到根)。 既然你指定了Linux,我只是把它作为一个通知给其他人,可能会发现这个问题。

Necromancing。

简单。 使用正常的或旧的内核,你不需要。
正如其他人指出的,iptables可以转发一个端口。
另外也有人指出,CAP_NET_BIND_SERVICE也可以做这个工作。
当然,如果你从脚本启动你的程序,CAP_NET_BIND_SERVICE将会失败,除非你在shell解释器上设置了一个没有意义的上限,你也可以像root一样运行你的服务。
例如对于Java,您必须将其应用于JAVA JVM

 sudo /sbin/setcap 'cap_net_bind_service=ep' /usr/lib/jvm/java-8-openjdk/jre/bin/java 

显然,这意味着任何Java程序都可以绑定系统端口。
Dito单声道/ .NET。

我也很确定xinetd不是最好的想法。
但是既然这两种方法都是黑客行为,为什么不通过解除限制来解除限制呢?
没有人说你必须运行一个正常的内核,所以你可以运行你自己的。

您只需下载最新内核的源代码(或者您现在拥有的相同)。 之后,你去:

 /usr/src/linux-<version_number>/include/net/sock.h: 

在那里你找这条线

 /* Sockets 0-1023 can't be bound to unless you are superuser */ #define PROT_SOCK 1024 

并将其更改为

 #define PROT_SOCK 0 

如果你不想有一个不安全的SSH情况,你可以改变它:#define PROT_SOCK 24

一般来说,我会使用您需要的最低设置,例如http为79,或者在端口25使用SMTP时为24。

这已经是全部了。
编译内核,并安装它。
重启。
完成 – 那个愚蠢的限制是GONE,而且也适用于脚本。

以下是编译内核的方法:

https://help.ubuntu.com/community/Kernel/Compile

 # You can get the kernel-source via package linux-source, no manual download required apt-get install linux-source fakeroot mkdir ~/src cd ~/src tar xjvf /usr/src/linux-source-<version>.tar.bz2 cd linux-source-<version> # Apply the changes to PROT_SOCK define in /include/net/sock.h # Copy the kernel config file you are currently using cp -vi /boot/config-`uname -r` .config # Install ncurses libary, if you want to run menuconfig apt-get install libncurses5 libncurses5-dev # Run menuconfig (optional) make menuconfig # Define the number of threads you wanna use when compiling (should be <number CPU cores> - 1), eg for quad-core export CONCURRENCY_LEVEL=3 # Now compile the custom kernel fakeroot make-kpkg --initrd --append-to-version=custom kernel-image kernel-headers # And wait a long long time cd .. 

简而言之,如果您想保持安全,请使用iptables,如果您想确保这个限制再也不会让您感到困扰,请编译内核。