OpenVPN iroute とカーネルルート:欠けているのはどちらか
サーバーにはルートがあるのに通信が止まる。経路の判断の一方はカーネルに、もう一方はピアに属する。どちらが欠けているのか、何を確認すべきかを解説します。
10.77.20.0/24 宛てのパケットは、OpenVPN サーバー上で二つの別々の判断を経ます。オペレーティングシステムがそれを VPN インターフェースへ渡す必要があり、OpenVPN はどの接続クライアントがそのプレフィックスを所有しているかを知っている必要があります。カーネルルートが欠けていればトンネルの手前で落ち、ピアルートが欠けていればその後に落ちますが、どちらの障害も遠隔 LAN からは同じに見え、どちらなのかを診断するには両側で一本ずつのコマンドが要ります。
古典的なユーザー空間のデータパスでは、カーネルルートがパケットをトンネルプロセスへ届け、iroute がそのプロセスにどのピアが受け取るべきかを伝えます。どちらも他方を代用するものではなく、片方しか持たない設定は最初の ping までは妥当に見えます。
二つの判断、一つのルートではない
10.77.20.0/24 が単一のクライアントの背後にある拠点間接続を思い浮かべてください。サーバーのカーネルルート、たとえば ip route add 10.77.20.0/24 dev tun0 は、該当するパケットをトンネルデバイスへ送ります。次に OpenVPN は、クライアント設定ディレクトリ内の iroute エントリから構築した独自の内部テーブルを参照し、どのピア接続がそれらを受け取るかを決めます。カーネルルートがなければパケットはプロセスに届かず、ピアルートがなければプロセスには届いてもどこへも行きません。
この分離は忘れがちで、クライアントプロファイルの一行のルートが両方の役割を果たすように見えるからです。そうではなく、ルートをプッシュすることはクライアントにトンネル経由で何を送るかを伝え、iroute はサーバーにクライアント背後のアドレス範囲が誰のものかを伝えます。両者は別のファイルにあり、別の側が読み、逆方向に失敗します。
iroute の置き場所と意味
エントリはクライアントの common_name にちなんで名付けられたクライアントごとのファイルに、client-config-dir の下で、iroute 10.77.20.0/24 として書きます。ファイル名の一致は見た目の問題ではありません。OpenVPN は認証された身元を引き当て、まさにその名前のファイルを読むため、site-a というファイルは共通名が site-a のクライアントにだけ効きます。すべてのクライアントが拠点ゲートウェイなら、そのようなファイルを持たないクライアントを一律に拒否する ccd-exclusive を追加し、ゲートウェイごとに一ファイルを保って実際に発行する証明書のサブジェクトで命名します。
遠隔 LAN を疑う前に、サーバー側でエントリを試してください。ステータスファイルは接続中のクライアントを共通名とともに一覧し、--verb 4 で動くサーバーはピアの接続時に iroute がインストールされる様子をログに残します。接続時に何も現れなければ、ファイルが誤ったディレクトリにあるか、誤った身元を指しています。
罠:ファイルはあるが身元が違う
正しく見える iroute が誤ったピアに付いていると、ディスク上はすべて正しく見えるため、ファイルがない場合より多くの時間を浪費します。証明書の改名、共通名の重複、実効的な身元を変える username-as-common-name のいずれもこれを生みます。期待した身元ではなく、サーバーが認証した身元を確認してください(ステータス出力が正式で、ファイル名は検索キーにすぎません)。
ルートは所有者より長生きすることがあります。静的ルートと iroute エントリは可用性の保証ではなくプレフィックスを表すため、現在切断されているピアへ通信が向かい続けることがあります。
ピアの先まで経路を完成させる
ピアの所有は経路の途中であり、終点ではありません。クライアントはトンネルから LAN へパケットを転送する必要があり、そのホストで IP 転送が有効で、通過を許可するファイアウォール規則が必要です。遠隔 LAN のホストはトンネルアドレスへの戻り経路を必要とし、ゲートウェイへ向かうルートかクライアント側で意図的に設計した NAT のどちらかになります。ディストリビューションの既定値を仮定せず、sysctl net.ipv4.ip_forward でクライアントの転送設定を確認してください。
他の VPN クライアントがそのサブネットへ到達する必要があるなら構成はさらに増え、サーバーには client-to-client が必要で、それらのクライアントはプレフィックスをトンネル経由でルーティングする必要があります。そのどれもサーバー自身のルートテーブルから導かれるものではありません。
サーバー自身からではなく、実際の送信元から一つの宛先を検証してください。無関係な LAN ホストからクライアント背後のホストへの ping は、戻り経路、転送規則、ピアの所有を一度に試しますが、成功したハンドシェイクは身元を証明するだけです。その後、所有するピアを切断してルートがどう振る舞うかを記録してください(その答えがあなたの障害モードです)。