我在Ubuntu Linux上,并且想在端口80上运行服务器,但是由于Ubuntu的安全性机制,出现以下错误:
java .net.BindException:权限被拒绝:80
我认为应该很简单,要么禁用此安全机制,以便端口80对所有用户可用,要么将必需的特权分配给当前用户访问端口80。
#1 楼
简短答案:您不能。低于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
您感兴趣的规则是nr。 2,因此将其删除:
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
评论
@Sunny:投票不是为西方最快的枪支,而是为了获得最佳反应。到目前为止,您最好的(我只提到了iptables;您实际上提供了完整的命令行)。我唯一没有的是关于其他用户也能够绑定到端口8080的警告。
– CesarB
08年11月10日14:45
请注意,这不适用于IPv6。
–伊曼纽尔·布尔格(Emmanuel Bourg)
2012年4月2日,12:12
任何人都可以解释一下以后如何删除此规则?运行它之后,它可以工作,但是它显然不是“规则”,因为当我执行sudo iptables --list时它不会显示。我知道iptables是什么,做什么,但在此之前我从未真正使用过它。
–编码器
2012年4月2日在18:31
感谢您的回答...每当我重新启动Ubuntu时,该规则就会消失,我必须再次运行它。有没有办法永远保存它?
– Coderji
2014年9月18日在8:16
@Coderji:检查社区文档中的“保存”部分:help.ubuntu.com/community/IptablesHowTo
–晴天
2014年9月18日在12:54
#2 楼
使用authbind。如果启用Java的仅IPv4堆栈,它甚至可以与Java一起使用。我使用:
authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …
评论
如果服务器是Tomcat,则可以通过在/ etc / default / tomcat6中设置AUTHBIND = yes来自动使用authbind
–伊曼纽尔·布尔格(Emmanuel Bourg)
2012年4月2日,12:16
我无法在具有默认Java包的Ubuntu服务器上使用它...
–阿什利
2012年6月20日17:17
请注意,您必须将authbind配置为实际允许这种情况发生。在手册页中:“已测试/ etc / authbind / byport / port。如果根据access(2),调用方用户可以访问此文件以执行该文件,则授权绑定到该端口。”对于端口80,sudo touch / etc / authbind / byport / 80;须藤chmod 777 / etc / authbind / byport / 80。初始安装的authbind通常没有任何预配置的授权。
–杰森C
2015年3月21日在20:57
哦,nonononononono,永远不要chmod 777!
–约翰内斯
2015年9月8日在11:45
@JasonC而不是777文件,将第二个命令分成两个:sudo chgrp 80s / etc / authbind / byport / 80; sudo chmod 550 / etc / authbind / byport / 80其中80s是您自己的用户组,或者是您创建的用户组,以便其他(系统)用户可以绑定到该端口。没有理由不允许所有的绑定,也没有给予他们对该文件的写访问权。
–沃尔夫
8月5日0:46
#3 楼
如果您的系统支持,则可以使用功能。查看人员功能,您需要的是CAP_NET_BIND_SERVICE。在较新的Debian / Ubuntu中,您可以运行:
sudo apt-get install libcap2-bin
sudo setcap 'cap_net_bind_service=+ep' /path/to/program
评论
这适用于nodejs:setcap'cap_net_bind_service = + ep'/ usr / bin / nodejs
–JasonS
15年4月4日在22:20
这个。我不知道为什么这个答案没有更多支持。比iptables选项imho容易得多。
–Dominik R
16年1月4日,下午1:54
这是正确且最有效的答案,所有其他答案都会导致性能下降或只是不稳定/不安全。
–OneOfOne
16年1月1日在12:33
完美提提您:您需要在setcap行之后启动该程序(不会影响正在运行的程序)。
– Stefan Reich
19/12/7在17:01
应用此解决方案后,Java拒绝运行,并显示错误“加载共享库时出错:libjli.so:无法打开共享库文件:没有这样的文件或目录”。我已通过应用此处描述的解决方案bugs.java.com/bugdatabase/view_bug.do?bug_id=7157699修复了该问题
– Deniz
10月6日22:11
#4 楼
另一个解决方案是使您的应用程序setuid可以与端口80绑定。以root身份执行以下操作chown root ./myapp
chmod +S ./myapp
请记住,除非已完成此操作绝对正确,这将使您面临潜在的安全漏洞,因为您的应用程序将与网络通信,并且将以完全root权限运行。如果采用此解决方案,则应查看Apache或Lighttpd或类似内容的源代码,它们在其中使用root特权打开端口,但随后立即放弃这些priv并“成为”特权较低的用户,以便劫机者无法接管您的整个计算机。一个脚本,当然)具有“
CAP_NET_BIND_SERVICE
”功能。如果安装了debian软件包“ libcap2-bin”,则可以通过发出命令setcap 'cap_net_bind_service=+ep' /path/to/program
来做到这一点。
评论
除非应用程序知道如何删除特权,否则这与以root用户身份运行是相同的。
– CesarB
08年11月10日在14:48
这很危险。这意味着任何请求都将以root用户身份运行。这是有原因的,即使apache也以root用户身份开始绑定,然后将特权放弃给另一个用户。
–晴天
08年10月10日在14:49
Paul:iptables并不是那么危险,因为即使该应用程序被盗用,它也不会使系统遭受攻击,至少没有root特权。以root用户身份运行该应用程序是另一回事。
–晴天
08年10月10日在14:55
正如CesarB所说,iptables的危险仅在于它是一个多用户系统,因为任何人都可以绑定到8080,并拦截流量。
–晴天
08年11月10日14:57
大声笑,爱如何接受答案有-15
–埃文·特兰(Evan Teran)
08年12月17日在18:53
#5 楼
我只是在前面使用Nginx。它也可以在本地主机上运行。apt-get install nginx
..或..
pkg_add -r nginx
..或适合您的操作系统的任何内容。
如果在localhost上运行,则nginx.conf中所需的全部是:
server { listen 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; } }
评论
我真的很喜欢这个解决方案。
– thomasfedb
2012年12月6日在16:05
这是JFrog本身建议的解决方案之一(jfrog.com/confluence/display/RTF/nginx)
–stolsvik
2014年1月1日23:27
#6 楼
Sunny和CesarB提出的方法:iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
可以很好地工作,但是它有一个小的缺点-它不会阻止用户直接连接到8080端口而不是80端口。 br />
当这可能是一个问题时,请考虑以下情形。
假设我们有一台服务器,它接受端口8080上的HTTP连接和端口8181上的HTTPS连接。
我们使用iptables建立以下重定向:
<现在,让我们假设服务器决定将用户从HTTP页面重定向到HTTPS页面。除非我们仔细重写响应,否则它将重定向到
https://host:8181/
。这时,我们被搞砸了:某些用户会将
https://host:8181/
URL添加为书签,我们将需要维护此URL以避免破坏其书签。 其他用户将无法连接,因为他们的代理服务器不支持非标准SSL端口。
我使用以下方法:
80 ---> 8080
443 ---> 8181
结合INPUT链上的默认REJECT规则,此方法可防止用户直接连接到端口8080、8181
评论
很好,但是为什么不将守护程序绑定到localhost:8080而不是0.0.0.0:8080呢?我想这样做,但是我需要iptables。
–阿马拉
2011-12-15 17:20
它的工作原理,真的很酷。
– xtian
2015年10月8日在20:26
#7 楼
传统上,在Unix上,只有root才能绑定到低端口(<1024)。解决此问题的最简单方法是在高端口(例如8080)上运行服务器并使用简单的端口。 iptables规则将连接从端口80转发到端口8080。请注意,这样做会使低端口失去额外的保护;您计算机上的任何用户都可以绑定到端口8080。#8 楼
如果您的系统支持,则可以使用功能。请参阅man capabilities
,您需要的是CAP_NET_BIND_SERVICE
。不,我从来没有亲自使用过它们,也不知道它们是否真的有用:-) 评论
它们确实起作用,我以普通用户身份使用CAP_NET_RAW运行tcpdump之类的工具。
–贾斯汀
2010-2-15在0:32
#9 楼
在应用程序服务器前使用反向代理(nginx,apache + mod_proxy)或缓存反向代理(Squid,Varnish)!使用反向代理,您可以实现很多有趣的事情,例如:负载平衡
在出现错误页面的用户中重新启动应用服务器
通过缓存加快处理速度
您通常使用的细粒度设置使用反向代理而不是应用程序服务器
#10 楼
您可以使用redir程序:sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
#11 楼
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
#12 楼
使用sudo。配置sudo,以便普通用户可以运行适当的命令:
/etc/init.d/httpd start
或
apachectl stop
或
/usr/local/apache2/apachectl restart
/myapp/myappbin start
(或其他任何命令/您用于启动/停止特定Web服务器/应用程序的脚本)
评论
这具有相同的问题-以root身份运行服务是一种不良做法。
–凯文·潘科(Kevin Panko)
09年9月9日在18:44
#13 楼
使用Linux,您还有另外两个选择:您可以尝试SELinux(http://www.nsa.gov/selinux/)
您可以尝试grsecurity(http ://www.grsecurity.net/)
Linux内核的两个扩展都允许在非常精细的级别上授予访问权限。这将允许您授予此过程以打开端口80,但它不会继承任何其他根权限。
据我所知,grsecurity使用起来更简单,但SELinux却很简单。更安全。
#14 楼
一种解决方案是使用iptables对端口80的数据包执行PAT。例如,您可以使用iptables将数据包路由到本地端口8080。确保将传出数据包调整回端口80。根据我的经验,由于安全问题,Linux的细粒度权限功能没有编译到标准内核中。#15 楼
如果您试图这样做,以便用户运行的命令可以使用端口80,那么您唯一的解决方案就是iptables技巧或将可执行的setuid-to-root设置。类似Apache的方式这样做(它绑定到端口80,但以root身份以外的其他人身份运行)将以root身份运行,绑定到端口,然后在设置端口后将进程的所有权更改为非特权用户。如果您正在编写的应用程序可以由root用户运行,则可以在设置端口后将其更改为非私有用户。但是,如果这仅是让普通用户从命令行运行,则必须使用其他解决方案之一。
#16 楼
当我不想以root用户身份运行各种Web服务应用程序(Python脚本,tomcat引擎等)时,通常会在它们前面配置一个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
评论
该解决方案的缺点是Tomcat日志中的传入IP丢失。
–伊曼纽尔·布尔格(Emmanuel Bourg)
2012年4月2日,12:22
#17 楼
我认为最好的解决方案是引导您的应用程序,一旦其端口绑定,它应通过切换到另一个用户来放弃特权。#18 楼
某些主机系统不允许使用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/port80解释得更好。
评论
这基本上等效于将反向代理放在服务器前面,但是与理解HTTP协议并可以添加有用的标头(例如X-Forwarded-For)的专用解决方案(例如HAproxy,Pound或Varnish)相比,效率较低。
–伊曼纽尔·布尔格(Emmanuel Bourg)
2012年4月2日在21:49
目前,这是我首选的解决方案,因为从头开始运行它比通过iptables转发要花费更少的工作。
– h22
4月17日7:43
#19 楼
顺便说一句,FreeBSD和Solaris(有人记得吗?)允许您执行此操作(绑定到低端端口)而无需特权升级(即,使用程序切换到root用户)。由于您已指定Linux,因此我只是将其发布给其他可能会发现此问题的人。评论
yaws.hyber.org/privbind.yaws上的详细信息在UN * X上发现的一个常见缺陷是限制,只有root才能绑定到低于1024的端口。很多钱浪费在解决方法上-经常-结果是安全漏洞…FreeBSD $ sysctl net.inet.ip.portrange.reservedhigh = 0 Solaris $ / usr / sbin / usermod -K defaultpriv = basic,net_privaddr erlang; grep erlang / etc / user_attr Linux $ setcap'cap_net_bind_service = + ep'/usr/lib/erlang/erts-5.7.4/bin/beam Debian $ echo'net.ipv4.ip_unprivileged_port_start = 0'> /etc/sysctl.d /50-unprivileged-ports.conf && sysctl --system
– devon
3月14日,11:24
#20 楼
死灵法师。简单。使用普通或旧内核,则不需要。
正如其他人指出的那样,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程序都可以绑定系统端口。 .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。
已经足够了。
编译内核并安装。
重新启动。
完成-愚蠢的限制已消失,它也适用于脚本。
以下是编译内核的方法:
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), e.g. 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;如果要保护内核,请编译内核确保此限制永远不会再打扰您。
评论
有人可以解释一下反对票吗?内核编译不起作用?还是仅仅是因为之后,您不能再从普通存储库中进行内核升级了?
–四进制
2015年9月1日9:35
我尝试了此解决方案(sudo setcap cap_net_bind_service = + ep / path-to-java / java),但在加载共享库时总是出现java:错误:libjli.so:无法打开共享对象文件:如果java有没有这样的文件或目录瓶盖套。另请参见unix.stackexchange.com/a/16670/55508的第一部分
–丹尼尔·奥尔德(Daniel Alder)
16-3-2在16:11
通过将
–丹尼尔·奥尔德(Daniel Alder)
16-3-2在16:25
评论
在没有特权的另一个端口上运行服务器有什么问题?您正在考虑禁用安全机制这样严酷的事情,而没有提供至少一个非常严肃的理由来在该端口上运行服务器。服务器是否已硬编码绑定到端口80?如果是这样,请将其丢弃。使用低于1024的端口的普通用户的可能副本
你不能低于1024的端口具有特权,并且只有root可以打开它们上的侦听套接字。适当的操作是在打开权限后删除权限。
“匿名”-世界各地的用户都经过训练可以在某些港口寻找某些服务。在某些情况下,它是标准化的。例如,端口80上的HTTP和端口443上的HTTPS。很难改变世界的用户和标准。
@FalconMomot如果低于1024的端口具有特权,那么Apache服务器为什么不要求输入密码来获得对端口80的root特权,它们怎么做呢?我认为发问者想知道如何以这种方式做事(无论从技术上讲它是否被用作root用户)。迪帕克·米塔尔(Deepak Mittal),如果我错了,请随时告诉我。