OpenVPNとFRR(OSPF)を組み合わせた多拠点VPNルーティングの限界と学び
背景 複数拠点(A, B, Cなど)を OpenVPN 経由で接続し、 **2系統のVPNトンネル(10.8.0.0/24 と 10.10.0.0/24)**を経由して経路冗長化したい。(openvpnサーバは独立した2マシン) そんなニーズから検証を始めました。 各拠点はそれぞれローカルLAN(例: 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24)を持ち、 それらを OSPF (FRRouting) で自動経路学習させて、 VPNトンネル越しに相互通信できるようにしたい、という構成です。 やりたかったこと OpenVPNで各拠点を接続(多拠点site-to-site VPN) FRR (OSPF) を使って動的ルーティング トンネルごとにコストを設定して経路選択 できれば route-nopull で手動ルーティングを制御 目標は「OpenVPNトンネルを2本走らせて、FRRで経路選択を任せる」ことでした。 これを実現するにあたり、色々とハマったので知見をまとめておこうと思います。 OpenVPNのルーティングの構造 OpenVPNはユーザランドで動作し、/dev/net/tun デバイスを通じて通信します。 Linuxカーネルはtunデバイスにパケットを出す そこから先は**OpenVPNプロセス(ユーザランド)**が受け取り、独自の内部ルーティングテーブルで転送を行う つまり、Linuxのルーティングテーブル(ip route)とは別世界で動いています。(ここが非常に大事です。openvpnサーバないのルーティングテーブルがちゃんと設定されていないと、クライアントから届いたパケットをどのクライアントに転送すればいいかがわかりません。ちなみに、openvpnのルーティングテーブルは/var/log/openvpn-status.logから確認可能です) push と route-nopull の関係 OpenVPNサーバはクライアントに対して push “route …” を送ることで、 クライアントのOSにもユーザランドにもルート情報を注入します。 一方、クライアント設定で route-nopull を有効にすると、 その push 情報をすべて拒否します。 frrでルーティングをさせたい場合には、route-nopullにしておかないと、0.0.0.0/1と128.0.0.1/1がOSのルーティングテーブルに登録され、すべてのパケットが特定のnicから出るように設定されてしまうので注意が必要(server側で**push “redirect-gateway def1 bypass-dhcp”**が入っている場合) FRR(OSPF)を組み合わせても解決しない理由 FRRでOSPFを走らせると、 VPNトンネル越しに相手拠点のLAN情報(例: 192.168.x.x/24)が学習されます。 これにより、OSレベルのルーティングテーブルは更新されます。 しかし! OpenVPNサーバはそのOSルートを全く参照しません。 OpenVPNプロセスは独自に「このLANはどのクライアントの背後にあるか」を iroute で知っていなければ、パケットをどこに転送すべきか判断できません。 自分の場合は、openvpnサーバの/etc/openvpn/ccd以下に書くルーティングファイルの情報が間違っており、クライアント1 -> サーバはパケットが届いていたが、サーバがクライアント2宛のパケットをうまく転送できずdropしてしまっていたのが原因ですね。 ...