僕は自宅のPCを使ってnginxでWebサーバーを立てているのですが、ある時、携帯回線から自分のサーバーにアクセスしたときと、特定のWi-Fiからアクセスしたときで、違うページが表示されてしまうことに気づきました。
具体的には、携帯回線につないているときは自分が意図したページが表示されるのですが、特定のWi-Fiに接続しているときは想定していないページが表示されてしまう状況でした。
最初原因がわからず、頭を抱えていたのですが、とりあえず回線を切り替えると再現することが分かったので、それぞれの回線でPCがサイトにアクセスしたときの挙動を比較してみました。
そこで、あることに気づきました。
携帯回線経由で接続した際はIPv4アドレス経由での接続が行われていたのに対し、例のWi-Fi環境ではIPv6経由でアクセスしていました。
対象のサイトへどちらのアドレスで接続しているかは、nslookupコマンドを使用するとわかります。
nslookup アクセス先のドメイン
結果にIPv4のアドレスが帰ってきたらIPv4、IPv6のアドレスが返ってきたらIPv6で接続していることになります。
ここまでお話すれば察しがつく方もいらっしゃるかもしれません。
nginxの設定ファイルには、各バーチャルホストごとにどのポートで待ち受けるのかを記述する部分があります。
//省略
server {
listen 80; //←これ
listen 443 ssl; //←これ
server_name example.com;
//以下省略
}
このポートの指定、自分のサーバーでは上記のようになっていました。
一見正しい指定のように見えますが、実はこの指定だと、IPv4経由でのアクセスしかカバーされていません。
サーバー自体がIPv4経由でしか到達できない回線に接続されているのであれば問題にはならないのですが、IPv6も利用可能な回線に繋がっている場合、IPv6経由でのアクセスではドメインが一致しても上記のディレクティブにマッチしないため、デフォルトのバーチャルホストが呼ばれてしまうのです。
ネット回線によって表示されるページが異なってしまうのはこれが原因でした。
解決策としては、すべてのバーチャルホストのlisten項目に、IPv6の指定を追加しておくことです。
//省略...
server {
listen 80;
listen [::]:80; //追加
listen 443 ssl;
listen [::]:443 ssl; //追加
server_name example.com;
//省略...
}
これでnginxサーバーがIPv6回線に接続していても、指定したバーチャルホストにちゃんと引っかかるようになりました。
ということで、自分のサーバーがIPv4、IPv6両方で受けられる場合は必要な設定も変わってきますので、注意してください。