外部からポートスキャンをされて、攻撃のターゲットにならないように、不要な3000番ポートを閉じたのですが、そのときのNginxの設定変更で2日間もハマってしまったので、一生忘れないようにするためにメモ!!
Nginxの設定ですが、当初は下記のような設定をしていました。
##設定
server {
listen 80; #ポート番号を指定
server_name ホスト名 #このホスト名に一致したリクエストの場合に、serverブロック(server {})が適用される
# nginx so increasing this is generally safe...
keepalive_timeout 5;
# path for static files
root /var/www/rails/sample_app/public;
# page cache loading
try_files $uri/index.html $uri.html $uri @app;
location @app {
# HTTP headers
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://IPアドレス:3000; #3000番ポートに中継して、Unicornにリクエストを転送
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/rails/sample_app/public;
}
}
##エラー内容・問題
3000番ポートを閉じてからサーバーにリクエストを送って本番環境へのアクセスを試みると、Nginxの500エラーページが出ている。つまりUnicornまでリクエストが届いていない状態になっていた。
3000番ポートを閉じたと言っても、今まで本番環境へアクセスする時は80番ポート経由でアクセスしていたから、これまで使ってこなかった3000番ポートを閉じても影響は出ないはずでは。。。と2日間もハマってしまいました。
結論から言うと、外部アドレスにアクセスしようとしていたことが原因でした。
##リクエストがサーバーに届くまでの流れ
この図の中で、私の理解が欠落していた部分は、DNSサーバーとルーターの存在でした。クライアントからのリクエスト送信先は、IPアドレスによって特定されます。
IPアドレスは人間にとっては見にくい表示形態なので、その多くはドメインを適用することで人間が見やすい文字列にしています。
裏を返すと、コンピュータからすると、ドメインの文字列はとても見にくくて、処理しにくい表示形態なので、ドメインではリクエスト送信先を特定することができません。なので、DNSサーバーに問い合わせて、リクエストとして指定された宛先であるドメインが示しているIPアドレスを特定します。いわばドメインをIPアドレスに変換しているようなイメージです。
IPアドレスが特定されると、ルーターを通して、外部ネットワークにデータが送信され、様々なルーターを経て最終的に、IPアドレスに示された送信先にデータが到着する、という流れです。
HTTPの仕組みについては、下記参照
https://chopesu.com/programing/http/
では、これを踏まえて私が陥っていた状況はどのような状況だったかを示しているのが、下記の図です。
このように、Nginxが受け取ったリクエストを同一サーバー内のUnicornに転送するという設定をしているつもりでしたが、実際は外部アドレスに転送するという設定になっていました。
外部アドレスに転送するという設定にした結果、上記の図のように既に閉じられている3000番ポートでリクエストが遮断され、アクセスすることができない状況になっていました。
##解決策
これを解消する方法はいくつかありますが、今回は転送先であるUnicornが同じサーバーマシン内、つまりlocalhostにあることを利用して、下記のような転送設定にすることで無事に解決することができました!!
server {
listen 80; #ポート番号を指定
server_name ホスト名 #このホスト名に一致したリクエストの場合に、serverブロック(server {})が適用される
# nginx so increasing this is generally safe...
keepalive_timeout 5;
# path for static files
root /var/www/rails/sample_app/public;
# page cache loading
try_files $uri/index.html $uri.html $uri @app;
location @app {
# HTTP headers
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://localhost:3000;
# 3000番ポートを経由して、同一サーバーマシン内(localhost)にあるUnicornにリクエストを転送
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/rails/sample_app/public;
}
}
仕組みを理解していないと、こんなに苦労するものかと思い知らされました笑