为什么我创建的 unix 套接字具有与其他文件不同的 ACL 掩码?

为什么我创建的 unix 套接字具有与其他文件不同的 ACL 掩码?

我正在部署一个 Nodejs Express 应用程序。它将与 Nginx 服务器在同一台机器上运行,后者将通过 unix 套接字将请求代理到它。然而,这个问题并不特定于 Nodejs。

express 应用程序以用户身份运行nodejs,nginx 以身份运行nginx

我的计划是创建一个Express/sockets拥有的目录nodejs来放置套接字,并nginx通过目录上的默认 ACL 授予对这些套接字的访问权限。如果这个想法很愚蠢,请随时告诉我,但请记住这不是我的核心问题。

我以 root 身份运行以下命令在目录上创建 ACL:

setfacl -Rd --mask -m nginx:rw  /sockets
setfacl -R  --mask -m nginx:rwX /sockets

然后,该目录具有以下 ACL:(为了问题的易读性,我将其制成表格)

# file: /sockets
# owner: nodejs
# group: root
user:      : rwx
user: nginx: rwx
group:     : r-x
mask:      : rwx
other:     : r-x
default: user:     :rwx
default: user:nginx:rw-
default:group:     :r-x
default: mask:     :rwx
default:other:     :r-x

如果以 身份运行nodejs并写入文件,则会正确创建该文件:

sudo -su nodejs
touch /sockets/testFile
getfacl /sockets/testFile

# file: /sockets/testFile
# owner: nodejs
# group: nodejs
user:     :rw-
user:nginx:rw-
group:    :r-x                      #effective:r--
mask:     :rw-
other:    :r--

伟大的!

listen()但是,如果 Node 通过调用此目录中的路径创建套接字,则会使用mask阻止nginx访问的 ACL 创建套接字。

const e = require('express')()
e.listen('/sockets/testSocket', (e) => console.error(e))

getfacl /sockets/testSocket 
# file: /sockets/testSocket
# owner: nodejs
# group: nodejs
user:     :rwx
user:nginx:rw-                  #effective:r--
group:    :r-x
mask:     :r-x
other:    :r-x

如果我使用 Nodejs 创建一个普通文件/sockets(例如通过fs.writeFile),它将使用与我上面运行时相同的权限创建touch /sockets/testFile,所以我不认为这是 Node 的问题umask

同样,如果我运行等效代码来绑定到中的套接字python,结果是相同的,所以我不认为这是 Node 本身的问题。

显然,这阻止了 Nginx 与我的 Express 应用程序通信。有人能找出原因吗? :/ 服务器正在运行 CentOS 7。

答案1

答案是 socket() 是一个 libc 函数,它没有实现 100% 记录的 ACL 策略。

通过实验我发现你必须为调用进程设置 umask,根据 ACL 规则应该不是创建文件时很重要,并且为了按照您想要的方式成功创建套接字,您必须:

umask 0002
setfacl -d -m user:nginx:rwx /sockets
setfacl -d -m group::rwx /sockets
setfacl -d -m mask::rwx /sockets

相关内容