有没有办法让非根进程绑定到“特权”进程? Linux 上的端口?

发布于 2024-07-10 19:32:44 字数 834 浏览 10 评论 0 原文

当我的开发盒上没有除了我之外的任何用户时,我的开发盒受到这种限制是非常烦人的。

我知道标准解决方法,但它们都没有完全达到我想要的效果:

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

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

编辑:在某些情况下,您可以 使用功能来执行此操作。

It's very annoying to have this limitation on my development box, when there won't ever be any users other than me.

I'm aware of the standard workarounds, but none of them do exactly what I want:

  1. authbind (The version in Debian testing, 1.0, only supports IPv4)
  2. Using the iptables REDIRECT target to redirect a low port to a high port (the "nat" table is not yet implemented for ip6tables, the IPv6 version of iptables)
  3. sudo (Running as root is what I'm trying to avoid)
  4. SELinux (or similar). (This is just my dev box, I don't want to introduce a lot of extra complexity.)

Is there some simple sysctl variable to allow non-root processes to bind to "privileged" ports (ports less than 1024) on Linux, or am I just out of luck?

EDIT: In some cases, you can use capabilities to do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(25

我最亲爱的 2024-07-17 19:32:44

好的,感谢指出功能系统和 CAP_NET_BIND_SERVICE 功能的人。 如果您有最新的内核,确实可以使用它以非 root 身份启动服务但绑定低端口。 简而言之,您可以这样做:

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

然后,此后任何时候执行程序,它都将具有CAP_NET_BIND_SERVICE功能。 setcap 位于 debian 软件包 libcap2-bin 中。

现在需要注意的是:

  1. 您至少需要 2.6.24 内核。
  2. 如果您的文件是脚本,则这将不起作用。 (即使用 #! 行启动解释器)。 在这种情况下,据我所知,您必须将该功能应用于解释器可执行文件本身,这当然是一个安全噩梦,因为任何使用该解释器的程序都将具有该功能。 我无法找到任何干净、简单的方法来解决这个问题。
  3. Linux 将在任何具有提升权限(例如 setcapsuid)的程序上禁用LD_LIBRARY_PATH。 因此,如果您的程序使用自己的.../lib/,您可能需要考虑其他选项,例如端口转发。

资源:

注意:RHEL 首先在 v6 中添加了此内容

Okay, thanks to the people who pointed out the capabilities system and CAP_NET_BIND_SERVICE capability. If you have a recent kernel, it is indeed possible to use this to start a service as non-root but bind low ports. The short answer is that you do:

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

And then anytime program is executed thereafter it will have the CAP_NET_BIND_SERVICE capability. setcap is in the debian package libcap2-bin.

Now for the caveats:

  1. You will need at least a 2.6.24 kernel
  2. This won't work if your file is a script. (i.e. uses a #! line to launch an interpreter). In this case, as far I as understand, you'd have to apply the capability to the interpreter executable itself, which of course is a security nightmare, since any program using that interpreter will have the capability. I wasn't able to find any clean, easy way to work around this problem.
  3. Linux will disable LD_LIBRARY_PATH on any program that has elevated privileges like setcap or suid. So if your program uses its own .../lib/, you might have to look into another option like port forwarding.

Resources:

Note: RHEL first added this in v6.

旧人 2024-07-17 19:32:44

更新2017:

使用authbind

免责声明(2021 年更新): 请注意,authbind 通过 LD_PRELOAD 工作,仅当您的程序使用 libc 时才使用它code>,如果您的程序是使用 GO 或任何其他避免使用 C 的编译器编译的,则情况并非如此(或可能)。如果您使用 go,请为受保护的端口范围设置内核参数,请参阅帖子底部。

AuthbindCAP_NET_BIND_SERVICE 或自定义内核好得多。

  • CAP_NET_BIND_SERVICE 向二进制文件授予信任,但不提供
    控制每个端口的访问。
  • Authbind 授予信任
    用户/组并提供对每个端口访问的控制,以及
    支持 IPv4 和 IPv6(最近已添加 IPv6 支持)。
  1. 安装:apt-get install authbind

  2. 为所有用户和组配置对相关端口的访问,例如 80 和 443:

    <块引用>

    sudo touch /etc/authbind/byport/80
    sudo touch /etc/authbind/byport/443
    须藤 chmod 777 /etc/authbind/byport/80
    sudo chmod 777 /etc/authbind/byport/443

  3. 通过 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 不是最好的主意。
但既然这两种方法都是 hack,为什么不直接通过解除限制来解除限制呢?
没有人说你必须运行普通的内核,所以你可以运行你自己的内核。

您只需下载最新内核的源代码(或您当前拥有的相同内核)。
然后,您转到:

/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

Update 2017:

Use authbind

Disclaimer (update per 2021): Note that authbind works via LD_PRELOAD, which is only used if your program uses libc, which is (or might) not be the case if your program is compiled with GO, or any other compiler that avoids C. If you use go, set the kernel parameter for the protected port range, see bottom of post. </EndUpdate>

Authbind is much better than CAP_NET_BIND_SERVICE or a custom kernel.

  • CAP_NET_BIND_SERVICE grants trust to the binary but provides no
    control over per-port access.
  • Authbind grants trust to the
    user/group and provides control over per-port access, and
    supports both IPv4 and IPv6 (IPv6 support has been added as of late).
  1. Install: apt-get install authbind

  2. Configure access to relevant ports, e.g. 80 and 443 for all users and groups:

    sudo touch /etc/authbind/byport/80
    sudo touch /etc/authbind/byport/443
    sudo chmod 777 /etc/authbind/byport/80
    sudo chmod 777 /etc/authbind/byport/443

  3. Execute your command via authbind
    (optionally specifying --deep or other arguments, see man authbind):

         authbind --deep /path/to/binary command line args
    
     e.g.  
    
         authbind --deep java -jar SomeServer.jar
    

As a follow-up to Joshua's fabulous (=not recommended unless you know what you do) recommendation to hack the kernel:

I've first posted it here.

Simple. With a normal or old kernel, you don't.
As pointed out by others, iptables can forward a port.
As also pointed out by others, CAP_NET_BIND_SERVICE can also do the job.
Of course CAP_NET_BIND_SERVICE will fail if you launch your program from a script, unless you set the cap on the shell interpreter, which is pointless, you could just as well run your service as root...
e.g. for Java, you have to apply it to the JAVA JVM

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

Obviously, that then means any Java program can bind system ports.
Ditto for mono/.NET.

I'm also pretty sure xinetd isn't the best of ideas.
But since both methods are hacks, why not just lift the limit by lifting the restriction ?
Nobody said you have to run a normal kernel, so you can just run your own.

You just download the source for the latest kernel (or the same you currently have).
Afterwards, you go to:

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

There you look for this line

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

and change it to:

#define PROT_SOCK 0

if you don't want to have an insecure ssh situation, you alter it to this:

#define PROT_SOCK 24

Generally, I'd use the lowest setting that you need, e.g. 79 for http, or 24 when using SMTP on port 25.

That's already all.
Compile the kernel, and install it.
Reboot.
Finished - that stupid limit is GONE, and that also works for scripts.

Here's how you compile a kernel:

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 ..

In a nutshell:

  • use iptables if you want to stay secure,
  • compile the kernel if you want to be sure this restriction never bothers you again.

sysctl method

Note:
As of late, updating the kernel is no longer required.
You can now set:

sysctl net.ipv4.ip_unprivileged_port_start=80

Or to persist:

sysctl -w net.ipv4.ip_unprivileged_port_start=80

And if that yields an error, simply edit /etc/sysctl.conf with nano and set the parameter there for persistence across reboots.

or via procfs

echo 80 | sudo tee /proc/sys/net/ipv4/ip_unprivileged_port_start
弄潮 2024-07-17 19:32:44

由于某种原因,没有人提到将 sysctl net.ipv4.ip_unprivileged_port_start 降低到您需要的值。
示例:我们需要将我们的应用程序绑定到 443 端口。

sysctl net.ipv4.ip_unprivileged_port_start=443

有人可能会说,这存在潜在的安全问题:非特权用户现在可以绑定到其他特权端口(444-1024)。
但是你可以使用 iptables 轻松解决这个问题,通过阻止其他端口:

iptables -I INPUT -p tcp --dport 444:1024 -j DROP
iptables -I INPUT -p udp --dport 444:1024 -j DROP

与其他方法的比较。 这种方法:

  • 从某种意义上说(IMO)比设置 CAP_NET_BIND_SERVICE/setuid 更安全,因为应用程序根本不 setuid,甚至部分不设置(功能实际上是这样)。
    例如,要捕获启用功能的应用程序的核心转储,您需要更改 sysctl fs.suid_dumpable (这会导致另一个潜在的安全问题)
    另外,当设置 CAP/suid 时,/proc/PID 目录由 root 用户拥有,因此您的非 root 用户将无法获得正在运行的进程的完整信息/控制权,例如,用户将无法(在常见情况下)通过 /proc/PID/fd/ (netstat -aptn | grep PID) 确定哪些连接属于应用程序。
  • 存在安全缺陷:当您的应用程序(或任何使用端口 443-1024 的应用程序)由于某种原因关闭时,另一个应用程序可能会占用该端口。 但这个问题也可能适用于 CAP/suid(如果你在解释器上设置它,例如 java/nodejs)和 iptables-redirect。 使用systemd-socket方法可以排除这个问题。 使用 authbind 方法仅允许特殊用户绑定。
  • 不需要在每次部署新版本的应用程序时设置 CAP/suid。
  • 不需要应用程序支持/修改,如 systemd-socket 方法。
  • 不需要内核重建(如果运行版本支持此 sysctl 设置)
  • 不会像 authbind/privbind 方法那样执行 LD_PRELOAD,这可能会影响性能、安全性、行为(是吗?尚未测试)。 在其他方面,authbind 确实是灵活且安全的方法。
  • 优于 iptables REDIRECT/DNAT 方法,因为它不需要地址转换、连接状态跟踪等。这仅在高负载系统上才会引人注目。

根据情况,我会在 sysctl、CAP、authbind 和 iptables-redirect 之间进行选择。 我们有这么多选择,这真是太好了。

For some reason no one mention about lowering sysctl net.ipv4.ip_unprivileged_port_start to the value you need.
Example: We need to bind our app to 443 port.

sysctl net.ipv4.ip_unprivileged_port_start=443

Some may say, there is a potential security problem: unprivileged users now may bind to the other privileged ports (444-1024).
But you can solve this problem easily with iptables, by blocking other ports:

iptables -I INPUT -p tcp --dport 444:1024 -j DROP
iptables -I INPUT -p udp --dport 444:1024 -j DROP

Comparison with other methods. This method:

  • from some point is (IMO) even more secure than setting CAP_NET_BIND_SERVICE/setuid, since an application doesn't setuid at all, even partly (capabilities actually are).
    For example, to catch a coredump of capability-enabled application you will need to change sysctl fs.suid_dumpable (which leads to another potential security problems)
    Also, when CAP/suid is set, /proc/PID directory is owned by root, so your non-root user will not have full information/control of running process, for example, user will not be able (in common case) to determine which connections belong to application via /proc/PID/fd/ (netstat -aptn | grep PID).
  • has security disadvantage: while your app (or any app that uses ports 443-1024) is down for some reason, another app could take the port. But this problem could also be applied to CAP/suid (in case you set it on interpreter, e.g. java/nodejs) and iptables-redirect. Use systemd-socket method to exclude this problem. Use authbind method to only allow special user binding.
  • doesn't require setting CAP/suid every time you deploy new version of application.
  • doesn't require application support/modification, like systemd-socket method.
  • doesn't require kernel rebuild (if running version supports this sysctl setting)
  • doesn't do LD_PRELOAD like authbind/privbind method, this could potentially affect performance, security, behavior (does it? haven't tested). In the rest authbind is really flexible and secure method.
  • over-performs iptables REDIRECT/DNAT method, since it doesn't require address translation, connection state tracking, etc. This only noticeable on high-load systems.

Depending on the situation, I would choose between sysctl, CAP, authbind and iptables-redirect. And this is great that we have so many options.

花落人断肠 2024-07-17 19:32:44

您可以进行端口重定向。 这就是我对 Linux 机器上运行的 Silverlight 策略服务器所做的事情

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 943 -j REDIRECT --to-port 1300

You can do a port redirect. This is what I do for a Silverlight policy server running on a Linux box

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 943 -j REDIRECT --to-port 1300
固执像三岁 2024-07-17 19:32:44

或者修补你的内核并删除检查。

(最后的选择,不推荐)。

net/ipv4/af_inet.c 中,删除读取的两行

      if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
              goto out;

,内核将不再检查特权端口。

Or patch your kernel and remove the check.

(Option of last resort, not recommended).

In net/ipv4/af_inet.c, remove the two lines that read

      if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
              goto out;

and the kernel won't check privileged ports anymore.

岁吢 2024-07-17 19:32:44

标准方法是让它们“setuid”,以便它们以 root 身份启动,然后在绑定到端口后但在开始接受与其连接之前就放弃 root 特权。 您可以在 Apache 和 INN 的源代码中看到很好的示例。 我听说 Lighttpd 是另一个很好的例子。

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

The standard way is to make them "setuid" so that they start up as root, and then they throw away that root privilege as soon as they've bound to the port but before they start accepting connections to it. You can see good examples of that in the source code for Apache and INN. I'm told that Lighttpd is another good example.

Another example is Postfix, which uses multiple daemons that communicate through pipes, and only one or two of them (which do very little except accept or emit bytes) run as root and the rest run at a lower privilege.

2024-07-17 19:32:44

现代 Linux 支持 /sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0

Modern Linux supports /sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0.

叹倦 2024-07-17 19:32:44

您可以设置本地 SSH 隧道,例如,如果您希望端口 80 访问绑定到 3000 的应用程序:

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

这具有使用脚本服务器的优点,并且非常简单。

You can setup a local SSH tunnel, eg if you want port 80 to hit your app bound to 3000:

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

This has the advantage of working with script servers, and being very simple.

渔村楼浪 2024-07-17 19:32:44

我知道这是一个老问题,但现在有了最近的(> = 4.3)内核,终于有了一个很好的答案 - 环境功能。

快速的答案是获取最新(尚未发布)版本的 libcap 来自 git 并编译它。 将生成的 progs/capsh 二进制文件复制到某处(/usr/local/bin 是一个不错的选择)。 然后,以 root 身份启动您的程序。 按

/usr/local/bin/capsh --keep=1 --user='your-service-user-name' \
    --inh='cap_net_bind_service' --addamb='cap_net_bind_service' \ 
    -- -c 'your-program'

顺序,我们

  • 声明,当我们切换用户时,我们希望保留当前的功能集
  • 。 组中
  • cap_net_bind_service 功能添加到继承的 & 环境设置
  • -- 之后的参数启动 bash)

Forking bash -c 'your-command' (因为 capsh 自动使用 在这里的引擎盖下。

首先,我们以 root 身份运行,因此默认情况下,我们可以获得全套功能。 其中包括切换 uid 和 uid 的能力。 gid 与 setuidsetgid 系统调用。 然而,通常当程序执行此操作时,它会失去其功能集 - 这样一来,使用 setuid 删除 root 的旧方法仍然有效。 --keep=1 标志告诉 capsh 发出 prctl(PR_SET_KEEPCAPS) 系统调用,这会在更改用户时禁止删除功能。 capsh 对用户的实际更改是通过 --user 标志进行的,该标志运行 setuidsetgid

我们需要解决的下一个问题是如何以在我们 exec 子项之后继续执行的方式设置功能。 功能系统始终具有一组“继承”的功能,即“跨 execve(2) 保留的一组功能”[功能(7)]。 虽然这听起来像是解决了我们的问题(只需将 cap_net_bind_service 功能设置为继承,对吧?),但这实际上仅适用于特权进程 - 并且我们的进程不再是特权进程,因为我们已经更改了用户(与 --user 标志)。

新的环境功能集解决了这个问题 - 它是“在非特权程序的 execve(2) 中保留的一组功能”。 通过将 cap_net_bind_service 放入环境集中,当 capsh exec 是我们的服务器程序时,我们的程序将继承此功能并能够将侦听器绑定到低端口。

如果您有兴趣了解更多信息,请参阅功能手册页对此进行了非常详细的解释。 通过 strace 运行 capsh 也能提供非常丰富的信息!

I know this is an old question, but now with recent (>= 4.3) kernels there is finally a good answer to this - ambient capabilities.

The quick answer is to grab a copy of the latest (as-yet-unreleased) version of libcap from git and compile it. Copy the resulting progs/capsh binary somewhere (/usr/local/bin is a good choice). Then, as root, start your program with

/usr/local/bin/capsh --keep=1 --user='your-service-user-name' \
    --inh='cap_net_bind_service' --addamb='cap_net_bind_service' \ 
    -- -c 'your-program'

In order, we are

  • Declaring that when we switch users, we want to keep our current capability sets
  • Switching user & group to 'your-service-user-name'
  • Adding the cap_net_bind_service capability to the inherited & ambient sets
  • Forking bash -c 'your-command' (since capsh automatically starts bash with the arguments after --)

There's a lot going on under the hood here.

Firstly, we are running as root, so by default, we get a full set of capabilities. Included in this is the ability to switch uid & gid with the setuid and setgid syscalls. However, ordinarily when a program does this, it loses its set of capabilities - this is so that the old way of dropping root with setuid still works. The --keep=1 flag tells capsh to issue the prctl(PR_SET_KEEPCAPS) syscall, which disables the dropping of capabilities when changing user. The actual changing of users by capsh happens with the --user flag, which runs setuid and setgid.

The next problem we need to solve is how to set capabilities in a way that carries on after we exec our children. The capabilities system has always had an 'inherited' set of capabilities, which is " a set of capabilities preserved across an execve(2)" [capabilities(7)]. Whilst this sounds like it solves our problem (just set the cap_net_bind_service capability to inherited, right?), this actually only applies for privileged processes - and our process is not privileged anymore, because we already changed user (with the --user flag).

The new ambient capability set works around this problem - it is "a set of capabilities that are preserved across an execve(2) of a program that is not privileged." By putting cap_net_bind_service in the ambient set, when capsh exec's our server program, our program will inherit this capability and be able to bind listeners to low ports.

If you're interested to learn more, the capabilities manual page explains this in great detail. Running capsh through strace is also very informative!

想你的星星会说话 2024-07-17 19:32:44

文件功能并不理想,因为它们可能会在软件包更新后中断。

恕我直言,理想的解决方案应该能够创建具有可继承的 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"

File capabilities are not ideal, because they can break after a package update.

The ideal solution, IMHO, should be an ability to create a shell with inheritable CAP_NET_BIND_SERVICE set.

Here's a somewhat convoluted way to do this:

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

capsh utility can be found in libcap2-bin package in Debian/Ubuntu distributions. Here's what goes on:

  • sg changes effective group ID to that of the daemon user. This is necessary because capsh leaves GID unchanged and we definitely do not want it.
  • Sets bit 'keep capabilities on UID change'.
  • Changes UID to $DAEMONUSER
  • Drops all caps (at this moment all caps are still present because of --keep=1), except inheritable cap_net_bind_service
  • Executes your command ('--' is a separator)

The result is a process with specified user and group, and cap_net_bind_service privileges.

As an example, a line from ejabberd startup script:

sg $EJABBERDUSER "capsh --keep=1 --uid=`id -u $EJABBERDUSER` --caps='cap_net_bind_service+pei' -- $EJABBERD --noshell -detached"
金兰素衣 2024-07-17 19:32:44

我的“标准解决方法”使用 socat 作为用户空间重定向器:

socat tcp6-listen:80,fork tcp6:8080

请注意,这不会扩展,分叉很昂贵,但这就是 socat 的工作方式。

My "standard workaround" uses socat as the user-space redirector:

socat tcp6-listen:80,fork tcp6:8080

Beware that this won't scale, forking is expensive but it's the way socat works.

泡沫很甜 2024-07-17 19:32:44

TLDR:对于“答案”(据我所知),请跳至>>TLDR<<

好吧,我已经弄清楚了(这次是真的),这个问题的答案,我的这个答案也是对推广 另一个答案(在这里和推特上)我认为是“最好的”,但在尝试之后,发现我错了那。 孩子们,从我的错误中吸取教训:在您亲自尝试过某件事之前,不要推广它!

我再次回顾了这里的所有答案。 我已经尝试了其中的一些(并选择不尝试其他解决方案,因为我根本不喜欢这些解决方案)。 我认为解决方案是使用 systemd 及其 Capability=CapabilityBindingSet= 设置。 经过一段时间的研究,我发现这不是解决方案因为:

功能旨在限制根进程!

作为OP明智地说,最好总是避免这种情况(如果可能的话,对于所有守护进程!)。

您不能在 systemd 单元文件中使用与 User=Group= 相关的功能选项,因为功能始终当调用 execev (或任何函数)时重置。 换句话说,当 systemd 分叉并放弃其权限时,功能将被重置。 没有办法解决这个问题,内核中的所有绑定逻辑都是围绕 uid=0 的,而不是功能。 这意味着能力不太可能成为这个问题的正确答案(至少在短期内)。 顺便说一句,正如其他人提到的,setcap 不是一个解决方案。 它对我不起作用,它不能很好地与脚本一起工作,并且每当文件更改时这些脚本都会重置。

在我微薄的辩护中,我确实声明了(在我现已删除的评论中)詹姆斯的 iptables 建议(其中OP还提到),是“第二最佳解决方案”。 :-P

>>TLDR<<

解决方案是将 systemd 与即时 iptables 命令,如下所示(取自 DNSChain):

[Unit]
Description=dnschain
After=network.target
Wants=namecoin.service

[Service]
ExecStart=/usr/local/bin/dnschain
Environment=DNSCHAIN_SYSD_VER=0.0.1
PermissionsStartOnly=true
ExecStartPre=/sbin/sysctl -w net.ipv4.ip_forward=1
ExecStartPre=-/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=-/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStartPre=/sbin/iptables -A INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStopPost=/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
User=dns
Group=dns
Restart=always
RestartSec=5
WorkingDirectory=/home/dns
PrivateTmp=true
NoNewPrivileges=true
ReadOnlyDirectories=/etc

# Unfortunately, capabilities are basically worthless because they're designed to restrict root daemons. Instead, we use iptables to listen on privileged ports.
# Capabilities=cap_net_bind_service+pei
# SecureBits=keep-caps

[Install]
WantedBy=multi-user.target

此处我们完成以下任务:

  • 守护进程侦听 5333,但由于 iptables 的帮助,连接在 533 上成功接受。
  • 我们可以将命令包含在单元文件本身中,从而避免人们头疼。 systemd 为我们清理防火墙规则,确保在守护进程未运行时将其删除。
  • 我们从不以 root 身份运行,而且即使守护进程被破坏并设置了 uid=0,我们也无法进行权限升级(至少 systemd 声称如此)。

不幸的是,iptables 仍然是一个相当丑陋且难以使用的实用程序。 例如,如果守护进程正在侦听 eth0:0 而不是 eth0,则命令为 略有不同

TLDR: For "the answer" (as I see it), jump down to the >>TLDR<< part in this answer.

OK, I've figured it out (for real this time), the answer to this question, and this answer of mine is also a way of apologizing for promoting another answer (both here and on twitter) that I thought was "the best", but after trying it, discovered that I was mistaken about that. Learn from my mistake kids: don't promote something until you've actually tried it yourself!

Again, I reviewed all the answers here. I've tried some of them (and chose not to try others because I simply didn't like the solutions). I thought that the solution was to use systemd with its Capabilities= and CapabilitiesBindingSet= settings. After wrestling with this for some time, I discovered that this is not the solution because:

Capabilities are intended to restrict root processes!

As the OP wisely stated, it is always best to avoid that (for all your daemons if possible!).

You cannot use the Capabilities related options with User= and Group= in systemd unit files, because capabilities are ALWAYS reset when execev (or whatever the function is) is called. In other words, when systemd forks and drops its perms, the capabilities are reset. There is no way around this, and all that binding logic in the kernel is basic around uid=0, not capabilities. This means that it is unlikely that Capabilities will ever be the right answer to this question (at least any time soon). Incidentally, setcap, as others have mentioned, is not a solution. It didn't work for me, it doesn't work nicely with scripts, and those are reset anyways whenever the file changes.

In my meager defense, I did state (in the comment I've now deleted), that James' iptables suggestion (which the OP also mentions), was the "2nd best solution". :-P

>>TLDR<<

The solution is to combine systemd with on-the-fly iptables commands, like this (taken from DNSChain):

[Unit]
Description=dnschain
After=network.target
Wants=namecoin.service

[Service]
ExecStart=/usr/local/bin/dnschain
Environment=DNSCHAIN_SYSD_VER=0.0.1
PermissionsStartOnly=true
ExecStartPre=/sbin/sysctl -w net.ipv4.ip_forward=1
ExecStartPre=-/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=-/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStartPre=/sbin/iptables -A INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStopPost=/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
User=dns
Group=dns
Restart=always
RestartSec=5
WorkingDirectory=/home/dns
PrivateTmp=true
NoNewPrivileges=true
ReadOnlyDirectories=/etc

# Unfortunately, capabilities are basically worthless because they're designed to restrict root daemons. Instead, we use iptables to listen on privileged ports.
# Capabilities=cap_net_bind_service+pei
# SecureBits=keep-caps

[Install]
WantedBy=multi-user.target

Here we accomplish the following:

  • The daemon listens on 5333, but connections are successfully accepted on 53 thanks to iptables
  • We can include the commands in the unit file itself, and thus we save people headaches. systemd cleans up the firewall rules for us, making sure to remove them when the daemon isn't running.
  • We never run as root, and we make privilege escalation impossible (at least systemd claims to), supposedly even if the daemon is compromised and sets uid=0.

iptables is still, unfortunately, quite an ugly and difficult-to-use utility. If the daemon is listening on eth0:0 instead of eth0, for example, the commands are slightly different.

晒暮凉 2024-07-17 19:32:44

另外两个简单的可能性:守护进程代理

守护进程

对于“守护进程”,有一种古老的(不流行的)解决方案“绑定在低端口上的守护进程,并将控制权交给您的服务器”。守护进程”。 它称为 inetd(或 xinetd)。

缺点是:

  • 你的守护进程需要在 stdin/stdout 上进行通信(如果你不控制守护进程——如果你没有源代码——那么这可能是一个阻碍,尽管有些服务可能有一个 inetd 兼容性标志)
  • 对于每个连接都会分叉一个新的守护进程,
  • 它是链中的一个额外链接

优点:

  • 就可以在任何旧的 UNIX 上使用
  • 一旦您的系统管理员设置了配置, ,您'很高兴继续您的开发(当您重新构建守护进程时,您可能会失去 setcap 功能吗?然后您必须返回管理员“请先生......”)
  • 守护进程不必担心网络的东西,只需要在 stdin/stdout 上进行对话
  • 就可以根据要求配置为以非 root 用户身份执行您的守护

进程

。 >更强大)从特权端口到可以运行目标守护程序的任意高编号端口。 (Netcat 显然不是一个生产解决方案,而是“只是我的开发盒”,对吧?)。 这样您就可以继续使用服务器的支持网络的版本,只需要 root/sudo 来启动代理(在启动时),而不会依赖于复杂/可能脆弱的功能。

Two other simple possibilities: Daemon and Proxy

Daemon

There is an old (unfashionable) solution to the "a daemon that binds on a low port and hands control to your daemon". It's called inetd (or xinetd).

The cons are:

  • your daemon needs to talk on stdin/stdout (if you don't control the daemon -- if you don't have the source -- then this is perhaps a showstopper, although some services may have an inetd-compatibility flag)
  • a new daemon process is forked for every connection
  • it's one extra link in the chain

Pros:

  • available on any old UNIX
  • once your sysadmin has set up the config, you're good to go about your development (when you re-build your daemon, might you lose setcap capabilities? And then you'll have to go back to your admin "please sir...")
  • daemon doesn't have to worry about that networking stuff, just has to talk on stdin/stdout
  • can configure to execute your daemon as a non-root user, as requested

Proxy

Another alternative: a hacked-up proxy (netcat or even something more robust) from the privileged port to some arbitrary high-numbered port where you can run your target daemon. (Netcat is obviously not a production solution, but "just my dev box", right?). This way you could continue to use a network-capable version of your server, would only need root/sudo to start proxy (at boot), wouldn't be relying on complex/potentially fragile capabilities.

弱骨蛰伏 2024-07-17 19:32:44

Linux 支持功能来支持更细粒度的权限,而不仅仅是“此应用程序以 root 身份运行” 。 其中一项功能是CAP_NET_BIND_SERVICE,它与绑定到特权端口(<1024)有关。

不幸的是,我不知道如何利用它来以非 root 身份运行应用程序,同时仍然为其提供 CAP_NET_BIND_SERVICE(可能使用 setcap,但肯定有一个现有的解决方案)。

Linux supports capabilities to support more fine-grained permissions than just "this application is run as root". One of those capabilities is CAP_NET_BIND_SERVICE which is about binding to a privileged port (<1024).

Unfortunately I don't know how to exploit that to run an application as non-root while still giving it CAP_NET_BIND_SERVICE (probably using setcap, but there's bound to be an existing solution for this).

九局 2024-07-17 19:32:44

systemd 是 sysvinit 的替代品,它可以选择启动具有特定功能的守护进程。 systemd.exec(5) 联机帮助页中的选项 Capability=、CapabilityBoundingSet=。

systemd is a sysvinit replacement which has an option to launch a daemon with specific capabilities. Options Capabilities=, CapabilityBoundingSet= in systemd.exec(5) manpage.

动次打次papapa 2024-07-17 19:32:44

使用 systemd,您只需稍微修改您的服务即可接受预激活的套接字。

您稍后可以使用 systemd 套接字激活

不需要任何功能、iptables 或其他技巧。

示例中相关 systemd 文件的内容

这是简单 python http 服务器文件 httpd- true.service

[Unit]
Description=Httpd true 

[Service]
ExecStart=/usr/local/bin/httpd-true
User=subsonic

PrivateTmp=yes

文件 httpd-true.socket

[Unit]
Description=HTTPD true

[Socket]
ListenStream=80

[Install]
WantedBy=default.target

With systemd, you just need to slightly modify your service to accept preactivated sockets.

You can later use systemd socket activate.

No capabilities, iptables or other tricks are needed.

This is content of relevant systemd files from this example of simple python http server

File httpd-true.service

[Unit]
Description=Httpd true 

[Service]
ExecStart=/usr/local/bin/httpd-true
User=subsonic

PrivateTmp=yes

File httpd-true.socket

[Unit]
Description=HTTPD true

[Socket]
ListenStream=80

[Install]
WantedBy=default.target
一束光,穿透我孤独的魂 2024-07-17 19:32:44

端口重定向对我们来说最有意义,但我们遇到了一个问题,即我们的应用程序将在本地解析也需要重新路由的 URL; (这意味着您shindig)。

这也将允许您在访问本地计算机上的 url 时进行重定向。

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

Port redirect made the most sense for us, but we ran into an issue where our application would resolve a url locally that also needed to be re-routed; (that means you shindig).

This will also allow you to be redirected when accessing the url on the local machine.

iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A OUTPUT -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080
白首有我共你 2024-07-17 19:32:44

启动时:

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

然后您可以绑定到您转发到的端口。

At startup:

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

Then you can bind to the port you forward to.

蓝天白云 2024-07-17 19:32:44

还有“djb 方式”。 您可以使用此方法以 root 身份启动进程,并在 tcpserver 下的任何端口上运行,然后在进程启动后立即将进程的控制权交给您指定的用户。

#!/bin/sh

UID=$(id -u username)
GID=$(id -g username)
exec tcpserver -u "${UID}" -g "${GID}" -RHl0 0 port /path/to/binary &

有关详细信息,请参阅:http://thedjbway.b0llix.net/daemontools/uidgid.html< /a>

There is also the 'djb way'. You can use this method to start your process as root running on any port under tcpserver, then it will hand control of the process to the user you specify immediately after the process starts.

#!/bin/sh

UID=$(id -u username)
GID=$(id -g username)
exec tcpserver -u "${UID}" -g "${GID}" -RHl0 0 port /path/to/binary &

For more info, see: http://thedjbway.b0llix.net/daemontools/uidgid.html

风流物 2024-07-17 19:32:44

将8080端口绑定到80并打开80端口:

sudo iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

然后以普通用户身份在8080端口运行程序。

然后您将能够在端口 80 上访问 http://127.0.0.1

Bind port 8080 to 80 and open port 80:

sudo iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

and then run program on port 8080 as a normal user.

you will then be able to access http://127.0.0.1 on port 80

梦年海沫深 2024-07-17 19:32:44

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

Use the privbind utility: it allows an unprivileged application to bind to reserved ports.

苦妄 2024-07-17 19:32:44

我尝试了 iptables PREROUTING REDIRECT 方法。 在较旧的内核中,IPv6 似乎不支持这种类型的规则。 但显然现在 ip6tables v1.4.18 和 Linux kernel v3.8 支持它。

我还发现 PREROUTING REDIRECT 不适用于机器内发起的连接。 要从本地计算机进行连接,还需要添加 OUTPUT 规则 - 请参阅 iptables 端口重定向不适用于 localhost。 例如:

iptables -t nat -I OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080

我还发现 PREROUTING REDIRECT 也会影响转发的数据包。 也就是说,如果机器还在接口之间转发数据包(例如,如果它充当连接到以太网的 Wi-Fi 接入点),则 iptables 规则还将捕获已连接客户端到 Internet 目的地的连接,并将它们重定向到机器。 这不是我想要的 - 我只想重定向定向到机器本身的连接。 我发现通过添加 -m addrtype --dst-type LOCAL 可以使其仅影响发送到该盒子的数据包。 例如:

iptables -A PREROUTING -t nat -p tcp --dport 80 -m addrtype --dst-type LOCAL -j REDIRECT --to-port 8080

另一种可能性是使用 TCP 端口转发。 例如,使用socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

然而,该方法的一个缺点是,在端口8080 上侦听的应用程序不知道传入连接的源地址(例如,用于日志记录或其他识别目的)。

I tried the iptables PREROUTING REDIRECT method. In older kernels it seems this type of rule wasn't supported for IPv6. But apparently it is now supported in ip6tables v1.4.18 and Linux kernel v3.8.

I also found that PREROUTING REDIRECT doesn't work for connections initiated within the machine. To work for conections from the local machine, add an OUTPUT rule also — see iptables port redirect not working for localhost. E.g. something like:

iptables -t nat -I OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080

I also found that PREROUTING REDIRECT also affects forwarded packets. That is, if the machine is also forwarding packets between interfaces (e.g. if it's acting as a Wi-Fi access point connected to an Ethernet network), then the iptables rule will also catch connected clients' connections to Internet destinations, and redirect them to the machine. That's not what I wanted—I only wanted to redirect connections that were directed to the machine itself. I found I can make it only affect packets addressed to the box, by adding -m addrtype --dst-type LOCAL. E.g. something like:

iptables -A PREROUTING -t nat -p tcp --dport 80 -m addrtype --dst-type LOCAL -j REDIRECT --to-port 8080

One other possibility is to use TCP port forwarding. E.g. using socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

However one disadvantage with that method is, the application that is listening on port 8080 then doesn't know the source address of incoming connections (e.g. for logging or other identification purposes).

我不会写诗 2024-07-17 19:32:44

由于 OP 只是开发/测试,不太流畅的解决方案可能会有所帮助:

可以在脚本的解释器上使用 setcap 来向脚本授予功能。 如果全局解释器二进制文件上的 setcaps 不可接受,请制作二进制文件的本地副本(任何用户都可以)并获得 root 权限以在此副本上进行 setcap。 Python2(至少)可以与脚本开发树中解释器的本地副本一起正常工作。 不需要 suid,因此 root 用户可以控制用户有权访问的功能。

如果您需要跟踪解释器的系统范围更新,请使用如下所示的 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 $*

Since the OP is just development/testing, less than sleek solutions may be helpful:

setcap can be used on a script's interpreter to grant capabilities to scripts. If setcaps on the global interpreter binary is not acceptable, make a local copy of the binary (any user can) and get root to setcap on this copy. Python2 (at least) works properly with a local copy of the interpreter in your script development tree. No suid is needed so the root user can control to what capabilities users have access.

If you need to track system-wide updates to the interpreter, use a shell script like the following to run your script:

#!/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 $*
地狱即天堂 2024-07-17 19:32:44

2015 年 9 月回答:

ip6tables 现在支持 IPV6 NAT:http ://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt

您将需要内核 3.7+

证明:

[09:09:23] root@X:~ ip6tables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:80 redir ports 8080
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:443 redir ports 1443

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination

Answer at 2015/Sep:

ip6tables now supports IPV6 NAT: http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt

You will need kernel 3.7+

Proof:

[09:09:23] root@X:~ ip6tables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:80 redir ports 8080
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:443 redir ports 1443

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination
深白境迁sunset 2024-07-17 19:32:44

有一个使用支持文件的共享库执行此操作的有效示例链接到 libcap 网站上的非特权应用程序。 最近在有关向共享库添加功能的问题的回答中提到了这一点。

There is a worked example of doing this with a file capable shared library linked to an unprivileged application on the libcap website. It was recently mentioned in an answer to a question about adding capabilities to shared libraries.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文