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

Dee*_*tal 365 linux

我在谷歌上搜索了很长一段时间的解决方案,但找不到答案。

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

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

我认为禁用此安全机制以便所有用户都可以使用端口 80 或为当前用户分配访问端口 80 所需的权限应该足够简单。

Sun*_*nny 401

简短的回答:你不能。低于 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
Run Code Online (Sandbox Code Playgroud)

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

# iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
Run Code Online (Sandbox Code Playgroud)

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

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

# iptables -t nat --line-numbers -n -L
Run Code Online (Sandbox Code Playgroud)

这将输出如下内容:

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
Run Code Online (Sandbox Code Playgroud)

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

# iptables -t nat -D PREROUTING 2
Run Code Online (Sandbox Code Playgroud)

  • @Sunny:投票不是为了西方最快的枪,而是为了最好的回应。到目前为止,你是最好的(我只提到了 iptables;你实际上提供了完整的命令行)。我唯一没有的就是关于其他用户也可以绑定到端口 8080 的警告。 (18认同)
  • 感谢您的回答...每当我重新启动 Ubuntu 时,此规则就会消失,我必须再次运行它。有没有办法永远保存它? (4认同)
  • @Coderji:查看社区文档中的“保存”部分:https://help.ubuntu.com/community/IptablesHowTo (4认同)
  • 请注意,这不适用于 IPv6。 (3认同)
  • 任何人都可以解释我以后如何在需要时删除此规则?运行它后,它可以工作,但它显然不是“规则”,因为当我执行 `sudo iptables --list` 时它没有出现。我知道 iptables 是什么和做什么,但在此之前我从未真正使用过它。 (3认同)

geo*_*car 86

使用身份验证

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

authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您必须配置 `authbind` 才能真正允许这种情况发生。从手册页: *“/etc/authbind/byport/port 被测试。如果调用用户可以访问该文件以执行,根据 access(2),则授权绑定到端口。”*,例如对于端口 80,`sudo touch /etc/authbind/byport/80 ; 须藤 chmod 777 /etc/authbind/byport/80`。`authbind` 的初始安装通常没有任何预配置的授权。 (12认同)
  • 哦,nonononononono,永远不要 chmod 777 任何东西! (6认同)
  • 如果服务器是 Tomcat,您可以通过在 /etc/default/tomcat6 中设置 `AUTHBIND=yes` 来自动使用 authbind (4认同)
  • @JasonC 而不是 `777` 文件,将第二个命令分成两个: `sudo chgrp 80s /etc/authbind/byport/80 ; sudo chmod 550 /etc/authbind/byport/80` 其中`80s` 是您自己的用户组,或者您创建的组,以便其他(系统)用户可以绑定到该端口。没有理由允许所有人自由绑定,也没有理由允许他们对该文件进行写访问。 (2认同)

小智 75

如果您的系统支持它,您可以使用功能。参见 man 功能,您需要的是 CAP_NET_BIND_SERVICE。

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

sudo apt-get install libcap2-bin 
sudo setcap 'cap_net_bind_service=+ep' /path/to/program
Run Code Online (Sandbox Code Playgroud)

  • 这是正确和最有效的答案,所有其他答案都会导致性能下降或只是不确定/不安全。 (8认同)
  • 这个。我想知道为什么这个答案没有更多的赞成票。恕我直言,比 iptables 选项容易得多。 (6认同)

Pau*_*lin 46

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

chown root ./myapp
chmod +S ./myapp
Run Code Online (Sandbox Code Playgroud)

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

更新:正如在这个问题中所看到的,似乎自 2.6.24 以来的 Linux 内核具有一项新功能,允许您将可执行文件(当然不是脚本)标记为具有“ CAP_NET_BIND_SERVICE”功能。如果你安装了 debian 包“libcap2-bin”,你可以通过发出命令来做到这一点

setcap 'cap_net_bind_service=+ep' /path/to/program
Run Code Online (Sandbox Code Playgroud)

  • 这是危险的。这意味着任何请求都将以 root 身份运行。出于某种原因,即使是 apache 也以 root 身份启动绑定,然后将权限丢弃给另一个用户。 (17认同)
  • Paul:iptables 没有那么危险,因为即使应用程序被入侵,它也不会暴露系统受到攻击,至少不会以 root 权限。以 root 身份运行应用程序是另一回事。 (9认同)
  • 这与以 root 身份运行相同,除非应用程序知道如何删除权限。 (7认同)

小智 46

我在前面简单地使用了Nginx。它也可以在本地主机上运行。

  • apt-get install nginx

.. 或者 ..

  • pkg_add -r nginx

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

如果在 localhost 上运行,则您需要在 nginx.conf 中的所有内容是:

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


小智 37

Sunny 和 CesarB 提出的方法:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
Run Code Online (Sandbox Code Playgroud)

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

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

假设我们有一个服务器,它接受端口 8080 上的 HTTP 连接和端口 8181 上的 HTTPS 连接。

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

80  ---> 8080
443 ---> 8181
Run Code Online (Sandbox Code Playgroud)

现在,假设我们的服务器决定将用户从 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
Run Code Online (Sandbox Code Playgroud)

结合 INPUT 链上的默认拒绝规则,这种方法可以防止用户直接连接到端口 8080、8181

  • 这很好,但为什么不将守护进程绑定到 localhost:8080 而不是 0.0.0.0:8080 呢?我想这样做,但我需要 iptables。 (2认同)

Ces*_*arB 30

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

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


小智 23

如果您的系统支持它,您可以使用功能。看man capabilities,你需要的就是CAP_NET_BIND_SERVICE。不,我自己从未使用过它们,我不知道它们是否真的有效:-)


Gio*_*ldo 12

在应用服务器前使用反向代理(nginx、apache+mod_proxy)或缓存反向代理(Squid、Varnish)!

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

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


小智 7

您可以使用 redir 程序:

sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
Run Code Online (Sandbox Code Playgroud)


小智 5

阳光明媚的答案是正确的,但您可能会面临其他问题,因为环回接口不使用 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
Run Code Online (Sandbox Code Playgroud)


小智 2

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

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