我已经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以避免打乱他们的书签。 我使用以下方法:
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,例如:
你可以使用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
顺便说一句,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,如果您想确保这个限制再也不会让您感到困扰,请编译内核。