LANのためにルーティングし、同時にVPNへダイヤルする機器は、自分自身と同じ議論に陥ります。トンネルは既定ルートを所有したがり、LANはそれを取り戻す必要があります。OpenVPNが接続すると、トンネル経由の既定ルート、または半既定ルートの組をインストールすることがあり、これはノートPCには正しく、LANアドレスからの応答を近隣が期待するゲートウェイには誤りです。答えはVPNを省くことではありません。答えは、二つの判断に別々のテーブルを与えることです。

一つの既定ルート、二人の所有者

転送されるトラフィックとローカルで発生するトラフィックは同じ経路を通る必要はありません。LANのクライアントは選んだ宛先にだけトンネルを必要とし、ホスト自身の管理セッションとそれらのクライアントへの応答はLANの既定ルートを必要とします。両方をメインテーブルに混ぜると、二つの異なる問いに一つの答えを押し付けることになります。

OpenVPNにはまさにこのためのスイッチがあります。route-noexecはクライアントがメインテーブルに一切触れないようにし、本来使う値はroute-upスクリプトにroute_vpn_gateway、dev、およびインターフェースのアドレスとして渡されます。その後、どのテーブルがどのルートを受け取るかを、後で読めるコードで決めます。

ポリシーテーブルかメインテーブルの書き換えか

ApproachWhat it buysWhat it costs
Separate table plus source ruleLAN traffic and host traffic keep independent defaultsEvery lookup now depends on rule order
Editing the main table onlyFewer moving parts on a single-purpose hostOne mistake takes the gateway offline entirely
Two half-default routesWorks for a full-tunnel clientAmbiguous on a host that must answer on its LAN address

別テーブルは一つのサブネットを超えて拡張できる唯一の選択肢です。一度名前を付けたら、番号を覚えなくて済むように名前で参照します。

echo "10 vpn" >> /etc/iproute2/rt_tables
ip rule add from 192.168.50.0/24 table vpn
ip route add default via 10.8.0.1 dev tun0 table vpn

ここにあるアドレスはプレースホルダーです。何かを実行する前に、自分の環境のLANプレフィックス、トンネルゲートウェイ、デバイス名に置き換えてください。

ルールはホストにも一致させる必要があります

LANプレフィックスだけに一致するルールは転送されるパケットを対象にします。ゲートウェイ自身が発生させるトラフィックや、送信元としてゲートウェイのLANアドレスを持つ、LANクライアントへ返す応答は対象になりません。そうした参照はmainに落ち、今でもトンネルから出ていきます。

ゲートウェイ自身のLANアドレス用に二つ目のルールを追加するか、最初のルールを両方を含む集合に広げます。順序が重要です。より具体的なルールを先に置き、送信元を明示する参照で結果を確認します。

ip route get 203.0.113.9 from 192.168.50.1

ローカルに残すべき宛先に対してトンネルデバイスが報告されるなら、テーブルの内容にかかわらずルール集合が誤っています。

NATか反対側のルートか

VPNサーバーはトンネルのサブネットしか知りません。LANの送信元アドレスで届くパケットは、誰かが戻り経路を用意しない限り戻れません。用意する方法はちょうど二つあります。サーバーにLANプレフィックスのルートを追加すると元の送信元が端から端まで見えたままになり、監査された設計が通常望むのはこれです。ゲートウェイでのマスカレードは送信元をトンネルアドレスに書き換え、サーバー側の協力を必要としません。

iptables -t nat -A POSTROUTING -s 192.168.50.0/24 -o tun0 -j MASQUERADE

サーバーを管理しておらず、そこにルートを追加できないならNATを選びます。ログ、アクセス制御、戻り経路の対称性が重要なならサーバー側ルートを選びます。マスカレードは反対側が記録するすべてから元のアドレスを消すからです。

どちらでも、転送を有効にする必要があり、厳格な逆経路フィルタリングは、mainがその送信元にトンネルを選ばない場合に応答を落とすことがあります。トンネルを責める前に実効値を確認してください。

再接続後も分割を維持する

手で追加したルールとルートはインターフェースが作り直されると消え、古いテーブルエントリはそれを正当化したセッションより長く残ることがあります。テーブルのルール、トンネルのルート、マスカレードのエントリをクライアントのroute-upスクリプトに入れ、スクリプトの先頭でテーブルをフラッシュして、古いゲートウェイが新しいセッションに残らないようにします。

両端から確認します。ゲートウェイでLAN送信元を使った参照と、LANクライアントからトンネルを通るべき宛先への実際の要求です。存在しても決して選ばれないルートは、カウンターを読むまでルートがまったくないのとまったく同じように振る舞います。

関連記事