Node Express Unix Domain Socket 权限

11
我正在运行一个nginx服务器和一个node express web服务器,使用daemontools设置Unix Domain Sockets通信。但是有几个问题:
  1. 关闭服务器时套接字文件仍然存在,因此在重新启动服务器时必须将其删除,否则会出现EADDRINUSE错误。
  2. nginx服务器以nginx用户身份运行,而node服务器以node用户身份运行。
  3. 当服务器启动并且umask设置套接字文件的权限为755时,Express创建套接字文件。
  4. setuidgid应用程序将组设置为用户的默认组,即在本例中为node用户名。
  5. 应用程序的部署脚本和daemontools的运行脚本在node服务器实例启动之前执行,因此无法设置文件的权限,因为它必须在启动过程中重新创建。
如果我使用chgrp和chmod g+w更改套接字文件的权限,则一切正常。是否有一种方法可以设置这样的方式,以便生成node应用程序的套接字文件具有正确的权限,使得nginx能够写入它,而不会危及任何一个应用程序的安全独立性?即使将nginx添加到node用户组中,只要还有一种方法可以设置套接字文件的权限,使其成为组可写的,我也可以接受。

1
我也很想知道一个干净的方法来做这件事。最终,我放弃了并回到使用TCP。 - Nate
4个回答

9
也许我来得太晚了。
作为您自己答案的补充,还有一种解决方案,不需要将nginx用户添加到节点组中。
创建一个仅用于套接字文件的目录,分配给节点用户和www-data(或nginx所在的任何组),并在该目录上设置组ID位(SGID)。
mkdir -p /var/lib/yourapp/socket
chown nodeuser:nginxgroup /var/lib/yourapp/socket
chmod g+rxs /var/lib/yourapp/socket

在该目录中创建的所有文件将自动归属于 nginxgroup 组。


完美,这是一个更加优雅的解决方案。谢谢! - Bobby
几乎完美,但我不知道为什么无法在g+w上进行套接字继承...有任何想法吗? - y_nk
新文件的写入权限不会继承其父文件夹的权限,必须在创建文件时或之后使用chmod命令进行设置(请参见karma0答案中的示例代码)。 - Patxitron
1
新文件的权限受到umask的影响,例如,如果您的节点应用程序由在systemd下运行的pm2启动,则可以将UMask = 0002添加到服务定义中。 - Daniel

5
我通过将nginx添加到节点用户的主要组中,使其工作起来了。
gpasswd -a nginx node

然后使用以下命令启动express服务器:

// Create the server
fs.stat(listen, function(err) {
  if (!err) { fs.unlinkSync(sock); }
  http.createServer(app).listen(sock, function(){
    fs.chmodSync(sock, '775');
    console.log('Express server listening on ' + listen);
  });
});

我不认为这是一个有效的解决方案,只是一个hack。Express并没有考虑删除和设置文件权限,特别是我不喜欢把nginx用户添加到node用户的主组中。如果nginx账户被攻击者攻击,攻击者可能会访问整个应用程序的源代码,并通过套接字尝试无限次攻击代码。我能做的最好的事情就是将umask设置为077,尝试使用chmod 600在每个文件上进行100%覆盖,并在每个目录上设置chmod 700,或者将默认组设置为用户的非默认值。

话虽如此,我仍然希望得到任何想法的支持。


4

@Bobby的答案让我在nginx中遇到connect() to unix:/run/static0.sock failed (13: Permission denied)的问题。Chmod 777是解决方法。这是我的解决方案[在他的基础上构建]:

var fs = require('fs');
var http = require('http');
var process = require('process');
var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World!')
})

var sock = process.argv[2];

fs.stat(sock, function(err) {
  if (!err) { fs.unlinkSync(sock); }
  http.createServer(app).listen(sock, function(){
    fs.chmodSync(sock, '777');
    console.log('Express server listening on ' + sock);
  });
});

运行方式:

$ node server.js /run/static0.sock
Express server listening on /run/static0.sock

我推荐@Patxitron的答案。你遇到的问题很可能是套接字不属于同一用户/组。777权限将使套接字可被机器上任何进程写入,这可能会带来相当大的安全问题,而这正是我一开始试图避免的。 - Bobby

0

我不知道它是否仍然相关,但我成功地作为节点客户端连接到了Unix套接字(服务器是用C编写的)。

使用运行节点的用户,我只是为此触摸了一个新的文件s.sock,当我的服务器启动时,它会监听此Unix套接字。

对我来说问题在于我尝试以sudo身份运行我的服务器,然后它更改了套接字的根权限。

无论如何,对我有用的是以非root权限运行服务器,然后当我尝试从节点连接到它时,我没有得到以下错误:

Error: connect EACCES

希望这能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接