如何使用普通用户创建的 root 套接字

How to use a socket created by root with a normal user

所以我有这个服务器:

import socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind('/tmp/sock.sock')
sock.listen(1)
while True:
    conn, ca = sock.accept()
    print(conn.recv(1024))

而这个客户:

import socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect('/tmp/sock.sock')
sock.send('Hello, World')

实际的发送和接收有点复杂,但只要服务器和客户端都是 运行 root 就可以完美地工作。当客户端是 运行 作为 root 并且服务器是 运行 时,它也适用于普通用户。但是当我尝试 运行 普通用户使用 root 和客户端的服务器时,我得到这个:

$ python3 client.py
connecting to /tmp/sock.sock
[Errno 13] Permission denied

我该如何解决这个问题?服务器需要 运行 作为 root 和客户端作为非特权用户。

我已经明白它与套接字文件的文件权限有关,但我不知道该如何修复它。我看不到任何传递给套接字构造函数的选项来解决这个问题。

更改文件模式以允许任何人访问它。在您的服务器中添加此行

import os
os.chmod("/tmp/sock.sock", 0o777)

感谢 P.Dmitry 为我指明了正确的方向。我最终对相同的想法进行了这种修改,它更适合我的需要:

import pwd
import grp
...
# Change the owner of the socket
os.chown('/tmp/sock.sock', 
         pwd.getpwnam('user').pw_uid, 
         grp.getgrnam('group').gr_gid)
# Restrict access to only this user (and root of course)
os.chmod('/tmp/sock.sock', 0o600)

注:

0o是Python3中的八进制前缀。在 Python2 中只是 0 就像在 C 中一样。

这不是一个好主意,如果您将整个服务器设计为 运行 作为 root,则某处存在设计错误。

这里发生的是 root 用户使用自己的权限创建 /tmp/sock.sock 文件,并且该文件只能由创建它的用户访问。

问题是,即使 Linux 上的 bind 方法(但 Mac OS 上没有!)已修补为不遵循符号链接,您仍在制造安全问题。假设文件不存在,服务器不在 运行ning。然后,普通用户可以创建从 /tmp/sock.sock/etc/passwd 的符号链接,当服务器尝试启动时,它将尝试绑定、设置权限,然后由于符号链接而失败,但权限将是放。因此,您会将密码文件设置为可写。

即使没有权限问题,假设有人发送了大量数据并且它填满了磁盘导致服务器崩溃。如果您 运行 具有普通用户的服务器,您可以设置最大配额,但您不想在 root 上设置它。

我的建议是:创建一个新用户,其唯一任务是 运行 服务器和客户端,并具有所需的最低权限集。