はじめに
nginxは多くのプロダクトやサービスで使用されているのですが、以外にセキュリティーの設定が分かり難かったりする部分があったので調べてみました。
nginxで行うセキュリティー対策は他にも沢山あるのですが、
今回はコンテナとして本番運用する際に絶対にやった方がいい基本的な設定を取り上げました。
公式のドキュメントにもさらっと書いてあるのですが、より詳細に解説していこうと思います。
また、今回はデフォルトのnginxの設定ファイルをベースに解説していきます。
https://hub.docker.com/_/nginx
1. non-rootユーザー(root以外のユーザー)で起動する
nginxを初め、多くのdockerイメージはデフォルトではrootで起動する設定になっています。
rootユーザーはありとあらゆる操作が可能で、万が一このユーザーでコンテナへの侵入を許してしまうと
ホスト側の操作もroot権限で実行できてしまうので非常に危険です。
コンテナだけでなく、基本的にroot権限でサーバーを運用するのは控えるべきです。
nginxユーザーで起動する
実際に以下の様にDockerfileでユーザをnginxに指定してコンテナを作成してました。
FROM nginx:latest
USER 101 #nginxのUID
# USER nignx でも大丈夫です!
イメージのビルドが済んでしまえばroot権限は不要なので、nginxユーザーを指定して起動を試みたのですが以下の様なエラーがでてしまいました。。。
nginx以外のイメージはroot以外のユーザーを作成、指定してあげるだけで起動できる場合が多いのですが、
nginxはそれだけでは起動できないようです。。😑(幸いなことにnginxユーザーはデフォルトで作成されているようです)
- nginxユーザーを指定したときのエラー
docker run -u nginx -p 80:80 nginx:1.17.8-alpine ✘ 1
[warn] 1#1: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
[emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
nginxユーザーで起動できるようにもう少しDockerfileの作成やnginxの設定をしていく必要がありそうですね🤔
順次解説していきたいと思います。
###待ち受けportを変更する
nginxをデフォルトで起動すると、待ち受けのポートとして80番が使用されます。
しかし、0から1023番までのポートはウェルノウンポートと言われ、このポートを使用するためにはroot権限が必要です。(参考:ウェルノウンポートとは)
そのため、nginxをroot権限以外で起動するためには、待ち受けのポートを1024番以降で指定する必要があります。
今回は8080番ポートでnginxが待ち受けられるように以下の例のように/etc/nginx/conf.d/default.confの設定を変更します。
nginxの設定を変更
server {
listen 8080; # <- この部分を変更
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
dockerのポートを変更
先ほどの設定でコンテナの中で起動するnignxのポートは8080番で起動するようになりました。
デフォルトのnginxイメージはコンテナポートが80番で開かられる設定になっているので、こちらもnginxの待ち受けポートである8080番に揃える必要があります。
また、先ほど作成したファイルがimageをbuildする際に取り込めるように設定を追加します。
COPY元のファイル名、パスは任意で構いませんが、COPY先は/etc/nginx/conf.d/default.conf
を指定します。
FROM nginx:latest
COPY default.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080
USER 101
上記の設定でroot権限を必要としないport番号でコンテナを起動できるようになりました!
が、しかし
nginxユーザーでも起動できるようにファイルの権限を設定する
デフォルトのnginxの設定は、pidの情報や各種一時ファイルの出力先がrootユーザーが所有するフォルダになっています。
nginxユーザーだとそれらのファイルに書き込むための権限がないので/tmp
配下など、どのユーザーでも読み書きできるファイルに出力するように設定する必要があります。
具体的には以下のように設定します。
# user nginx; <- マスタープロセスがroot起動時の設定なのでなくても大丈夫です
worker_processes auto;
error_log /var/log/nginx/error.log warn;
#変更前 pid /var/run/nginx.pid;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
##### 追加する設定 #####
proxy_temp_path /tmp/proxy_temp;
client_body_temp_path /tmp/client_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
######################
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
Dockerfile側で上記のファイルが取り込めるように設定を追加します。COPY先は/etc/nginx/nginx.conf
です
また、キャッシュの書き込みが出来るようにnginxユーザーに/var/cache/nginx
への書き込み権限を付与します。
FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
RUN chown -R 101:0 /var/cache/nginx \
&& chmod -R g+w /var/cache/nginx
USER 101
以上の設定でやっとnginxユーザーでコンテナを起動するようにできました🎊
2. Read-Only モードで起動する
dockerにはコンテナを起動する際(runする際)に、read-only
モードを指定することが出来ます。
これを指定することでコンテナへの書き込みが不可能となり、改竄を防止することが出来ます。
以下に先ほど作成したDockerfileをbuildして、read-onlyモードでコンテナを起動するコマンドの例を載せておきます。
docker build -t nginx-non-root:latest .
docker run -p 8080:8080 --read-only -v $(pwd)/tmp:/tmp/ nginx-non-root:latest
所感
振り返ってみると結構設定項目数がありました🤔
設定方法は公式のdockerHubに記載されてはいたのですが、
解説までは無かったので備忘録としてまとめてみました。
不適切な部分や考慮漏れ、もっとこうしたら分かりやすくなる、等ございましたら教えて頂けると嬉しいです。
おまけ
ここまで一生懸命記事を書いたのですが、ここで作成したdocker imageはすでに有志の方が作ってくれています。。。
色々めんどくさい。手っ取り早く設定ファイルが欲しい。という方は以下コマンドで使用することが出来ます🙄
docker pull nginxinc/nginx-unprivileged
DockerHub https://hub.docker.com/r/nginxinc/nginx-unprivileged
GitHub https://github.com/nginxinc/docker-nginx-unprivileged
おまけ2
日々とてもとても有益な情報を発信しています。
Nginxコンテナを本番運用するときのセキュリティー対策よりも重要になる日が来るかもしれません😼
256人彼女が欲しい
— ぐしゃ@ フリーランスクラウドエンジニア (@gusya_the_fool) April 3, 2020