ついさっきまでこのサイトはIPアドレス指定でアクセスできてしまっていたのですが、弾くようにしました。

やり方


はじめはこの投稿を参考にしていたのですが、その中で言及されていた 公式ドキュメントのほうがちゃんとしてそうだったので、最終的に公式ドキュメントをもとに設定しました。

記述のないドメインへのアクセスを判定する

nginxの設定ファイルに記載していないserver_nameへのアクセスを全て弾けばよいのですが、どうすればよいのでしょうか。ドキュメントには下記のように書いてあります。

In catch-all server examples the strange name “_” can be seen. There is nothing special about this name, it is just one of a myriad of invalid domain names which never intersect with any real name. Other invalid names like “–” and “!@#” may equally be used.

というわけでserver_name_を指定します。--とか!@#でもいいみたいですね。

ステータスコード

なお、この際のステータスコードはどうすればいいのか?これは要件によって変わると思います。リダイレクトさせるのもありでしょう。

今回はすべて防ぎたかったのですが、そうなると404?でもそれもどうなのかな?と思ったところ、前述の公式ドキュメントのサンプルは444を指定してました。

444はnginx独自のステータスコードでレスポンスヘッダを返さずにコネクションを切るらしいです。下記の解説がわかりやすいですね。

nginxのステータスコード444

設定


というわけで設定してみます。nginx.confに以下を記述しました。conf.dとかsites-availableのdefault設定を読み込んでいる場合もあると思うのでその辺りも留意する必要があります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80 default_server;
server_name _;
return 444;
}

server {
listen 443 default_server;
server_name _;
ssl on;
ssl_certificate ${ssl.pem};
ssl_certificate_key ${ssl.key};
return 444;
}

httpsの方は証明書を指定しないと下記のような感じでエラーが発生しnginxが起動できません。

1
2
3
4
5
6
systemd[1]: Starting nginx - high performance web server...
nginx[10564]: nginx: [emerg] no "ssl_certificate" is defined for the "ssl" directive in /etc/nginx/nginx.conf:47
systemd[1]: nginx.service: Control process exited, code=exited status=1
systemd[1]: Failed to start nginx - high performance web server.
systemd[1]: nginx.service: Unit entered failed state.
systemd[1]: nginx.service: Failed with result 'exit-code'.

証明書はドメインで使用しているものと同じものを指定しました。たぶん問題ないと思います…。

アクセスしてみる


設定がうまくいっている場合はIPで直接アクセスした場合に下記のように表示されると思います。

以上です。