Nginxでレスポンスヘッダの一部を隠蔽する方法
はじめに
拡張モジュールが導入されていないNginxでは、バージョンを隠すことはできますが、Nginxを使っていること自体は隠すことができません。
レスポンスヘッダには使用しているサーバ(Apache/Nginxなど)の他にも色々な情報が載っています。中にはセキュリティ上問題となる情報が含まれていることもあります(例えばApacheではデフォルトの設定だとOpenSSLのバージョンが表示されていたりします)
Nginxはデフォルトの設定のままでもセキュリティ的に大きな問題はないですが、レスポンスヘッダは攻撃者の良い材料ともなり得るので、できるだけ不要な情報は隠すことが望ましいです。
ここでは、Nginxでレスポンスヘッダの情報をできるかぎり隠蔽する方法を説明します。以下の説明では状況に応じてsudo
をつけてください。
TL;DR
$ wget https://nginx.org/download/nginx-X.XX.X.tar.gz
$ tar -xzvf nginx-X.XX.X.tar.gz
$ wget https://github.com/openresty/headers-more-nginx-module/archive/vX.XX.tar.gz
$ tar -xzvf vX.XX.tar.gz
$ cd nginx-X.XX.X
$ ./configure --add-dynamic-module=拡張モジュールをインストールしたディレクトリのパス/headers-more-nginx-module-X.XX --with-http_ssl_module --with-http_v2_module
$ make
$ sudo make install
X.XX.X
や X.XX
にはそれぞれ Nginx や 拡張モジュールのバージョンが入る。Nginx のバージョンについては公式サイトのダウンロードページ、拡張モジュールのバージョンについてはGitHubのページを参照のこと。
load_module /usr/local/nginx/modules/ngx_http_headers_more_filter_module.so;
http {
server_tokens off;
more_clear_headers Server;
more_clear_headers ETag;
more_clear_headers Transfer-Encoding;
more_clear_headers Date;
more_clear_headers Status;
more_clear_headers X-Request-Id;
more_clear_headers X-Runtime;
more_clear_headers X-UA-Compatible;
more_clear_headers Cache-Control;
more_clear_headers Connection;
more_clear_headers X-Powered-By;
# 以下省略
}
export PATH="/usr/local/nginx/sbin:$PATH"
$ source ~/.bashrc
$ sudo visudo
- Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
+ Defaults secure_path = /sbin:/bin:/usr/local/nginx/sbin:/usr/sbin:/usr/bin
$ sudo nginx # すでに起動している場合は $ sudo nginx -s reload
$ curl -I ドメイン名
HTTP/1.1 200 OK
Content-Type: text/html
... # 指定のレスポンスヘッダが隠蔽されていればOK
ソースからビルド
大前提として、Nginxでレスポンスヘッダを編集するには拡張モジュールが必要となります。そしてこの拡張モジュールは、Nginxをソースからビルドして追加する必要があります。
公式サイトからダウンロードします。
$ wget https://nginx.org/download/nginx-X.XX.X.tar.gz
:warning: X.XX.X
の箇所はNginxのバージョンを指定してください。バージョンは公式サイトのダウンロードページから確認できます。Stable version (安定版) か Mainline version (最新版) のどちらかのバージョンを選んでください。
ダウンロードした圧縮ファイルを展開します。
$ tar -xzvf nginx-X.XX.X.tar.gz
次に、レスポンスヘッダを編集するための拡張モジュールをダウンロードします。headers-more-nginx-module を使用します。
$ wget https://github.com/openresty/headers-more-nginx-module/archive/vX.XX.tar.gz
:warning: vX.XX.tar.gz
には拡張モジュールの最新版をバージョンを入れてください。最新版のバージョンはGitHubのページから確認できます。たとえば、v0.31.tar.gz
のような形式です。
ダウンロードした圧縮ファイルを展開します。
$ tar -xzvf vX.XX.tar.gz
展開したNginxのディレクトリに移動します。
$ cd nginx-X.XX.X
移動したら以下のコマンドを実行します。こちらはSSL/TLS通信(HTTPS通信)を使わない人向けです。
$ ./configure --add-dynamic-module=拡張モジュールをインストールしたディレクトリのパス/headers-more-nginx-module-X.XX
こちらはSSL/TLS通信を使う人向けです。
$ ./configure --add-dynamic-module=拡張モジュールをインストールしたディレクトリのパス/headers-more-nginx-module-X.XX --with-http_ssl_module --with-http_v2_module
HTTP/2を使わない人は--with-http_v2_module
を外しても良いですが、せっかくSSL/TLS対応しているのであればHTTP/2にも対応したほうがオトクです。
ちなみに上記コマンドでは/usr/local
以下にNginxがインストールされます。場所は変更しなくて良いですが、変えたい場合は--prefix=インストールしたいパス
を追加してください。ただし別の場所にインストールした場合は、モジュールをあとから追加する際に毎回--prefix
オプションを付けなければいけないことに注意してください。なお、以下の説明では/usr/local
にインストールされたものとして説明します。
上記コマンドを実行したら続けて以下のコマンドを実行します。
$ make
$ sudo make install
これで/usr/local
に、拡張モジュール付きでNginxがインストールされます。ちなみに拡張モジュールは/usr/local/nginx/modules
以下に置かれます。
参考: headers-more-nginx-module - GitHub
レスポンスヘッダを隠蔽
Nginxの設定ファイルにレスポンスヘッダを隠す設定を追加していきます。まずは拡張モジュールを読み込まないといけないので、ディレクティブの外({}
で囲まれていない外の部分)に以下の一行を追加します。ディレクティブの外ならどこでも良いですが、わかりやすいようにファイルの最初の辺りに書いておくと良いです。
load_module /usr/local/nginx/modules/ngx_http_headers_more_filter_module.so;
:warning: /usr/local
以外にインストールした場合は適宜パスを変更してください
次にレスポンスヘッダを隠す設定を追加します。レスポンスヘッダにはサイトによって色々な情報が含まれますので、実際には他にもたくさん設定があります。以下はその一例です。詳しくはリポジトリを参照してください。また、レスポンスヘッダ情報によっては隠してしまうとアプリケーションが正しく機能しなくなる可能性があるので注意してください。Railsではmore_clear_headers Content-Type;
を追加するとうまく動きませんでした。適宜、環境に合わせて編集してください。
http
ディレクティブ(http { }
内のどこか)に以下を追加します。
http {
server_tokens off;
more_clear_headers Server;
more_clear_headers ETag;
more_clear_headers Transfer-Encoding;
more_clear_headers Date;
more_clear_headers Status;
more_clear_headers X-Request-Id;
more_clear_headers X-Runtime;
more_clear_headers X-UA-Compatible;
more_clear_headers Cache-Control;
more_clear_headers Connection;
more_clear_headers X-Powered-By;
# more_clear_headers Content-Type;
# 以下省略
}
more_clear_headers
で各レスポンスヘッダ情報を隠します。server_tokens
はNginxのバージョンを表示するかどうかです。なお、server_tokens
に関してはソースからビルドしなくても(拡張モジュールを使用しなくても)使用できます。
パスを通す
すでにNginxをyum
やapt
でインストール済みの場合は、nginx
コマンドがそちらのパスを参照するようになっていることが多いです。
$ which nginx
/usr/sbin/nginx # パッケージからインストールしたNginxを参照してしまっている
なので、nginx
コマンドを、今回インストールしたほうを使うようにします。既存のNginxを削除すれば、誤って元のNginxを操作してしまう可能性が減ります。
# 実行しない!!
$ sudo yum -y remove nginx
# 実行しない!!
$ sudo apt -y purge nginx
ただし、削除してしまうと一緒に設定ファイル等も削除されてしまうので、設定ファイル等をあらかじめバックアップしておく必要があります。
また、万一ソースからビルドしたNginxでうまくいかない場合、先に既存のNginxを削除してしまうと色々と厄介です。
さらに、既存のNginxを削除したとしてもそのままではパスが通っていないので、結局はパスを通すことになります。
$ which nginx
# パスが見つからない!
なので既存のNginxを削除するのはすべての作業が終わってからでも十分です。
Nginxをすでにインストールしていてもいなくても、パスを通す必要があります。以下のように、$PATH
よりも前に/usr/local/nginx/sbin
が来るようにパスを設定してください。これは、既存のNginxが参照されてしまうことを避けるためです。
export PATH="/usr/local/nginx/sbin:$PATH"
追加したら設定を反映させます。
$ source ~/.bashrc
nginx
のパスを確認して、/usr/local/nginx/sbin/nginx
となっていればOKです。
$ which nginx
/usr/local/nginx/sbin/nginx # OK!
また、nginx
コマンドはroot権限で実行することが多いので、sudo
をつけたときにも同じようにパスが通るようにする必要があります。以下のコマンドでroot権限での設定を変更します。
$ sudo visudo
vim
などのエディタが立ち上がるので、以下の一行を探してください。
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
:warning: パスはOSによって異なる場合があります。
すでにあるパスに対して元々のNginxがあるパス(/usr/sbin
)より前に/usr/local/nginx/sbin
を追加します。元々のNginxがなければ(インストールしてなければ)末尾に追加しても問題ないです。
Defaults secure_path = /sbin:/bin:/usr/local/nginx/sbin:/usr/sbin:/usr/bin
:warning: このファイルはかなり特別なファイルなので、くれぐれもタイプミスをしないように注意してください。特に:
を忘れないように!
これでsudo
を使ったときでも/usr/local/nginx/sbin
にパスが通るようになります。
参考: 【Linux】「sudo: service: command not found」というエラーが出た場合の対処法
Nginxを起動
それではいよいよ起動します。よく使うコマンド一覧です。
$ sudo nginx # 起動
$ sudo nginx -s reload # リロード
$ sudo nginx -s stop # 終了
何もメッセージが表示されなければ起動成功です。
確認
ただサーバが起動しただけではレスポンスヘッダが隠せているかどうかがわからないので、実際に確認してみましょう。ここでは2種類の確認方法を紹介します。
ディベロッパーツールを使用する
Google Chrome を例に紹介します。他のブラウザの場合は各自で調べてみてください。ディベロッパーツールを開くには、WindowsではF12
, Macでは command + option + i
です。もしくは右クリックの「検証」でも開けます。
ディベロッパーツールを開いたらNetwork
タブを開きます。開いたら一度ページをリロードする必要があります。リロードしたら、左側にたくさんのファイル名が出てくると思いますが、一番上(example.com
やindex.html
やURLのパス名などになっている)のものをクリックします。
すると以下のように表示されます。
ここの Response Headers
となっている部分がレスポンスヘッダになります。これがサーバからクライアント側に送られるサーバ情報ですね。ここに、Nginxで設定したレスポンスヘッダが表示されていなければ成功です!
cURLを使用する
curl
コマンドを使用するとサーバからのレスポンス情報が確認できます。
$ curl -I ドメイン名
:warning: http://
でリクエストがあった際にhttps://
にリダイレクトするような設定にしている場合は明示的にhttps://
と入力する必要があります。
$ curl -I https://noraworld.jp
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 2915
Connection: keep-alive
Cache-Control:
Strict-Transport-Security: max-age=31536000; includeSubDomains;
ブラウザで確認したのと似たような結果が返ってきます。ここにNginxで設定したレスポンスヘッダが表示されていなければOKです!
拡張機能を使用する
これはレスポンスヘッダを確認するわけではないのであくまで参考程度ですが、個人的に好きな拡張機能なのでおまけとして載せておきます。
Wappalyzerを使用すると、そのサイトでどのようなサーバ、アプリケーション等が使われているかが簡単に確認できます。
Google Chrome では Chrome Web Store からインストールできます。
インストールすると拡張機能の欄にアイコンが追加されます。調べたいサイトにアクセスしたときに表示された内容が、そのサイトで使われているサーバやアプリケーションになります。
たとえばQiitaではこんな感じ。
レスポンスヘッダを確認するというよりは使われているアプリケーションを調べるツールですが、ここにNginxという表記がなければServer
は隠せていることになります。また、Expressなどを使用しているサイトではX-Powered-By
を隠すことにより解析できない(表示されない)ようになります。
余談ですが、ここにバージョン等が表示されていたら少し気をつける必要があります。
その他
既存のNginxから設定ファイルをコピーしてきた場合は、パスなどに注意する必要があります。たとえば自分の場合は、SSL/TLS通信で使用するDH鍵(ssl_dhparam
)のパスが変わったのに気が付かずにエラーになりました。他にも404エラーページのHTMLのパスなどが変わることがありますので、既存のNginxの設定を引き継ぐ際はご注意ください。
Discussion