今回は、ネットワークの話。
解決してみれば割としょうも無いトラブルで、時間を浪費してしまったので、自戒の意味を込めて記事にしておく。
サブネット外から ping が通らない
ある日、 ホストPC の NIC とブリッジ接続されている VM に、 サブネット外からアクセスできなくなってしまった。
構成を図にすると、以下のような感じ。
(あまり UML図 に明るくないので、書き方がヘタクソだったり本来の意味と違う記号の使い方をしている点は大目に見て欲しい。)
同一サブネット内 (図の "Machine on Same Subnet") から 172.16.42.16 を叩くと VM ゲストに到達するのだが、 サブネット外 (図の "Machine on Different Subnet") からだと ping すら通らない。
以前は同じ構成で、サブネット外から繋がっていたはずだ。
ちょうど直前に、ネットワーク機器のメンテナンスがあったため、 そちらで IPフィルタの動作がおかしくなったのではないかと疑ってしまった。
しかし、繋がらなくなった直接的な原因は、 VM Gurest 側にあった。
このため、答えにたどり着くのに時間がかかってしまった。
アクセスできなかった原因
上の図で若干答えを示唆してしまっているが、 VM Guest に繋がっているもう一つの仮想ネットワークアダプタ (図の "eth0") が原因だ。
この eth0 は NAT 経由でホスト側のネットワークに繋がっていた。
そして、 eth0 の metric が、 eth1 よりも短くなる設定に変更してしまっていたのだ。
(何故そんな繋ぎ方をしているかというと、 ホスト PC の IP として通信させたい事情があったから。 理由は察して。)
構成を図にしてみると、以下のような感じ。
このような構成だと、 VM Guest からの通信は全て、 より『距離が近い』と見做される eth0 と NAT 経由で行われるようになる。
通常、ルータや L3スイッチ などが、 IPアドレス と MACアドレス の対照表である ARP テーブルに載っていない IP のパケットを受け取った場合、 サブネット内に ARP リクエストパケットをブロードキャストして、対象の MACアドレス を探しに行く。
しかし このサブネットの間を取り持っているルータは、どうも ARP テーブルに載っかっていない IP へのパケットを全て破棄してしまうらしい。
(レイヤ3 の知識が不十分なので、正確な説明ではないかも知れないが、雰囲気だけでも伝われば。)
つまり、 VM Guest から eth1 を経由してルータに到達する通信がなかったために、 ルータが eth1 の MACアドレスを知らず、パケットが全て破棄されてしまっていたようだ。
以前通信できていた頃は、 eth0 より eth1 からの通信の方が metric が近かったため、 eth1 からルータを経由してインターネットへ向かう通信が存在し、 ルータが eth1 の MACアドレス を知っていたため、 サブネット外からの通信がちゃんと eth1 に届いていたのだろう。
一方、同一サブネット内の "Machine on Same Subnet" からの通信は、この Machine が直接 ARP リクエストパケットをブロードキャストして、 eth1 の MAC アドレスを見つけられるため、 metric の距離にかかわらず通信できていたのだと思われる。
解決策
VM Guest の eth1 から通信が外に出るように metric の設定を変更して、 適当なパケットを投げたところ、 サブネット外から eth1 の IPアドレスに通信ができるようになった。
ルータがサブネット内の未知の IPアドレス へのパケットを全て握りつぶすというのは、盲点だった。。。