wg show のハンドシェイクは新しく、エンドポイントも正しく、鍵も一度も変わっていないのに、ping は依然としてピアへの経路がないと言う。一時間前にトンネルのサブネットを変更した。この症状は鍵の問題ではなくプレフィックスの不一致の印である。WireGuard はハンドシェイクを完了したあと、送信元アドレスが受信側ピアの受け入れる範囲と一致しなくなったためデータを捨てた。サブネット変更を実施する方法は二つあり、失敗する箇所もそれぞれ違う。

変更を実施する二つの方法と、それぞれのコスト

方法 A はその場での採番し直しである。インターフェースのアドレス、ピアの範囲、経路、設定のすべてのコピーを編集し、再読み込みする。方法 B は新しいプレフィックス上に二つ目のインターフェースを古いものの隣に作り、ピアを移し、通信が実際に移ったところで古いインターフェースを削除する。

A: renumber in placeB: parallel interface
DowntimeThe reload window, per hostNone if peers are added to both
RollbackRe-apply the previous filesPoint peers back at the old interface
RiskHalf-applied change: new address, old rangesTwo live interfaces with overlapping intent
EffortSmall, if the deployment has one ownerHigher, and needs a cleanup step
FitsTwo or three peers you controlMany peers, remote sites, or no maintenance window

方法 A を危険にするのは、中途半端に適用された状態である。壊れて見えないからだ。インターフェースは上がり、ハンドシェイクも成功し、データ経路だけが失敗する。方法 B は手間がかかるが、すべての参照を見つける間も動く経路を生かしておける。

手元で一緒に動かす必要があるもの

ローカルホスト上の四つのものが同じサブネットを表しており、一つを変えることはすべてを変えることになる。インターフェースのアドレス、各ピアの AllowedIPs、システムがその宛先に使う経路、そして管理ツールが代わりに設定するものだ。wg-quick では後ろの二つがインターフェースを上げるたびに設定から生成されるため、古いコピーが古いプレフィックスを静かに戻してしまう。

どちらかを信じるのではなく、設定されているものと実際に動いているものを比べる。

wg show
wg showconf wg0
ip addr show wg0
ip route get 10.90.0.5

経路の照会は人が飛ばしがちな手順だ。カーネルがある宛先に対して実際に何をするかを答え、管理ツールやコンテナ実行環境が残したより具体的な経路も含む。トンネルとは別のインターフェースを返すなら、設定は問題ではない。

稼働中のインターフェースでは、トンネルを壊さずに編集済みファイルを適用する。

wg syncconf wg0 <(wg-quick strip wg0)

これでピアと範囲がその場で更新される。インターフェースのアドレスや経路は更新されない。それらは WireGuard の設定ではないからだ。したがって採番し直しには、インターフェースの再作成か ip によるアドレス変更が依然として必要で、そのあと経路を再確認する。

遠端で一緒に動かす必要があるもの

サブネット変更がたいてい死ぬのはここだ。AllowedIPs は経路のヒントだけではない。ピアが提示を許される送信元アドレスの一覧でもある。クライアントを採番し直してサーバーの AllowedIPs を古いプレフィックスのままにすると、サーバーはハンドシェイクを受け入れ、暗号化されたパケットを受け取り、そのピアに対応づけたどの範囲とも内側の送信元が一致しないため捨てる。エラーは記録されず、クライアント側にはタイムアウトが見える。

だから受信側は意図をもって更新する。サーバーのピア項目に新しいクライアントのプレフィックスを並べ、サーバー自身の戻り経路をそのプレフィックスに対してトンネルへ向け、サーバーの背後の下流ネットワークに新しい経路を学ばせる。古い範囲を名指ししていたファイアウォール規則も同じ扱いが必要で、送信元に基づく選択をするものも同様だ。

二つの失敗を切り分ける診断は安い。ハンドシェイクが新しくデータがないなら、トンネルは上がっていて内側のアドレス設計が食い違っている。ハンドシェイクがまったくないなら、到達性か鍵を見ている。プレフィックスの問題で鍵を回してはいけない。動いていた唯一のものを初期化してしまう。

編集より長生きする古いコピー

ファイルを編集することは稼働中のシステムを変えることと同じではない。コピーは人が思うより多く、 インターフェースを所有するユニットや管理ツール、別のディレクトリにある同じ名前の二つ目のプロファイル、設定をイメージに焼き込んだコンテナ、独自の編集版を保持するルーターの UI、起動時に保存済みトンネルを再インポートするクライアントアプリだ。どれも、変更が完了したように見えたあとで古いプレフィックスを復元しうる。

名前も移動する。数値の経路は動くのにホスト名が失敗するなら、内部 DNS レコードかサービスの設定がまだ古いトンネルアドレスを指している。ピアの範囲をすべて広げるのではなく参照を直すべきだ。広げれば本当の問題を覆い隠し、同時に送信元 ACL まで広げてしまう。

作業中は復旧経路を一つ開けておく。ホストへの二つ目の入り口、シリアルコンソール、設定ファイルの定時ロールバックなどだ。変更しているマシンから自分を締め出すトンネル変更が、この作業を一晩の作業に変える最もよくある道だ。

二つの選択と、切り替えの確認

すべてのピアを自分が持ち、数が少なく、短い停止が許容できるなら A を選ぶ。ピアが自分で制御しない遠隔の人手である場合、拠点間リンクを上げたままにする必要がある場合、すべてのコピーが一度で更新される保証がない場合は B を選ぶ。その場合は新しいプレフィックスを両方のインターフェースに足し、ピアを一つずつ移し、新しい側の通信を見てから、古いインターフェースとその経路を削除する。

どちらの方法でも、四つの確認が通れば変更は完了だ。ハンドシェイクが新しいこと、新しいプレフィックスの宛先への経路照会がトンネルを名指すこと、数百バイトのペイロードが両方向に通ること、そしてホストや管理ツールを再起動したあとも同じであることだ。参照すべきは wg(8) のマニュアル で、AllowedIPs が各方向で何を意味するかを示しており、症状を消すために範囲を広げる前に読み直す価値がある。

  • ハンドシェイクが新しくデータがないなら、鍵に触れる前に受信側の AllowedIPs を見る。
  • 経路照会が別のインターフェースを指すなら、経路を持っているのは管理ツールかコンテナであり、自分のファイルではない。
  • 数値アドレスは良くホスト名が壊れているなら、古い参照であり経路ループではない。
  • 再起動後も新しいプレフィックスを使っていて初めて変更は完了する。

関連記事