我正在开发使用 Unix 域套接字进行 IPC 的应用程序。据我所知,常见的方法是将套接字文件放入其中/var/run
。我使用 Ubuntu 18.04,我看到这var/run
是一个/run
.不幸的是,该文件夹只能访问root
:
ls -Al /
drwxr-xr-x 27 root root 800 Apr 12 17:39 run
因此,只有 root 拥有该文件夹的写入权限,这使得普通用户无法使用 Unix 域套接字。
首先我不明白为什么?以及如何为非 root 用户使用 Unix 域套接字?我当然可以使用主文件夹,但我更喜欢使用一些正确且常用的方法。
答案1
如果用户不是某种特殊的系统用户,那么在用户主目录的 dotfile 或 dotdir 中创建套接字并没有什么问题。唯一的问题是通过 nfs 在多台计算机之间共享主目录,但这可以通过在套接字名称中包含主机名来轻松解决。
在 Linux/Ubuntu 上你也可以使用“抽象的”Unix 域套接字,不使用文件系统中的任何路径或索引节点。抽象 unix 套接字是那些地址/路径以 NUL 字节开头的套接字:
抽象的:抽象套接字地址(与路径名套接字)的区别在于它
sun_path[0]
是空字节(\0
)。
sun_path
此命名空间中套接字的地址由地址结构的指定长度覆盖的附加字节给出。 (名称中的空字节没有特殊意义。)该名称与文件系统路径名没有联系。当返回抽象套接字的地址时,返回的值addrlen
大于sizeof(sa_family_t)
(即大于2),并且套接字的名称包含在(addrlen - sizeof(sa_family_t))
的第一个字节中sun_path
。
当为用户显示或由用户输入时,抽象 Unix 套接字地址中的 NUL 字节通常被替换为@
s。许多程序都犯了严重的错误,因为它们不会@
以任何方式转义正则和/或假设只有第一个字节可能是 NUL。
与常规 Unix 套接字路径不同,抽象 Unix 套接字名称具有不同的语义,因为任何人都可以绑定到它们(如果尚未使用该名称),并且任何人都可以连接到它们。
而不是依赖文件/目录权限来限制谁可以连接到您的套接字,并假设例如。只有 root 可以在某个目录中创建套接字,您应该检查对等方的凭据getsockopt(SO_PEERCRED)
(以获取连接或绑定对等方的 uid/pid),或SCM_CREDENTIALS
辅助消息(获取通过该对等方发送消息的人的 uid/pid)插座)。
这(取代通常的文件权限检查)也是SO_PEERCRED
/ SCM_CREDENTIALS
IMHO 的唯一合理使用。
答案2
您的unix域套接字不应直接进入/run
,您必须在其中创建一个文件夹/run
,例如/run/my-ipc
为您的用户提供适当的权限,然后写入该文件夹。
该文件夹必须在启动时重新创建。接受的答案这个问题解释了几个替代方案。