在我的开发盒上有这种限制是非常令人讨厌的,因为除了我之外再也没有其他用户了。

我知道一些标准的变通办法,但没有一个能完全满足我的要求:

authbind (Debian测试中的版本,1.0,仅支持IPv4) 使用iptables REDIRECT目标将低端口重定向到高端口(iptables的IPv6版本ip6tables尚未实现“nat”表) sudo(作为根是我试图避免的) SELinux(或类似的)。(这只是我的开发框,我不想引入很多额外的复杂性。)

是否有一些简单的sysctl变量允许非根进程绑定到Linux上的“特权”端口(端口小于1024),或者我只是运气不好?

编辑:在某些情况下,您可以使用功能来做到这一点。


当前回答

文件功能并不理想,因为它们可能在包更新后失效。

恕我直言,理想的解决方案应该是能够创建具有可继承CAP_NET_BIND_SERVICE集的shell。

这里有一个有点复杂的方法:

sg $DAEMONUSER "capsh --keep=1 --uid=`id -u $DAEMONUSER` \
     --caps='cap_net_bind_service+pei' -- \
     YOUR_COMMAND_GOES_HERE"

capsh实用程序可以在Debian/Ubuntu发行版的libcap2-bin包中找到。事情是这样的:

sg将生效的组ID修改为守护用户的组ID。这是必要的,因为capsh会使GID保持不变,而我们肯定不想要它。 设置位“保持UID更改的能力”。 修改UID为$DAEMONUSER 删除所有的大写(此时所有的大写仍然存在,因为——keep=1),除了可继承的cap_net_bind_service 执行命令(“——”是分隔符)

结果是一个具有指定用户和组以及cap_net_bind_service特权的进程。

例如,ejabberd启动脚本中的一行:

sg $EJABBERDUSER "capsh --keep=1 --uid=`id -u $EJABBERDUSER` --caps='cap_net_bind_service+pei' -- $EJABBERD --noshell -detached"

其他回答

由于OP只是开发/测试,不那么圆滑的解决方案可能会有帮助:

可以在脚本解释器上使用Setcap来为脚本授予功能。如果全局解释器二进制文件上的setcaps是不可接受的,那么就对二进制文件做一个本地副本(任何用户都可以),并在这个副本上获取root到setcap。Python2(至少)使用脚本开发树中的解释器的本地副本正常工作。不需要suid,因此根用户可以控制用户可以访问哪些功能。

如果你需要跟踪解释器的系统范围的更新,可以使用下面这样的shell脚本来运行你的脚本:

#!/bin/sh
#
#  Watch for updates to the Python2 interpreter

PRG=python_net_raw
PRG_ORIG=/usr/bin/python2.7

cmp $PRG_ORIG $PRG || {
    echo ""
    echo "***** $PRG_ORIG has been updated *****"
    echo "Run the following commands to refresh $PRG:"
    echo ""
    echo "    $ cp $PRG_ORIG $PRG"
    echo "    # setcap cap_net_raw+ep $PRG"
    echo ""
    exit
}

./$PRG $*

你可以设置一个本地SSH隧道,例如,如果你想要端口80击中你的应用绑定到3000:

sudo ssh $USERNAME@localhost -L 80:localhost:3000 -N

这样做的优点是可以使用脚本服务器,而且非常简单。

使用privbind实用程序:它允许非特权应用程序绑定到预留端口。

2017年更新:

使用authbind

免责声明(2021年更新):请注意,authbind通过LD_PRELOAD工作,这只在你的程序使用libc时使用,如果你的程序用GO编译,或任何其他避免使用c的编译器,这是(或可能)不是情况。如果你使用GO,为受保护的端口范围设置内核参数,请参阅post底部。< / EndUpdate > Authbind比CAP_NET_BIND_SERVICE或自定义内核好得多。

CAP_NET_BIND_SERVICE授予二进制文件信任,但不提供 控制每个端口的访问。 Authbind向对象授予信任 用户/组,并提供对每个端口访问的控制 支持IPv4和IPv6 (IPv6支持已添加到后期)。

安装:apt-get Install authbind 为所有用户和组配置访问相关端口,例如80和443: 触摸/etc/authbind/byport/80 触摸/etc/authbind/byport/443 Sudo chmod 777 /etc/authbind/byport/80 Sudo chmod 777 /etc/authbind/byport/443 .使用实例 通过authbind执行命令 (可选地指定——deep或其他参数,参见man authbind): Authbind——deep /path/to/binary命令行参数 如。 authbind——deep java -jar SomeServer.jar


作为Joshua关于破解内核的绝妙建议(=不推荐,除非你知道自己在做什么)的后续:

我首先把它贴在这里。

简单。对于普通内核或旧内核,则不需要。 正如其他人指出的那样,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程序都可以绑定系统端口。 对于mono/. 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, 如果您想确保这个限制不再困扰您,请编译内核。


sysctl方法

注意: 到目前为止,不再需要更新内核。 你现在可以设置

sysctl net.ipv4.ip_unprivileged_port_start=80

还是坚持

sysctl -w net.ipv4.ip_unprivileged_port_start=80.

如果产生错误,只需用nano编辑/etc/sysctl.conf,并在那里设置参数,以便在重启期间保持不变。

或者通过procfs

echo 80 | sudo tee /proc/sys/net/ipv4/ip_unprivileged_port_start

标准方法是将它们设置为“setuid”,以便它们以根用户身份启动,然后在它们绑定到端口但开始接受到该端口的连接之前丢弃根用户特权。您可以在Apache和INN的源代码中看到这样的好例子。我听说莱特特警局是另一个很好的例子。

另一个例子是Postfix,它使用多个通过管道通信的守护进程,其中只有一两个守护进程(除了接受或发出字节外几乎不做任何事情)以根身份运行,其余的守护进程以较低的权限运行。