VirtualBox VPN ラボ:ゲートウェイ VM かホストオンリー ネットワークか
VirtualBox VPN ラボで、ルーティング済みのゲートウェイ VM とホストオンリーのセグメントのどちらを選ぶかを決め、トンネルが落ちたときにゲストを閉じた失敗に追い込みます。
VPN ラボにどれだけの仕掛けが必要かを決める必要があります。二つの VirtualBox セグメントの間に置くルーティング済みのゲートウェイ VM は、実在のクライアントが背後に座るアドレス変換、戻り経路、ファイアウォールの位置を再現します。ホストオンリーのセグメント一つでは、制御された扉が一つ手に入るだけで、それ以外は何も得られません。ゲートウェイ版はゲスト三台と維持すべきルーティングテーブルを要し、ホストオンリー版はゲスト一台とポリシー一つで済みます。三つの問いが両者を分け、三つ目があなたのテストがそもそも通るかどうかを決めます。
何かを複製する前に三つの問いに答える
まず VPN サーバーが何を観測しなければならないかを考えます。サーバーがテスト用ゲストではない送信元アドレスを見る必要があるなら、両者の間で何かが変換しなければならず、その何かはあなたが制御するルーターでなければなりません。ホストオンリー ネットワークはゲストのセグメントにホストのアダプターを与えるだけで、変換器ではありません。次にゲストが外の何かに到達する必要があるとき、NAT アダプターを接続しますが、VirtualBox 自身の NAT エンジンがあなたに尋ねずに送信元を書き換えます。
次に、ゲストがトンネル以外の何かに到達してよいかを問います。その答えが内部かホストオンリーかを選び、これこそがほとんどのラボ記事が飛ばす問いです。最後に、トンネルが落ちたときに何が起きるべきかを問います。これはトポロジーではなくポリシーを決めることであり、幸せな経路だけを示すラボはほとんど何も試していないからです。
| What the test requires | Routed gateway VM | Host-only guest |
|---|---|---|
| Server sees a translated source address | Yes, from your own MASQUERADE rule | No, VirtualBox NAT does it instead |
| The guest has exactly one egress | Yes, while the second adapter faces the tunnel | Only until a NAT adapter is attached |
| Policy is testable during a tunnel failure | Rules live in one place | Rules live on each guest |
三つの役割を内部ネットワークで配線する
ゲスト三台と名前付きセグメント二つを使い、両方にアダプターを持つ唯一のマシンをゲートウェイにします:
VBoxManage modifyvm lab-client --nic1 intnet --intnet1 WAN
VBoxManage modifyvm lab-server --nic1 intnet --intnet1 LAN
VBoxManage modifyvm lab-gw --nic1 intnet --intnet1 WAN --nic2 intnet --intnet2 LAN
内部ネットワークに別個の作成手順はありません。--intnet1 の文字列がセグメントそのものであり、二台のマシンは名前が完全に一致するときだけそれを共有し、ホスト上の何もそこに接続されません。この最後の性質のおかげでラボはきれいに繰り返せます。ホストのルート、ホスト自身の VPN クライアント、ファイアウォールが誤ってゲストに届くことはないからです。内部セグメントには DHCP サーバーもありません(追加しない限り)。ですから固定アドレスが最短の道です。
クライアントには WAN アドレスだけを与え、デフォルトゲートウェイはゲートウェイの WAN アドレスを指すようにします。サーバーは LAN アドレスを受け取り、ゲートウェイの LAN アドレスを自分のデフォルトゲートウェイとして使います。一つのセグメントに二つのアドレスを保持したり、もう一方のセグメントへの迷いルートを持ったりするゲストは、ルーターを迂回する経路を持ち、下のテストはあなたに嘘をつきます。
私は VM 名の横に、四つのアドレスと二つのセグメント名を書いたテキストファイルを置き、あらゆるシェルに貼り付けます。数週間後、プロファイルの変更が何かを壊したとき、そのファイルがプロファイルをデバッグすることと自分の記憶をデバッグすることの差になります。
漏れてはいけないセグメントには内部かホストオンリーを選ぶ
ホストオンリー モードはホスト自身の上に仮想アダプターを作り(通常は vboxnet0)、ホストにゲストのセグメント上のアドレスを与えます。これは管理には便利で、分離テストには致命的です。ホストがゲストに直接到達できるようになり、ホスト側のあらゆるサービスが可能な経路になるからです。内部モードにはホスト アダプターがまったくありません。二つのモードはネットワーク設定パネルで混同しやすいので、ラベルではなく文書化された違いを確認してください(VirtualBox のネットワーク詳細のページを参照)。
トンネルを使わなければならないゲストには、内部がより安全な既定であり、ゲートウェイが唯一の出口です。ホストオンリーを保つなら、ホスト アダプターを管理経路として扱い、それを声に出して言ってください。ホストはゲストに到達してよいが、ゲストはホストを出口として使えてはなりません。
VBoxManage modifyvm lab-client --nic1 hostonly --hostonlyadapter1 vboxnet0
証明できる分離とは、あなたが設定した分離です。内部アダプター一つ、ゲートウェイへのデフォルトルート、NAT アダプターなしのゲストには、ゲートウェイを迂回する経路がありません。ホストオンリー アダプターと NAT アダプターを持つゲストには二つの経路があり、そのうち一つだけがあなたが試そうとした経路です。
ゲートウェイでルーティングと変換を行い、次に閉じた失敗をさせる
VirtualBox はセグメント間を転送しませんが、転送するのはゲストです。VPN サーバーの VM がゲートウェイの背後にある状態で、転送を有効にし、クライアントのトラフィックがサーバーへ出ていくときに変換します:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
この規則により、サーバーはクライアントではなくゲートウェイの LAN アドレスを見ます。これは、通信事業者の NAT の背後にいる実在のクライアントがヘッドエンドからどう見えるかと同じです。sysctl の値を /etc/sysctl.d/ に、規則をディストリビューションが使うファイアウォール サービスに保存しなければ、再起動でラボは静かに、ルーティング済みだが未変換の状態に戻ります。
転送は認可ではありません。ACCEPT の既定の FORWARD ポリシーの下では、デフォルトルートがゲートウェイを指すゲストは、トンネルの有無にかかわらず、ルーティングテーブルが選ぶインターフェースから出ていきます。ゲートウェイにパッケージ導入用の NAT アダプターもあるなら、そのアダプターはトンネルが落ちた瞬間に機能する暗号化されていない出口であり、あなたの VPN 専用テストは VPN 専用テストだったことがありません。
代わりにサーバーが遠隔にあり、ゲートウェイ自身がトンネルを終端する場合、同じ判断はインターネットに届く NIC ではなくトンネル インターフェースを指します:
iptables -P FORWARD DROP
iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
トンネル自身の外側の輸送と帯域外の管理経路を、転送されるトラフィックから切り離しておきます。ゲートウェイを修理する唯一の方法が、あなたがデバッグ中のトンネルを通ることなら、ラボは締め出しの演習になります。シリアル コンソール、ホストオンリーの管理アダプター、既知の良好な状態のスナップショットは、壊れたルーターを手作業で復旧するより安く済みます。
経路はホストからではなくゲストから検証する
外へ向かって作業します。クライアントがゲートウェイの WAN アドレスに届くこと、次にゲートウェイ経由でサーバーに届くこと、次に VPN ポートへの接続が出て戻ることを確認します。ゲートウェイの両インターフェースでのキャプチャは、応答が届いて戻り経路で捨てられるかどうかを示しますが、クライアントだけで取ったキャプチャでは区別できません:
tcpdump -ni eth0 udp port 1194
tcpdump -ni tun0 udp port 1194
次に、ゲストからアドレス反射サービスにどの送信元が見えるかを尋ね、ゲートウェイ自身の出口アドレスと比べて出口を証明します。答えがホストのアドレスと一致するなら、トンネルを迂回する経路が存在します。ゲストが実際にどのリゾルバーを使っているかを確認し、IPv6 は別に確認してください。IPv6 が有効なのにトンネルが IPv4 しか運ばないセグメントは、偶然ではなく設計によって漏れるからです。
最後に、意図的に壊します。トンネルを止めるか外側のポートを塞ぎ、ゲストから新しい接続を開きます。それは失敗しなければならず、理由はあなたが名指しできるものでなければなりません。経路がない、拒否規則がある、リゾルバーが死んでいる、のいずれかです。トンネルを再開し、ゲストがネットワークを作り直さずに回復することを確認します。Hamachi や ZeroTier のようなメッシュ VPN がラボを共有しているなら、ブリッジされたアダプターはメッシュではなくアダプター名に従うので、クライアントが独自の仮想アダプターを導入した後にブリッジを向け直す必要があります。
VBoxManage list bridgedifs
VBoxManage modifyvm lab-client --bridgeadapter1 <mesh-adapter-name>
ゲストのトンネルをホストと共有することは問題を映し出します。ホストのデフォルトルートをゲストに向けるのは機能し、ゲスト内のプロキシも機能します。ホスト経由の NAT は、ホストが起点となったトラフィックについてゲストのトンネルを運びません。セグメント名とファイアウォール規則を一か所に保存し、動作する状態のスナップショットを取り、サーバーが観測した送信元アドレスを記録します。そうすれば次のプロファイル変更は、作り直したラボではなくスクリプト一回分で済みます。