VPN ネットワークへのルートは、混同しやすい二つのアドレス、つまりパケットが到達しようとする宛先プレフィックスと、それを一歩近づけるネクストホップを運びます。LAN ホストでは、そのネクストホップは同じリンク上で実際に到達できるルーターでなければなりません。リモートの VPN アドレスは、どれほどきれいに目的の宛先と一致しても、ネクストホップにはなれません。

このランブックは通常のケース、つまり 192.168.20.0/24 上のラップトップ、LAN アドレス 192.168.20.5 を持つ VPN ゲートウェイ、そしてそのゲートウェイの背後にあるリモートネットワーク 10.70.0.0/24 を扱います。以下のコマンドは、特に断らない限り、ラップトップ上で実行するものとします。

二つのアドレス、一つのルート

意図するエントリは 10.70.0.0/24 via 192.168.20.5 で、プレフィックスはパケットがどこへ向かうかを示し、via アドレスは誰がそこへ運ぶかを示します。カーネルは、指定したインターフェース経由でゲートウェイに到達できないルートのインストールを拒否します。その拒否こそが要点であり、到達可能であるためにトンネルを必要とするネクストホップは、トンネルを構築するネクストホップにはなれません。

したがって最初の確認は「ゲートウェイは動いているか」ではなく「ゲートウェイはこのリンク上にあるか」です。ラップトップ自身のサブネット、その ARP または近隣エントリ、ルート内のインターフェースがすべて一致している必要があります。10.70.0.0/24 の内部にしか存在しないアドレスは、二番目のルートの宛先にはなれても、最初のルートの via には決してなれません。

ネクストホップがゲートウェイに課すもの

ラップトップにルートをインストールしても決まるのは最初の受け渡しだけです。その後ゲートウェイには独自の経路、つまり転送の有効化、10.70.0.0/24 へのトンネルルート、そして誰が使えるかを定めるアクセスポリシーが必要です。Linux では net.ipv4.ip_forward=1 とトンネルルートであり、その手前のファイアウォールには転送されるフローを許可するルールが必要です。

戻りの方向こそ人々が忘れる部分です。リモート側には 192.168.20.0/24 への戻りルートが必要か、設計側でラップトップの送信元をリモート側が知っている何かに変換する必要があります。ゲートウェイからの ping が通ることはゲートウェイがリモートネットワークに到達できる証拠にすぎず、ラップトップのパケットが帰路を生き延びるかどうかは何も語りません。

送信するホストから検索を検証する

カーネルにどのネクストホップを選ぶかを尋ね、その答えの中のインターフェースを読みます:

ip route get 10.70.0.10
ip route show 10.70.0.0/24
ip neigh show 192.168.20.5

検索結果がゲートウェイと LAN インターフェースを示していれば、最初の区間は意図どおりに構成されています。トンネルデバイスを示しているなら、テーブルのより前にある何かがより具体的で勝っています。ルートがまったくインストールできないなら、カーネルはゲートウェイに到達できないと告げており、そのメッセージはどんなパケットキャプチャよりも役に立ちます。

次に、正しい場所からテストを繰り返します。ゲートウェイ上で作られたリクエストはゲートウェイ自身の送信元アドレスを使うため、戻りルートの欠落や、特定の送信元だけを許可するポリシーを隠してしまいます。ip-route のマニュアルは宛先、ゲートウェイ、onlink による上書きを分けて説明しており、上書きは使う前に理解する価値があります。

到達可能性を偽装するために onlink を使わない

onlink は、ゲートウェイの到達可能性チェックを飛ばしてそのまま送るようカーネルに指示します。経路を作るわけでも、存在しないアドレスの ARP を解決するわけでも、リモートのルーターをあなたの Ethernet セグメント上で応答させるわけでもありません。応答はするが接続されたサブネットに属さないゲートウェイには正当ですが、説明していないエラーを黙らせるために使うと罠になります。

onlink を付けないとルートがインストールされないなら、次の問いはなぜゲートウェイが想定の場所にないのかです。誤った VLAN、誤ったインターフェース上の二番目のアドレス、最後のオクテットの打ち間違いはどれもこれを引き起こし、どれもトラフィックが流れ始めた時点で戻り経路を壊します。

ポイントツーポイントのトンネルは Ethernet ではない

トンネルデバイスは ARP を行わず、意味のある近隣サブネットを持たないことがよくあります。そのルートは 10.70.0.0/24 dev tun0 のように見え、via をまったく伴わないことが多いのは、ピアが唯一のもう一方の端点だからです。LAN 流の via をそのテーブルにコピーすると、カーネルが拒否するルート、あるいはもっと悪いことに、ピアが決して応答しないアドレスを指すルートが生まれます。

ランブックでは二つのモデル、つまり到達可能なゲートウェイを持つ LAN ルートと、インターフェースとピアを持つトンネルルートを分けておきます。WireGuard、OpenVPN、IPsec はいずれも少しずつ異なる形をとるので、一つのホストから一般化するのではなく、実際に使った形を記録してください。

追加し、確認し、元に戻す

変更全体は三つのコマンドと一つの確認であり、まさにその順序で書き留めるべきです:

sudo ip route add 10.70.0.0/24 via 192.168.20.5
ip route get 10.70.0.10
ping -c 3 10.70.0.10
sudo ip route del 10.70.0.0/24 via 192.168.20.5

経路を確認し、一つの宛先を確認し、そのうえで、変更が予想しなかった形でホストを到達不能にする場合に備えて削除行を手元に用意しておきます。ルートを再起動後も残す必要があるなら、シェルのプロファイルではなくホストのネットワーク設定に置き、それに頼る前に再起動を試します。追加したシェルの中にしか存在しないルートは、二度デバッグすることになるルートです。

関連記事