node.jsで少しセキュリティ的な脅威を減らす80番ポートを使った起動方法

特権ユーザで80ポートをlistenしたら一般ユーザに切り替える - 四角革命前夜の続き的な。
環境を作る部分がちょっと増えただけでコードはあまり変わってないです。
環境:Ubuntu Server 12.04 LTS 64bit / node.js 0.8.12

やること

  • node.jsを起動するための専用のユーザを追加する
  • node.jsをrootで起動して80番をlistenしてから上記で追加したユーザのuidに切り替える

グループとユーザの追加

最初にグループの追加と、続いてユーザの追加をします。

$ sudo addgroup --gid 1001 node

nodeというグループを追加しています。gidは指定しないと勝手に指定してくれるんだったかな?
sasaplus1グループが1000だったのでここでは1001を指定しました。


次にユーザの追加です。

$ sudo adduser  \
> --uid 1001  \
> --gid 1001  \
> --no-create-home  \
> --disabled-password  \
> --disabled-login  \
> --shell /bin/false \
> node

nodeというユーザを追加しています。これもsasaplus1ユーザが1000だったので1001を指定しました。
グループは先ほど追加したグループのgidを指定しています。名前でも良かったような気がするんですが、名前で指定したら怒られました。(もしかしたらオプションの入力間違いとか別の理由で怒られたのかも)
node.jsからはuidが使えれば良いので、乗っ取られても何も出来ないように、シェルからのログインを無効化しています。
CentOSなどのサンプルだと/sbin/nologinが多いような気がします。

$ groups node
$ id node

などで確認するのもよいでしょう。

80番ポートをlistenした後にuidを変更するコード

最後にコードと、起動方法を。

index.js
#!/usr/bin/env node

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {
    'content-type': 'text/plain; charset=utf-8'
  });
  res.end('Hello, World!');
}).listen(80, function () {
  process.setuid && process.setuid('node');
  // process.setuid(1001);
  // でもOKです。
  // むしろ文字列で指定すると、数値によるIDの解決できるまでブロックするらしいので、
  // 数値の方が良いのかも。まあ、解決にそこまで時間かからないと思うけど。
});

上記のコードを用意したら、後は実行するだけです。

$ sudo "`which node`" index.js

でOKなはず。whichでnode.jsの場所を指定しているのは、nodebrewでnode.jsを入れていたからで、
本来なら/usr/localやら/optやらにインストールしたnode.jsのパスを書いてあげた方が良いです。


chown, chmodもした方が良いのかな?とこれを書いていて気がついたりとか。

$ sudo chown node:node index.js
$ sudo chmod 0755 index.js


とまあ、こんな感じでしょうか。とりあえずrootで起動してそのまま、というよりかはずっと良いよいはず……