リモートユーザーはハブに接続し、ハブ自身の LAN にあるファイルサーバーには到達できて、すべて正常に見えます。ところが本社の 10.20.0.50 の共有を開くと、ハブは別の拠点間トンネル経由でそこに到達するはずが、タイムアウトします。 どちらのトンネルも上がっており、両方のカウンターが増えているので、壊れているトンネルはありません。ハブを横切るのは三つの機器での三つのルーティング判断であり、 トンネルは、それが作られた対象のプレフィックスしか運びません。私が確認する順序と、各手順が成り立つかを示すコマンドは次のとおりです。

通過には三つの照会が必要で、トンネル一つでは足りない

どの機器も自分自身で最長プレフィックス一致を行い、その結果を忘れます。ラップトップは 10.20.0.50 をローカルルーターではなくトンネルへ送る必要があります。ハブはリモートアクセスインターフェースに届いたパケットを受け取り、拠点間インターフェースへ渡す必要があります。本社はユーザーのアドレス宛ての応答をトンネル経由で返す必要があります。三つのうちどれか一つが失敗しても、ブラウザーでは同じに見えます。沈黙です。

だからこそ、各トンネルを単独で試験してもほとんど何も証明できません。ハブの LAN アドレスに ping すると最初の判断を試し、本社からハブに ping すると三つ目を試します。失敗するパケットは送信元がユーザープール、宛先が第二の拠点なので、まずそのプレフィックスを書き留めます。ここではプールが 10.80.0.0/24、ハブの LAN が 10.10.0.0/24、本社が 10.20.0.0/24 です。

遠隔のプレフィックスをリモートクライアントにプッシュする

ある OpenVPN リモートアクセスサーバーでは、クライアントは接続時にルートを学習します。push がなければ、スプリットトンネルのクライアントは 10.20.0.50 を自分のゲートウェイへ送り、パケットはトンネルに入りません。

push "route 10.20.0.0 255.255.255.0"

プッシュされたルートはクライアントが接続したときに反映されるので、接続したままのユーザーは再接続するまで何も見えません。クライアントで確認します。Linux では ip route get 10.20.0.50、Windows では route print です。出力にはトンネルインターフェース名が含まれるはずです。

push はハブの助けにはなりません。これはクライアントへのメッセージであり、サーバー上のルートでも転送の許可でもないので、完璧な push 行を持つハブでも一ホップ先でフローを落とします。これが、人々が push の失敗だと結論づける通常の理由です。

ハブに実際の出口ルートを与える

ハブには本社のプレフィックスに対する自分自身のネクストホップが必要です。ルーティングされたトンネルでは、それは拠点間インターフェースを通る通常のルートであり、一つのコマンドで選択されたルートと選択された送信元の両方が表示されます。

ip route get 10.20.0.50 from 10.80.0.25
sudo ip route add 10.20.0.0/24 via 172.30.0.2 dev s2s0

拠点間の区間自体が OpenVPN の場合、ルートはその構成の中に、ピアのトンネルアドレスをゲートウェイとして置けます。route 10.20.0.0 255.255.255.0 172.30.0.2。ゲートウェイは省略できません。省略するとネクストホップは実装の既定値に落ち、単一リモートのクライアントと複数ピアのハブで異なります。

ポリシーベースの IPsec は異なります。ハブのカーネルはパケットを通常の LAN ゲートウェイへ送り、ポリシーが出ていく途中でそれを捕まえるので、トンネルのルートは何もしないか、ポリシーを迂回してトラフィックを流します。上のコマンドの送信元に注目してください。プールのアドレスではなく 10.10.0.1 なら、カーネルが遠隔側に拒否されるアドレスを選んだということです。iroute も答えではありません。これはサーバーに、どのクライアントが自分のトンネルの背後にあるサブネットを所有するかを伝えるもので、第三の拠点へのトラフィックをどこへ送るかではありません。

遠隔側をユーザープールまで広げる

本社はすでにハブの LAN である 10.10.0.0/24 をカバーしています。ユーザープールは二つ目のプレフィックスであり、セレクターにも入っていなければなりません。そうでなければ 10.80.0.25 宛ての応答をカバーするポリシーがありません。各ピアは同じ組のプレフィックス集合を自分の側から指定します。

# strongSwan swanctl.conf, on the hub
local_ts  = 10.10.0.0/24, 10.80.0.0/24
remote_ts = 10.20.0.0/24
# on the headquarters peer
local_ts  = 10.20.0.0/24
remote_ts = 10.10.0.0/24, 10.80.0.0/24

一方の機器の local_ts はもう一方の remote_ts。ハブのブロックを本社にコピーすると組が反転し、子 SA は決して上がりません。

古い ipsec.conf 構文ではカンマ区切りの leftsubnet を使います。稼働中のセキュリティアソシエーションは交渉したセレクターを保持するので、編集後にトンネルを再確立してください。10:00 に変更したセレクターを 09:40 に上がった SA に対して試しても失敗したままで、その間も構成ファイルは正しく見えます。

次に最後のホップを確認します。遠隔のエンドポイントで ip route get 10.80.0.25 がトンネルを指すはずです。サービスが LAN ルーターを既定のゲートウェイにしている場合、そのルーターにも戻りルートが必要で、なければ応答はそこで死にます。そのセグメントで tcpdump -ni eth1 host 10.80.0.25 を実行すれば、応答がそもそもエンドポイントを出たかがわかります。

ハブでフローを許可する

転送を有効にし、経路を許可する必要があります。インターフェース間ですべてを受け入れるのではなく、ルールを二つのプレフィックスに限定してください。

sysctl -w net.ipv4.ip_forward=1
iptables -I FORWARD -i tun0 -o s2s0 -s 10.80.0.0/24 -d 10.20.0.0/24 -j ACCEPT
iptables -I FORWARD -i s2s0 -o tun0 -s 10.20.0.0/24 -d 10.80.0.0/24 -j ACCEPT

逆経路フィルタリングはその隣にある静かな失敗です。二つの区間が別のインターフェースにあると、rp_filter=1 が応答を落とす一方で、許可ルールのカウンターはまったく動きません。試行の前後で iptables -vnL FORWARD を比較してください。まったく増えないルールには到達していないので、書き直すのではなく一つ下の層を見てください。

一つのグループだけが通過を必要とするなら、グローバルの push を広げるのではなく、client-config-dir の下のクライアントごとのファイルにルートを置きます。ハブの送信元 NAT も遠隔側の戻りルートの必要性をなくしますが、ユーザーのアドレスを隠すので、遠隔拠点のログやアドレスベースのルールはユーザーを区別できなくなります。

クライアントから確認し、次に逆順でロールバックする

ICMP だけでなく TCP ポートを試験してください。ping は通ってもサービスが遮断されたままのことがあります。クライアントから nc -vz 10.20.0.50 445 と traceroute -n 10.20.0.50 で、二番目のホップがハブのトンネルアドレスかがわかります。ハブでは tcpdump -ni tun0 host 10.20.0.50 と拠点間インターフェースで同じフィルターです。両方に要求があり、どちらにも応答がなければ、問題は遠隔側へ移ります。

次に、遮断されたままであるべきものを試験します。プールが決して到達すべきでないホストも応答するなら、通過以上に開けており、ルールを狭めるべきです。すべてをすべてのスポークへ転送するハブは最初の試験に通り、二番目に失敗します。

ロールバック用の一覧を保ってください。四つのオブジェクトが変わり、そのうち三つは忘れやすいからです。プッシュしたルート、ハブのルート、セレクター、ファイアウォールのルールです。逆順に戻し、SA を再確立し、一人のユーザーに再接続させます。部分的なロールバックは、もう一致しないトンネルを指すルートを残し、それは元の沈黙より読みにくいものです。 OpenVPN 2.6 のマニュアル には、お使いのバージョンの push、route、iroute が記載されています。

関連記事