OpenVPN の「File exists」はルート上のファイル問題ではない
メッセージはファイルシステムではなく、カーネルのルートテーブルから出ています。LAN ポリシーを変える前に、すでにプレフィックスを所有しているエントリを読んでください。
まずメッセージが現れる場所から始めます。クライアントが接続し、トンネルが上がり、そのあとログが Linux のルート追加コマンドが File exists で失敗したと報告します。この文には証明書、鍵、設定ファイルへの言及はありませんが、言葉はそう示唆します。カーネルは自身のルートテーブルを説明しており、インストールを要求したプレフィックスにはすでにエントリがあります。
クライアント自身の順序とは、何を要求したのか、テーブルにすでに何があったのか、そのエントリを誰が置いたのか、そしてようやく何を変えるのかという順序です。各手順で可能な所有者が一つずつ消えます。
クライアントが実際に求めていたもの
失敗の前に、クライアントは追加しようとするルートを、通常は宛先、ネットマスク、ゲートウェイ、ときにメトリックやテーブルとして記録します。その行が要求です。続くエラーはカーネルの答えであり、両者は並べて読むべきものです。
journalctl -u openvpn-client@office -b --no-pager | grep -nE 'route|File exists'
openvpn --config /etc/openvpn/client/office.ovpn --verb 4 --log /tmp/ovpn.log
ルートヘルパーの非ゼロ終了ステータスは、カーネルの反応が異なっても非ゼロのステータスになるため、その下のテキストよりも情報が少なくなります。正確なメッセージを残してください;既存エントリと到達不能なゲートウェイの区別が、次のどの節が当てはまるかを決めます。
既存のルートを読む — アドレスだけでは不十分
テーブルで同じドット付き四つ組を探すだけでは足りません。ルートオブジェクトはアドレスファミリ、テーブル、宛先プレフィックス、メトリック、プロトコル、出力デバイスで識別され、プレフィックスを共有するエントリはそれらの属性が異なる場合、正当に共存できます。衝突するのはテキストではなくオブジェクト全体です。
ip -4 route show table all | grep -F '10.40.'
ip -4 route show match 10.40.0.0/16
ip -4 route get 10.40.0.5
最後のコマンドは、何が存在するかではなくカーネルがその宛先に対して今どのエントリを選ぶかという、最初の二つとは別の問いに答えます。どちらの見方も有用で、結論を出す前に比較する価値があるほど頻繁に食い違います。両者の不一致こそ興味深いケースであり、丸め誤差ではありません。
失敗した要求の横に、プレフィックス、テーブル、メトリック、デバイスを記録します。既存のエントリが同じ属性と同じ次のホップを持つなら、ルーティングの問題ではなく重複した指示です。
プレフィックスが持ちうる四つの所有者
接続ルートは割り当てられたアドレスから生まれ、そのアドレスが存在するたびにシステムが作り直します。DHCP クライアントや接続マネージャーは自身のライフサイクルの一部としてルートをインストールします。別の VPN クライアントがすでに同じプレフィックスを運んでいる可能性があります。またローカルのフックやスクリプトが、ほかが知らないルートを追加することもあります。
所有者ごとに修正が異なります。接続ルートは削除するものではなく、削除するとトンネルが使えるようになる前にローカルアクセスが壊れることがあり、カーネルが元に戻します。マネージャー所有のルートはそのマネージャーを通じて変更すべきで、次の再接続で取り消される手動の ip route del ではありません。
保持されたインターフェースは同じ混乱を起こしやすくします。トンネルデバイスが再接続後も残ると、独自の設定コードがインストールしたルートが二回目の実行でも存在することがあり、きれいな状態を前提とするスクリプトは二回目に失敗し、一回目は動きます。古いエントリを意図的に消すか、設定コードを冪等にしてください。
block-local は別の問いに答える
プロファイルがすべてのトラフィックをトンネル経由で送る場合、クライアントはローカルネットワークをどうするか決める必要があります。block-local フラグはローカル LAN をトンネル経由でルーティングしつつ、LAN ゲートウェイに関する文書化された例外を保つことで、その決定を変えます — これは到達可能性に目に見える影響を持つトラフィックポリシーの選択です。
これはルート追加が既存エントリのエラーを返した理由を説明せず、万能の修理として採用すると実際の競合がポリシー変更の陰に隠れます。プロファイル編集後にローカルリソースに届かなくなったなら、このフラグは最初に確認すべきものの一つです;ルート追加が失敗する場合、それは答えではありません。
どの宛先をローカルに残すかという決定として扱い、意図的に決めて書き留めてください。ログが不穏に見えるときに試すスイッチではありません。
ループを閉じる — 重複をその発生源で取り除く
どの所有者がエントリを持っているか分かったら、指示が定義されている場所で重複した指示を取り除きます。プロファイル内の route 行、サーバーからの push、もう実行する必要のないフックのいずれかでしょう。
ip -4 route show match 10.40.0.0/16
ip -4 route get 10.40.0.5
journalctl -u openvpn-client@office -b --no-pager | tail -n 15
そのうえで再接続し、三つを確認します:トンネルが上がること、意図した宛先が望んだ経路に解決されること、失敗が消えてその場所に新しい失敗が現れないこと。経路の選択が間違ったままログがきれいでも、修理ではありません。
プレフィックスが片側ではローカル LAN、もう片側では遠隔ネットワークを意味するなら、問題は重複ではなくアドレスの重なりであり、どれだけ削除しても両方の意味が同時に真になることはありません。その場合は二つのネットワークのどちらかに別の計画が必要です。どちらを再番号付けするかを、どちらかに触る前に決めてください。