我如何以“正确的方式”将低编号端口声明为非根端口?

发布于 2024-08-27 19:32:51 字数 634 浏览 15 评论 0原文

我有一个脚本,我想作为守护进程运行,侦听低编号端口(<1024)

脚本是用Python编写的,尽管Perl中的答案也是可以接受的。

该脚本正在使用 start- 进行守护进程stop-daemon 在启动脚本中,这可能会使答案复杂化

我真正(认为)不想要的是输入 ps -few 并看到此进程以“root”运行在它的线上。

我该怎么做?

(从我对系统调用不太了解的角度来看,我可以看到 3 个途径,

  1. 以 root 身份运行脚本(没有 --user/--group/--chuid 来启动-停止-守护进程),并在它声明脚本上的端口 Setuid root (chmod u+s) 后降级其用户
  2. ,并以运行用户身份运行脚本(通过 --user/--group/--chuid 启动- stop-daemon,启动脚本仍然必须以 root 身份调用),在脚本中,获取 root 权限,声明端口,然后恢复为普通用户(
  3. 其他我不知道的事情

I have a script that I want to run as a daemon listening on a low-numbered port (< 1024)

Script is in python, though answers in perl are also acceptable.

The script is being daemonized using start-stop-daemon in a startup script, which may complicate the answer

What I really (think) don't want is to type ps -few and see this process running with a "root" on it's line.

How do I do it?

( from my less-than-fully-educated-about-system-calls perspective, I can see 3 avenues,

  1. Run the script as root (no --user/--group/--chuid to start-stop-daemon), and have it de-escalate it's user after it claims the port
  2. Setuid root on the script (chmod u+s), and run the script as the running user, (via --user/--group/--chuid to start-stop-daemon, the startup script still has to be called as root), in the script, acquire root privileges, claim the port, and then revert back to normal user
  3. something else i'm unaware of

)

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

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

发布评论

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

评论(4

凶凌 2024-09-03 19:32:51

“你不知道的东西”是“功能”,但正如提到的其他地方 功能不能很好地与使用 shebang 方法的脚本配合使用,因此这里并不是一个很好的答案。我会采用“绑定端口,然后放弃特权”的方法。

The "something you don't know about" is "capabilities", but as mentioned elsewhere capabilities don't play very well with scripts using the shebang method, so it's not much of an answer here. I would go with the "bind the port, then drop privileges" method.

爱人如己 2024-09-03 19:32:51

这个页面有一些代码引导我找到它,< a href="http://antonym.org/2005/12/dropping-privileges-in-python.html" rel="nofollow noreferrer">http://antonym.org/2005/12/dropping-privileges-in -python.html

我想设置 umask 是完成这项工作所必需的,这是这段代码似乎唯一做的事情,而我的尝试却没有做到(我不确定设置 umask 真正做了什么,在将其应用于流程的上下文)

我把他的示例撕碎了一点,此外,该页面是 2005 年的,所以我在这里重新发布我的工作解决方案,

def drop_privileges(uid_name='nobody', gid_name='nogroup'):
    # Get the uid/gid from the name
    running_uid = pwd.getpwnam(uid_name)[2]
    running_gid = grp.getgrnam(gid_name)[2]

    # Try setting the new uid/gid
    try:
        os.setgid(running_gid)
    except OSError, e:
        logging.error('Could not set effective group id: %s' % e)
        exit()

    try:
        os.setuid(running_uid)
    except OSError, e:
        logging.error('Could not set effective user id: %s' % e)
        exit()

    # Ensure a very convervative umask
    new_umask = 077
    old_umask = os.umask(new_umask)
    logging.info('drop_privileges: Old umask: %s, new umask: %s' % \
             (oct(old_umask), oct(new_umask)))

    final_uid = os.getuid()
    final_gid = os.getgid()
    logging.info('drop_privileges: running as %s/%s' % \
             (pwd.getpwuid(final_uid)[0],
              grp.getgrgid(final_gid)[0]))    

This page had some code that led me to it, http://antonym.org/2005/12/dropping-privileges-in-python.html

I suppose setting the umask is necessary to finish the job, that's the only thing this code seems to do that my attempts weren't (i'm not sure what setting the umask really does, in the context of applying it to a process)

I tore his example up a bit, and besides, that page is from 2005, so I'm reposting my working solution here,

def drop_privileges(uid_name='nobody', gid_name='nogroup'):
    # Get the uid/gid from the name
    running_uid = pwd.getpwnam(uid_name)[2]
    running_gid = grp.getgrnam(gid_name)[2]

    # Try setting the new uid/gid
    try:
        os.setgid(running_gid)
    except OSError, e:
        logging.error('Could not set effective group id: %s' % e)
        exit()

    try:
        os.setuid(running_uid)
    except OSError, e:
        logging.error('Could not set effective user id: %s' % e)
        exit()

    # Ensure a very convervative umask
    new_umask = 077
    old_umask = os.umask(new_umask)
    logging.info('drop_privileges: Old umask: %s, new umask: %s' % \
             (oct(old_umask), oct(new_umask)))

    final_uid = os.getuid()
    final_gid = os.getgid()
    logging.info('drop_privileges: running as %s/%s' % \
             (pwd.getpwuid(final_uid)[0],
              grp.getgrgid(final_gid)[0]))    
笔芯 2024-09-03 19:32:51

选项 1 是 Apache httpd 所采用的路线。如果它对于世界上最受欢迎的 Web 服务器来说足够好,那么就值得认真考虑自己的守护进程。

Option 1 is the route Apache httpd takes. And if it's good enough for the world's most popular web server then it's worth serious consideration for ones own daemons.

另类 2024-09-03 19:32:51

您可以安装一个库,如果LD_PRELOAD-ed,它将伪造任何可执行文件(脚本或其他)的根权限:http://fakeroot.alioth.debian.org/

在脚本上设置粘性位权限(至少根据我的经验)没有效果; ELF 二进制解释器(/usr/bin/python、/bin/sh、/usr/bin/perl 等)需要粘性权限才能工作。您可以做的是将二进制文件复制到另一个位置,在其上设置粘滞位,然后将脚本的 bang 行指向它。

不过,如果您在正在执行的系统上没有 root 访问权限,则可以修改路由器设置,将 <1024 外部端口定向到 >=1024 内部端口。

编辑:我忘了提到这个小工具:redir。这是本地端口重定向服务。它甚至对 inetd 友好。

You can install a library which, if LD_PRELOAD-ed, will fake root permissions for any executable (script or otherwise): http://fakeroot.alioth.debian.org/

Setting sticky bit permissions on a script will (at least in my experience) have no effect; it's the ELF binary interpreter (/usr/bin/python, /bin/sh, /usr/bin/perl, etc.) that needs the sticky permissions in order for it to work. What you could do is to copy the binary to another location, set the sticky bit on it, then point the script's bang line to it.

If you don't have root access on the system you're executing on, though, you may be able to modify the router settings to direct the <1024 external port to a >=1024 internal port.

EDIT: I forgot to mention this little tool: redir. It's a local port redirection service. It's even inetd-friendly.

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