在Python中放弃根权限

49 投票
6 回答
20942 浏览
提问于 2025-04-15 21:57

我想让一个Python程序在80号端口上开始监听,但之后希望它能在没有管理员权限的情况下运行。有没有办法在不需要管理员权限的情况下使用80号端口或者在运行后放弃管理员权限呢?

6 个回答

5
  1. systemd可以帮你处理这个问题。如果你通过systemd启动你的程序,systemd可以把已经打开的监听端口交给它,而且在第一次连接时也可以激活你的程序。你甚至不需要把它变成后台进程。

  2. 如果你选择独立的方式,你需要有CAP_NET_BIND_SERVICE这个能力(可以查查相关的手册)。这可以通过正确的命令行工具逐个程序来设置,或者让你的应用程序(1)以suid root的身份运行(2)启动(3)监听端口(4)立即降低权限。

记住,suid root程序有很多安全方面的考虑(比如干净安全的环境、umask、权限、资源限制等等,这些都是你的程序需要正确设置的)。如果你能使用像systemd这样的工具,那就更好了。

13

我建议你使用 authbind 来启动你的Python程序,这样就不需要以管理员身份运行它了。

https://en.wikipedia.org/wiki/Authbind

58

你不能在没有管理员权限的情况下打开80端口,这是操作系统的限制。所以唯一的解决办法就是在打开端口后放弃管理员权限。

这里有一个在Python中放弃管理员权限的可能解决方案:在Python中放弃权限。这个方法总体上是不错的,但你还需要在函数中添加os.setgroups([]),以确保不会保留根用户的组成员身份。

我稍微整理了一下代码,去掉了日志记录和异常处理,所以处理OSError的部分就留给你自己来做(这个错误会在进程无法切换有效的用户ID或组ID时抛出):

import os, pwd, grp

def drop_privileges(uid_name='nobody', gid_name='nogroup'):
    if os.getuid() != 0:
        # We're not root so, like, whatever dude
        return

    # Get the uid/gid from the name
    running_uid = pwd.getpwnam(uid_name).pw_uid
    running_gid = grp.getgrnam(gid_name).gr_gid

    # Remove group privileges
    os.setgroups([])

    # Try setting the new uid/gid
    os.setgid(running_gid)
    os.setuid(running_uid)

    # Ensure a very conservative umask
    old_umask = os.umask(077)

撰写回答