二人の所有者、一つのアドレス:TAPブリッジ上のIP重複
先に接続したときだけアドレスを保つVPNクライアントは、競争ではなくARP競合に負けている。ブリッジ上のアドレスの所有者をすべて洗い出す。
一台のWindowsクライアントが10.8.0.2を保持し、起動順序が変わるまで動作する。その後、クライアント側では何も変わっていないのに、同じアドレスが競合として報告される。同じブリッジセグメント上の二台目のホストが同じ値を主張し、構成を最後に終えたマシンがたいてい負ける。両方とも自分が所有していると信じ、負けた側は使うよう指示されたアドレスを静かに使わなくなる。これをタイミングの問題として扱うことこそが、再起動のたびに再発させる原因である。
ブリッジに触れる前に競合の証拠を読む
Windowsはアドレス競合を、もう一方の主張者のハードウェアアドレスとともに報告する。そのハードウェアアドレスこそが有用な事実である。一台のホスト上の一つのインターフェースに対応するのに対し、イベントの表示名は重複がどこにあるかを何も教えてくれない。何かを変更する前にハードウェアアドレスを書き留める。
ARPベースの重複検出は、アドレスが使われる前に競合する所有者を調べ、その後も監視を続ける。だからこそ、ネットワークを構成している間に不在だったホストが一時間後にも競合を起こせる。調査は起動時の一度きりの確認ではない。後から現れたマシンが、一日中静かに使われていたアドレスを取ることがある。だからこの障害は構成エラーではなく競争のように読める。
競合イベントだけでは、どの構成がもう一方の主張を作ったかは分からない。アドレスを実験的に消すと、それを教えてくれた対応関係が壊れる。証拠の目的は、ハードウェアアドレスを検査できるインターフェースに変えることにある。マシン名で台帳を検索すると、たいてい間違ったホストにたどり着く。
セグメント上のすべての主張を洗い出す
ブリッジ化されたTAP構成は、以前は別々だったEthernetセグメントを結合する。そのため、それぞれのネットワーク内では一意だったアドレスも、フレームが一つのリンクを共有した途端に衝突しうる。この障害クラスがVPNにあって、置き換えたルーティングネットワークにないのはそのためである。疑った最初の一台ではなく、考えうるすべての所有者を列挙する。
次の順にリストをたどる。各ブリッジデバイスとそのメンバーポートのアドレス、OpenVPN のプールとクライアントごとの固定割り当て、そしてブリッジセグメントを覆うDHCPサーバーである。そのうえで、競合レポートのハードウェアアドレスを見つけたインターフェースと突き合わせる。
ip -4 addr show | grep -E 'inet |^[0-9]+: '
bridge link show
ip neigh show dev br0
プールとDHCP範囲は、人が忘れがちな二人の所有者である。他のことをする前に、両方の範囲を並べて出力し、重なりを探す。手動で割り当てたブリッジアドレスと、同じ値を払い出すプールは遅かれ早かれ衝突する。両方の範囲を並べて出力するまで、その衝突はランダムに見える。
ブリッジに番号を付けるのは、識別子が必要な場所だけにする
通常のホストブリッジでは、ブリッジデバイスがホストの第三層の構成を持ち、EthernetとTAPのメンバーはポートとして働く。各メンバーに独自のアドレスを与えること、あるいはアドレスを変えずに一つのセットアップスクリプトを複数のマシンにコピーすることが、一つのセグメントに同じ値の所有者を三人も生む原因である。メンバーはフレームを転送するのに自分の識別子を必要としない。必要なのは、そのセグメントで到達可能であるべきホストごとにちょうど一つの識別子だけである。
フレームをスイッチするだけのブリッジには、そのセグメント上のアドレスはまったく要らない。番号を付けずに放置すれば、衝突のクラスを丸ごと排除できる。ただし、ホストに検証済みの管理経路が残っていることが条件である。まずアクセスを確認し、次にアドレスを外し、三番目に到達性を確かめる。
削除しようとしているアドレスがマシンへの唯一の経路なら、実験として削除することは診断ではなく自ら招いた停止である。何かを試す前に帯域外の経路を検証する。
修正を再起動後も残す
稼働中のインターフェースを変えても、直るのは今回の起動だけで他は何も変わらない。起動時にアドレスを作り直すものは何であれ、次の再起動で競合を復活させる。すると修正が効かなかったと結論してしまうが、実際には一度も永続していなかったのだ。どのファイルを変えたかを記録しておけば、次の再起動は驚きを明かすのではなく決定を確認する場になる。
その構成の所有者を探す。ネットワークマネージャーのプロファイル、インターフェースごとのファイル、コンテナやVMの定義、あるいはcloud-initの断片である。そこで変更し、その後、影響を受けたホストを一台意図的に再起動して、新しい値が戻ってくることを確認する。再起動だけが永続性を証明する試験である。
ブリッジのアドレスはDHCP範囲内で除外として予約するか、範囲の外へ移す。表計算ソフトの中にしかない予約は除外ではなく、割り当て側はそれを読まない。
すべてのクライアントをオンラインにして証明する
接続が一回成功しても何の証明にもならない。元の症状は順序が変わったときにだけ現れたからだ。想定するすべてのクライアントを起動し、起動順を変え、再接続の後に繰り返す。そのうえで、以前に競争で負けていたホストを再起動し、アドレスが生き残ることを確認する。
直接確かめるには、アドレスを割り当てる前に重複した所有者がいないか調べ、その後で近隣テーブルを監視する。何も応答せず、完全な再起動サイクルを通じてアドレスが一意に保たれるなら、競合は隠されたのではなく解決している。以下のコマンドはブリッジデバイス上で両方の確認を行う。 RFC 5227 は、これらのツールが実行する調査と告知の挙動を記述しており、検出を無効にしようという提案が出たときに引用すべき参考文献である。
arping -D -I br0 10.8.0.2
ip neigh show dev br0 | grep 10.8.0.2
応答のない調査は、きれいなセグメントでは想定どおりの結果である。応答を引き出す調査は、残っている所有者のハードウェアアドレスを与えてくれる。それは最初にWindowsのイベントが与えてくれたのと同じ証拠である。この出力は変更記録と一緒に保管する。アドレスが一意に保たれていることを示す唯一の証拠だからだ。