Question

I am running an nginx server and a node express web server, using daemontools, setup to communicate over Unix Domain Sockets. There's just a few problems:

  1. The socket file stays present on shutdown, so I have to delete it when bringing the server back up, otherwise I will get the EADDRINUSE error.
  2. The nginx server runs as the nginx user, and the node server runs as the node user.
  3. The socket file gets created by Express when the server starts up and umask sets the permissions on the socket file to 755.
  4. The setuidgid application sets the group to the default group of the user, both the node username in this case.
  5. The deployment scripts for the application and daemontools' run script execute before the node server instance gets launched, so there's no way to set the permissions on the file, as it has to get recreated during the launch process.

If I chgrp and chmod g+w the socket file, everything works fine. Is there a way to set this up so that the node application's socket file gets generated with the correct permissions for nginx to be able to write to it without compromising the security independence of one application or the other? I would even be okay with adding nginx to the node user's group, if there was still a way to set the permissions on the socket file so that it would be group writable.

Was it helpful?

Solution

Maybe I am too late.

As a complement of your own answer there is a solution not having to add the nginx user to the node group.

Create a directory only for the socket file, assign it to the node user and www-data (or whatever group the nginx is) group and set the group-id bit (SGID) on that directory.

mkdir -p /var/lib/yourapp/socket
chown nodeuser:nginxgroup /var/lib/yourapp/socket
chmod g+rxs /var/lib/yourapp/socket

All files created inside this directory will automatically be owned by the nginxgroup group.

OTHER TIPS

I was able to get it working by adding nginx to the node user's primary group:

gpasswd -a nginx node

And then starting the express server using the following:

// 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);
  });
});

I don't really feel like this is a valid solution, just a hack. Express wasn't built with deleting and setting file perms in mind, and it especially bugs me to have to add the nginx user to the node user's primary group. If there were ever a compromise of the nginx account, the attacker could conceivably have access to all of the application's source, and an avenue to try endless attacks on the code using the socket. The best that I can do is set the umask to 077 for the node user and try to get 100% coverage with a chmod 600 on every file and chmod 700 on every directory, or set the group to the non-default for the user on everything.

That said, I would still appreciate any ideas.

@Bobby's answer left me with connect() to unix:/run/static0.sock failed (13: Permission denied) in nginx. Chmod 777 was the trick. Here's my solution [building on his]:

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);
  });
});

Run like:

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

I don't know if it's still relevant but i succeed to connect to the unix socket as the node client (server is in c).

With the user that runs the node i simply touched a new file s.sock for that matter, when my server starts it listens to this unix socket.

The issue for me was that i tried running my server as sudo, and then it changes the socket to root privileges.

Anyhow what worked for me was simply running the server without root privileges and then then when tried connecting to it from node i didn't got.

Error: connect EACCES

Hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top