FRRoutingによるOSPF動的ルーティングを備えたWireGuard拠点間VPN:Linuxでの複数拠点自動フェイルオーバー

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

昨年11月の午前2時14分、上位回線の光ファイバー切断により、オースティンとシカゴを結ぶメイン回線が突如遮断されました。夜間のPostgreSQL移行作業に従事していた20名のエンジニアが突如アクセスを失ったのです。さらに悪いことに、静的IPsecトンネルはアイドル状態のままで、エンジニアたちはルーティングテーブルを手動で書き換えるため3台のゲートウェイを行き来する羽目になりました。この4時間に及ぶ障害により、デプロイ遅延に伴うダウンタイムで約18,000ドルの損害が発生しました。そしてこれが、インフラチームが静的ルートを完全に廃止する決定打となったのです。

WireGuardは、Open Shortest Path First(OSPF)を実行するFRRouting(FRR)と極めてスマートに連携します。両者を組み合わせることで、隣接リンクの検出、サブ秒単位のハートビートによるリンクヘルス監視、そして手動介入なしでのトラフィック再ルーティングが実現します。私たちはこの構成を、AWSとオンプレミスのベアメタルコロケーションを組み合わせたハイブリッド環境で実際に稼働させています。現在では、アクティブなTCPセッションのパケットロスをゼロに抑えたまま、4秒未満でクリーンにフェイルオーバーが完了します。

クイックスタート:10分以内で構築する最小構成の2拠点セットアップ

この基本構成では、2台のUbuntu 24.04ゲートウェイ(拠点A:オースティン本社、拠点B:シカゴ支社)を暗号化されたポイントツーポイントトンネルで接続し、OSPFによるルート交換を行います。

1. ネットワークトポロジとIPアドレス設計

  • 拠点A(本社):パブリックWAN 203.0.113.10、ローカルLAN 10.10.0.0/24、トンネルIP 10.255.255.1/30
  • 拠点B(支社):パブリックWAN 198.51.100.20、ローカルLAN 10.20.0.0/24、トンネルIP 10.255.255.2/30
  • オペレーティングシステム:Ubuntu 22.04または24.04 LTS(カーネル 5.15以降)

2. WireGuardトンネルの設定

まず、両方のホストにWireGuardをインストールし、暗号化キーを生成します。

sudo apt update && sudo apt install -y wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey

拠点A(本社)で、以下の内容を /etc/wireguard/wg0.conf に保存します。Table = off という設定に注目してください。この設定により、全宛先(catch-all)ピア定義を処理する際に wg-quick がシステムのデフォルトゲートウェイを上書きするのを防ぎます。

[Interface]
PrivateKey = <拠点Aの秘密鍵>
Address = 10.255.255.1/30
ListenPort = 51820
Table = off
MTU = 1420

[Peer]
PublicKey = <拠点Bの公開鍵>
Endpoint = 198.51.100.20:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 15

拠点B(支社)でも、同様に /etc/wireguard/wg0.conf 内に対称となる設定を記述します。

[Interface]
PrivateKey = <拠点Bの秘密鍵>
Address = 10.255.255.2/30
ListenPort = 51820
Table = off
MTU = 1420

[Peer]
PublicKey = <拠点Aの公開鍵>
Endpoint = 203.0.113.10:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 15

カーネルのパケット転送を有効化し、トンネルを起動します。

echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-router.conf
sudo sysctl --system
sudo systemctl enable --now wg-quick@wg0

3. FRRouting OSPFの起動

FRRスイートをインストールし、OSPFルーティングデーモンを有効化します。

sudo apt install -y frr frr-pythontools
sudo sed -i 's/ospfd=no/ospfd=yes/' /etc/frr/daemons
sudo systemctl restart frr

拠点Aで sudo vtysh を実行してFRR統合シェルを起動し、以下の設定ディレクティブを入力します。

configure terminal
interface wg0
 ip ospf network point-to-point
 ip ospf area 0
exit
router ospf
 ospf router-id 10.255.255.1
 network 10.10.0.0/24 area 0
exit
do write
exit

次に、拠点Bの sudo vtysh プロンプト内でも対応する設定を適用します。

configure terminal
interface wg0
 ip ospf network point-to-point
 ip ospf area 0
exit
router ospf
 ospf router-id 10.255.255.2
 network 10.20.0.0/24 area 0
exit
do write
exit

シェルから直接ネイバーの確立を確認します。

sudo vtysh -c "show ip ospf neighbor"

ネイバー状態は3秒未満で Init から Full/ - へと遷移します。Zebraは直ちにリモートサブネット(10.20.0.0/24)をLinuxカーネルのルーティングテーブルに登録します。

詳細解説:WireGuardが従来の動的ルーティングと衝突する理由

WireGuardは、標準的なダミーTUNやGREインターフェースのようには動作しません。「Cryptokey Routing(暗号鍵ルーティング)」エンジンとして機能します。送信パケットは、WireGuardが暗号化してピアに送信する前に、AllowedIPs 内の明示的なサブネットと一致している必要があります。

マルチキャストの問題

OSPFは、224.0.0.5(全OSPFルーター宛)および 224.0.0.6(指定ルーター宛)に送信されるリンクローカルマルチキャストトラフィックに大きく依存しています。多くのエンジニアは、AllowedIPs を 10.255.255.2/32, 10.20.0.0/24 のような明示的なサブネットに限定しようとします。しかしその設定では、WireGuardはすべてのマルチキャストパケットを警告なしに破棄してしまいます。

暗号ハンドシェイク自体は成功し、wg show のカウンターも正常に増加します。しかし、OSPFネイバーが形成されることはありません。Table = off と併せて AllowedIPs = 0.0.0.0/0 を設定することで、この障壁を解決できます。これにより、暗号検証チェックをマルチキャストパケットが通過できるようになり、実際の転送判断をFRRに委ねることが可能になります。

ポイントツーポイントモードが必須である理由

OSPFは、非シリアルインターフェース上ではデフォルトでブロードキャストネットワークのセマンティクスを採用します。ブロードキャストモードでは、OSPFはDesignated Router(DR:指定ルーター)とBackup Designated Router(BDR:バックアップ指定ルーター)を選出します。VPNトンネル上では、この選出処理によって不要な40秒のレイテンシが発生し、わずかなパケットジッターでも選出のフラッピングが引き起こされる可能性があります。

ip ospf network point-to-point を実行すると、そのリンクを共有しているノードが正確に2台だけであることがOSPFに伝達されます。これによりDR/BDRの選出が完全にスキップされ、アジャセンシーが即座に形成され、復旧時間は40秒からサブ秒レベルにまで短縮されます。

高度な構成:コストベースのフェイルオーバーを備えた複数拠点メッシュ

本番環境ではルートの冗長性が不可欠です。オースティン本社、シカゴ第1支社、デンバー第2支社を接続する三角トポロジを考えてみましょう。オースティンは1 Gbpsの光ファイバーを介して大容量トラフィックを処理します。緊急時の冗長化のため、200 Mbpsのセカンダリブロードバンドトンネルがシカゴとデンバーを直接結んでいます。

        +-----------------------+
        |     オースティン本社 (HQ)   |
        |      10.10.0.0/24     |
        +-----------------------+
             /              \
   wg0 (コスト 10)         wg1 (コスト 10)
           /                  \
+-------------------+  wg2 (コスト 50)  +-------------------+
|   シカゴ (支社)    |==================|   デンバー (支社)   |
|   10.20.0.0/24    |                  |   10.30.0.0/24    |
+-------------------+                  +-------------------+

タイマーとメトリックコストのチューニング

プライマリの光回線リンクには低いメトリックを、拠点間トンネルには高いメトリックを割り当てます。また、障害検知を高速化するためにHelloインターバルとDeadインターバルを短縮します。

シカゴのゲートウェイ上で、vtysh からインターフェースパラメータを設定します。

configure terminal
interface wg0
 description オースティン本社へのアップリンク
 ip ospf cost 10
 ip ospf dead-interval 4
 ip ospf hello-interval 1
exit
interface wg2
 description デンバーへの拠点間バックアップ
 ip ospf cost 50
 ip ospf dead-interval 4
 ip ospf hello-interval 1
exit
do write

Helloインターバルを1秒、Deadタイマーを4秒に設定することで、FRRは4回のハートビート喪失で回線切断を検知します。オースティンがオフラインになった場合、FRRは即座にShortest Path First(SPF)ルートを再計算します。トラフィックは4.2秒で wg2 を経由してデンバーへとルーティングされ、長時間実行されているデータベースクエリのTCPセッション切断を防ぎます。

本番環境向けの堅牢化とトラブルシューティング

1. 安全なMTUサイジングによるDBDパケットのフラグメンテーション防止

WireGuard内部でパケットをカプセル化すると、IPv4で60バイト(IPヘッダー20バイト + UDPヘッダー8バイト + WireGuardヘッダー32バイト)、IPv6で80バイトのオーバーヘッドが追加されます。WANのMTUが1500の場合、wg0 にMTU 1500を設定するとパケットのフラグメンテーションが強制的に発生します。

サイズの大きいOSPFデータベース記述(DBD)パケットは同期中に断片化されます。多くのクラウドトランジットファイアウォールは、断片化されたUDPパケットを即座に破棄します。これが発生すると、OSPFネイバーは ExStart または Exchange 状態で無期限にハングします。[Interface] 内でトンネルのMTUを明示的に 1420 に設定し、あらゆる上位キャリア経由でもクリーンに通過できるようにしてください。

2. NATセッションの維持

AWS NAT Gatewayやローカルのエンタープライズファイアウォールの背後で稼働しているゲートウェイは、30〜60秒のアイドル状態でUDPセッションマッピングを破棄します。すべてのリモートピア定義に PersistentKeepalive = 15 を追加してください。この設定により、15秒ごとに暗号化された空パケットが送信され、ステートフルファイアウォールのポートが常時開放状態に保たれます。

3. インシデント切り分けの3ステップ

自動ルートアラートが発生した場合は、以下のシーケンスに沿ってネットワークスタックを正確に切り分けます。

# 1. 暗号トランスポートとハンドシェイク経過時間の確認
sudo wg show wg0 latest-handshakes

# 2. ルーティングアジャセンシーとステートマシンの確認
sudo vtysh -c "show ip ospf neighbor"

# 3. カーネルルーティングテーブルの登録確認
ip route show proto ospf

ハンドシェイクが120秒以上前のものである場合は、まずUDPポート51820の到達性をトラブルシューティングしてください。ハンドシェイクが最近行われているにもかかわらずネイバーが ExStart のまま留まっている場合は、両拠点でMTUが一致しているか確認します。ネイバー状態が Full/ - と表示されている場合は、ip route show proto ospf を確認して、zebraがLinuxカーネルテーブルに正常にルートを反映させているかを検証してください。

Share: