一台のホストでOpenVPNサーバーとクライアントを動かす:クライアントが落ちる理由
OpenVPNを提供しつつ自分でも使うホストでは、トンネル自体は上がったままローカルクライアントが応答を失うことがあります。原因は二つ、共有されたプールと新しいデフォルトルートです。
VPNサーバーがすでに動いているマシンにクライアントプロファイルを追加すると、最初の犠牲は元のサービスです。新しいトンネルは確立しないこともあれば、上がったままサーバーの既存クライアントが静かに応答を受け取れなくなることもあります。二つの衝突がどちらの結果も生みます。すでに使われているトンネルプールと、新しいクライアント側が入れるデフォルトルートがテーブル全体を覆うことです。どちらもOpenVPNのエラーメッセージを出さないため、この障害はサーバーの問題として読まれてしまいます。
一台のマシン、二つの役割、そして応答がどこへ行くべきかについて相容れない二つの答え。
同じプール、二つのサーバー:どちらが勝つか
サーバーインスタンスはそれぞれ専用のトンネルサブネットを必要とします。server 10.8.0.0 255.255.255.0のような行を二つ目の設定にコピーすると、二つのインスタンスが同じプレフィックスを持ち、結果は起動の拒否か、片方のサーバーのクライアントがもう片方も自分のものと信じるアドレスを受け取る静かな争いになります。UDPポートやデバイス名を変えても、どちらもアドレス空間に触れないので役に立ちません。二つ目のプールを変え、ルートがそれを挙げているすべての場所で変えてください。
編集する前に何が動いているか列挙する:ip -4 addr showはトンネルデバイスを一覧し、ss -lunpは待ち受けを一覧し、systemctl list-unitsはユニット名を示します。トンネルのアドレスを一目見れば、プールが衝突しているか決まります。
クライアントプロファイルがテーブルに加えるもの
クライアント側は接続するとすぐにルートを書き込みます。redirect-gateway def1はデフォルトルートを0.0.0.0/1と128.0.0.0/1に分割し、どちらも新しいデバイス経由でルーティングし、さらに遠くのサーバーへのホストルートを意図的に物理インターフェースに固定します。この固定は、トンネルが自身の転送用の経路を保つためにあります。それ以外のすべて、ローカルサーバーが自分のクライアントに返す応答も含めて、いまは新しいデフォルトに従い、遠隔のリンクから出ていきます。
つまり二つ目の衝突は壊れたトンネルではありません。テーブルの間違った位置で動いているトンネルです。
役割を分けておく三つの方法
最も侵襲の少ない修正は、デフォルトルートをクライアントプロファイルから外すことです。route-nopullに加えて、遠隔プレフィックス用の明示的なroute行を書き、ローカルのテーブルは頼んだ場所だけ変わるようにします。次の段階は、ローカルのトンネルサブネットを除外するポリシールールで、デフォルトルートがあってもローカルクライアントへの応答が届いたインターフェースから出られるようにします。最も徹底した方法はクライアント役割用に別のネットワーク名前空間を用意することで、共有テーブルを完全に取り除きますが、二つ目のルーティング文脈を維持する費用がかかります。
どの道を選んでも、例外はLANではなくローカルのトンネルサブネットを名指ししなければなりません。ローカルサーバーが返す応答の宛先はトンネルのアドレスなので、LANの形をした例外は決して一致しません。
二つのインスタンスのどちらが悪いのか
クライアントインスタンスを止めて、元のクライアントを再試験します。すぐに回復すれば原因はルーティングであり、サーバーではありません。クライアントを戻し、送信元と宛先の両方のアドレスを与えたip route getで応答を一つ追跡すると、カーネルが選ぶ経路が分かります。次にtcpdump -ni any port 1194で、パケットが実際に使うインターフェースを観察します。サーバーのステータスファイルは数秒ごとにstatusディレクティブで書かれ、接続中のクライアント一覧と両方向のバイトカウンターを持ちます。
そのカウンターを突き合わせて読んでください。出ていって二度と戻らない通信は、ハンドシェイクの問題ではなくルーティングの答えです。