一番近いところは逆に接続できない?
事務所や自宅でサーバーを立ち上げたら、ネットワーク設定によって、外から正常にアクセスできたのに、LAN内部のPCからサーバーに接続できないという謎現象が発生する場合があります。
その動作を説明するために、以下の状況を仮定します。
PC | 192.168.0.10 |
サーバー | 192.168.0.11 |
外部IP | 1.1.1.1 |
原因
ブラウザーでドメインネームを入力したら、まずDNSからそのドメインのIPアドレスを取得します。ここは1.1.1.1とし、PCから以下のようなパケットが生成されます。
from | 192.168.0.10 |
to | 1.1.1.1 |
port | 80 |
このパケット自体は問題なくスイッチ、ルーターに送信できますが、1.1.1.1であるルーターの外部ポートに到達したら、NAT変換によってパケットヘッダーが書き換えられて、本当のサーバーに送信されます。
from | 192.168.0.10 |
to | 192.168.0.11 |
port | 80 |
次はサーバーがパケットの内容を処理して、送信元であるPCのアドレス宛に返信をします。
from | 192.168.0.11 |
to | 192.168.0.10 |
port | 80 |
ここが問題。
ルーターが送信元と送信先が同じLANのアドレスであることを認識して、外部ポートを経由せずに、スイッチハブ部分だけの処理でパケットを捌いてしまいます。
つまりこのパケットはそのままPCに転送されることです。この場合、PCがパケットを受け取って、自分が1.1.1.1に送信したのに、なんか知らないアドレスから返信が来たので、無効なパケットだと判断して、このパケットを捨ててしまいます。
もちろんその後1.1.1.1からの返信はいつまでも来ないので、接続がタイムアウトになります。
対処方法
原因が分かったら、対処は簡単です。
LANのIPアドレスでアクセスする
同じLANにあるなら、当然LANのアドレスで直接サーバーにアクセスすることができます。
ただし,ウェブサイトがHTTPS化している場合、SSL証明書はドメインにバインドしているため、直接IPでアクセスするとブラウザーに安全ではないと怒られるので、ストレスが溜まるしかない。
内部DNS
次の考えはドメインネームを内部IPにバンドする方法。もちろん外のDNSにローカルIPを設定するわけがないので、LAN内部でDNSサーバーを立ち上げて、LAN内のPCはそれを利用するようにする必要があります。
また、OSがこの「よくある問題」を解決するためにすでに似たような機能を提供しています。それはhostsファイル。ブラウザーにドメインネームを入力したら、外部DNSまでIPを探しに行く前に、先にhostsファイルにIPの記録があるか調べて、存在するなら外部DNSに頼らずそこのIPを利用します。
Windowsを例に言うと、(C:\Windows\System32\drivers\etc\hosts)に
ドメインネーム サーバーのローカルIP
を登録すればドメインネームから接続できるようになります。
ルーターに両方向NAT変換を設定する
何かの理由でいちいちPCのhostsファイルを弄りたくない場合、ルーターが返信を転送するとき、外部ポートを経由しない問題を何とかする方法もあります。
それはルーターのVlan設定にこのようなNATルールを追加して
nat server protocol tcp global 1.1.1.1 80 inside 192.168.0.11 80
サーバーからのパケットが必ず外部ポートにNAT変換するように設定します。これでルーターが外部ポートの1.1.1.1をソースとしてPCにパケットを送るので、外部からと同じく正常に接続できます。