クライアントは OpenVPN サーバーのトンネルアドレスに ping して応答を得るが、次にサーバーの LAN 上のホストを試すと何も返ってこない。この切り分けで障害はかなり絞れ、トンネルは上がっており、転送もおそらく動いており、応答は戻らない扉から出ていっている。修正は三通りあり、どれが正解かは何を管理でき、何をあきらめるかで決まる。次の三つの問いに順に答えれば、選択は好みの問題ではなくなる。

まずは壊れている向きを確認する

要求は VPN プールの送信元アドレスを持ってトンネルインターフェースに届く。サーバーはそれを LAN のホストへ転送し、そのホストは自分の表が示すゲートウェイ、通常は LAN のルーターへ応答する。ルーターにプールへのルートがなければ、応答はそこで死ぬかインターネット方向へ迷い込む。

どちらかを触る前に両方のマシンで確かめる。サーバーでは経路表がクライアントにどう届くかを問い、LAN のホストでは同じアドレスにどう届くかを問う。最初の検索はたいていトンネルを指し、二回目は LAN のルーターを指すので、その差が一行の障害になる。二回の検索はファイアウォールの監査より安く、問題の向きを確定できる。

ip route get 10.8.0.37
sysctl -n net.ipv4.ip_forward

LAN のホストがすでに VPN サーバーを指しているなら、問題はファイアウォール規則か MTU の上限であり、戻り経路の欠落ではない。フィルターを直すためにルートを足してはいけない。

問い一:遠隔 LAN のルーターを編集できるか?

LAN のルーターが自分のものなら、VPN プールへの静的ルートを引き、次ホップに VPN サーバーの LAN アドレスを置くのがきれいな答えだ。クライアントの送信元アドレスが保たれるので、LAN のホストがアドレス単位で記録・絞り込み・帯域制限する場合に効く。サーバー側の変換も要らないため、トンネルは純粋な経路のままになる。代わりに生じる義務は文書化であり、プール、ルート、サーバー設定の三つが一致していなければならない。

誰かがプールを変えた日に、それは静かに壊れる。値を一度書き留め、三か所のどこかを直すときは三か所すべてを直すものとして扱う。

サービスを載せている NAS やレイヤー 3 スイッチにも同じルートが要る(そのルートを持つルーター経由で全部を送っていない限りは)。インターネット側を向いた機器だけでなく、サブネットを終端する機器を確認しよう。小さなネットワークでは経路について意見を持つ機器が三台あることも珍しくない。

問い二:LAN からクライアントのアドレスが見えなくてもよいか?

ルーターが他人のものなら、VPN サーバー側の変換に相手の協力は要らない。LAN のホストはサーバーの LAN アドレスを見て、そこへ応答し、サーバーが変換して戻す。アプライアンスや NAT ベースのリモートアクセスがこう振る舞うのはそのためだ。

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

代償は帰属であり、クライアントごとのアドレスが LAN のログから消える。すると LAN のホスト側の許可リストは、プールではなくサーバーを名指ししなければならない。

変換を選ぶのは協力が得られないときであって、単に不便なときではない。変換はクライアントをあらゆる後日の調査から隠し、どのノート PC が接続を開いたかを知る必要がある場面も隠してしまう。アドレスをペイロードに埋めるプロトコルも壊しうる(変換はヘッダーの中で起きるからだ)。どちらが上ということはなく、両者は所有権について別の問いに答えている。

問い三:サーバー自身が別のトンネルのクライアントではないか?

もう一つの構成を思い描いてほしい(VPN サーバーが商用プロバイダーにもダイヤルしていて、トンネルが二本、アドレスも二組ある場合だ)。自分のクライアントのために転送する通信はプロバイダーから出ていき、プロバイダーは応答をプールのアドレスへ戻さない。両方のトンネルが健全なのに応答が消えるのはそのためだ。

修正は出ていくトンネルにもマスカレードをかけることで、プロバイダーにはサーバーのトンネルアドレスしか見えなくなる。逆方向には独自の規則が要る(サーバーが自分のクライアントへ接続を始めるのは別のフローだからだ)。その規則がないと、クライアントは経路のないアドレスへ応答してしまう。狭い規則は広いマスカレードより前に置き、具体的な変換が勝つようにする。

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o tun1 -j MASQUERADE
iptables -t nat -A POSTROUTING -d 10.8.0.0/24 -o tun0 -j SNAT --to-source 10.8.0.1

複数のインターフェースを持つホストは、クライアントから見ると同じに見える関連障害を追加する。送信元アドレスが別の表から選ばれたため、応答がメトリックの低い側のインターフェースから出ていく。戻り経路は検索で確かめ、行きの経路が戻りを含むと決めてかからないこと。

続いて両方向と両サイズを検証する

変更後は、クライアントから LAN のホストへ ping し、次に LAN のホストからクライアントへ ping する。二つ目の向きこそが飛ばされがちで、不完全な変換規則を暴くのはこちらだ。両方の結果を時刻付きで記録し、後日の退行を比べられるようにする。

それから実際のデータを流す(小さな ping が通るのに大きな転送が止まるのは MTU の症状だ)。その障害は、経路を直したと自分をほめた直後に現れる。

最後に再起動してもう一度試す。実行中に入れた経路やファイアウォールのコマンドは再起動を越えないので、次の起動で消える修正は文脈の少ない誰かがもう一度診断することになる。変更はそのシステムがもともと使っている方法で永続化し、それから一度だけわざと再起動する。

関連記事