LoginSignup
19
11

More than 3 years have passed since last update.

初めてでも大丈夫🙆‍♂️Nginxコンテナを本番運用するときのセキュリティー対策

Posted at

はじめに

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の設定を変更

/etc/nginx/conf.d/default.conf
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配下など、どのユーザーでも読み書きできるファイルに出力するように設定する必要があります。
具体的には以下のように設定します。

/etc/nginx/nginx.conf
# 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コンテナを本番運用するときのセキュリティー対策よりも重要になる日が来るかもしれません😼

19
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
11