在Python中删除根权限

46 python unix linux permissions root

我想让一个Python程序开始监听端口80,但之后执行没有root权限.有没有办法放弃root或没有它的端口80?

Tam*_*más 57

没有root权限,您将无法在端口80上打开服务器,这是对操作系统级别的限制.因此,唯一的解决方案是在打开端口后删除root权限.

以下是在Python中删除 root权限的可能解决方案:在Python中删除权限.这通常是一个很好的解决方案,但您还必须添加os.setgroups([])到该函数以确保不保留root用户的组成员身份.

我复制并清理了一点代码,并删除了日志记录和异常处理程序,因此可以让你OSError正确处理(当不允许进程切换其有效的UID或GID时会抛出它):

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)
Run Code Online (Sandbox Code Playgroud)

  • 请记住,HOME目录仍然是`/ root`而不是`/ home/uid_name`,并且uid_name将无法对`〜/`执行任何操作,然后将扩展为`/ root /` .这会影响像matplotlib这样的模块,它们将配置数据存储在HOME目录中.`authbind`似乎是处理这个问题的正确方法. (2认同)
  • *“如果没有 root 权限,您将无法在端口 80 上打开服务器...”* - 这不一定是真的(也许不再是了?)。另请参阅超级用户上的[允许非 root 进程绑定到端口 80 和 443?](https://superuser.com/q/710253/173513) 和[是否有办法让非 root 进程绑定到“特权” Linux 上的端口?](/sf/ask/28966521/) (2认同)

All*_*len 12

我建议authbind用来启动你的Python程序,所以它都不能以root身份运行.

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


Aut*_*act 7

在我需要删除权限时,要求用户输入他/她的用户名和组并不是一个好主意.这是Tamás代码的略微修改版本,它将删除权限并切换到启动sudo命令的用户.我假设你正在使用sudo(如果没有,请使用Tamás的代码).

#!/usr/bin/env python3

import os, pwd, grp

#Throws OSError exception (it will be thrown when the process is not allowed
#to switch its effective UID or GID):
def drop_privileges():
    if os.getuid() != 0:
        # We're not root so, like, whatever dude
        return

    # Get the uid/gid from the name
    user_name = os.getenv("SUDO_USER")
    pwnam = pwd.getpwnam(user_name)

    # Remove group privileges
    os.setgroups([])

    # Try setting the new uid/gid
    os.setgid(pwnam.pw_gid)
    os.setuid(pwnam.pw_uid)

    #Ensure a reasonable umask
    old_umask = os.umask(0o22)


#Test by running...
#./drop_privileges
#sudo ./drop_privileges
if __name__ == '__main__':
    print(os.getresuid())
    drop_privileges()
    print(os.getresuid())
Run Code Online (Sandbox Code Playgroud)


小智 5

  1. systemd 可以为您完成,如果您通过 systemd 启动程序,systemd 可以将已经打开的侦听套接字交给它,并且它还可以在第一次连接时激活您的程序。你甚至不需要守护它。

  2. 如果您打算采用独立方法,则需要功能 CAP_NET_BIND_SERVICE(查看功能手册页)。这可以使用正确的命令行工具在逐个程序的基础上完成,或者通过使您的应用程序 (1) 成为 suid root (2) 启动 (3) 侦听端口 (4) 立即删除权限/功能.

请记住,suid root 程序有很多安全方面的考虑(干净和安全的环境、umask、特权、rlimits,所有这些都是你的程序必须正确设置的东西)。如果您可以使用 systemd 之类的东西,那就更好了。