学習ラボの全体像と安全性: 隔離の考え方と、戻せる状態の作り方
この記事は、ネットワークの実験を行うラボの全体像と、安全に実験するための考え方を説明します。ラボは、Windows 上の VirtualBox で動かす AlmaLinux の VM です。実験のたびにファイアウォールや経路を変えるので、「ラボの通信が外に出ないこと」と「いつでも元に戻せること」が前提になります。
まずは最初に全体の流れをまとめます
- ラボの通信は、VirtualBox の内部ネットワークだけを通します。各 VM には、管理用の NAT のアダプターも付きますが、ラボの通信には使いません。
- ただし、アダプターを分けるだけでは足りません。静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるでは、ルーター R1 の
enp0s8が NAT 側のenp0s3と同じpublicゾーンに入っていた状態で、client の ping が R1 のenp0s3(NAT 側)から出るのを観測しました(理由は候補。4 章)。 - 変更の前にスナップショットを取り、戻せる状態を作ります。復元すると、取得後のファイルは失われるので、先に記録を回収します。
確認できたことと、確認していないことを分けて書きます。確認していないことは、末尾の「要検証」にまとめました。この記事は、実験の記録(data/)の抜粋で説明します。個人名は、<WINDOWS_USER> のようなプレースホルダーに置き換えています。
1. ラボの構成: VM と、2 種類のネットワーク
ラボは、VirtualBox 7.1.10(ホストは Windows 11 Home)上の、AlmaLinux 9.8 の VM でできています。実験によって、使う VM が違います。
| VM | 役割 |
|---|---|
| client | 通信の送り手 |
| server | 通信の受け手 |
| switch | 実験の一部で使う(L2 スイッチの役) |
| router、router2 | ルーター(R1、R2) |
静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分ける以降は、client、R1、R2、server の 4 台構成です(詳しくは E3 の記事で扱います)。
client R1 (router) R2 (router2) server
+--------+ +------------+ +------------+ +--------+
| |--lan-a-| |-transit-| |--lan-b-| |
+--------+ +------------+ +------------+ +--------+
ラボの通信は、この線(VirtualBox の内部ネットワーク)だけを通る
各 VM の enp0s3 --(NAT)--> ホスト --> インターネット (管理用。ラボの通信には使わない)
各 VM は、次の 2 種類のネットワークにつながります。
| 種類 | VirtualBox の設定 | 用途 |
|---|---|---|
| 管理用 | NAT(enp0s3。10.0.2.15/24、既定ゲートウェイ 10.0.2.2) | SSH、時刻同期、dnf。ホストからは、127.0.0.1 のポートフォワードで SSH に入る |
| ラボ用 | 内部ネットワーク(intnet。lan-a、transit、lan-b など) | 実験の通信 |
ここで書いた構成の値は、リポジトリの構成の文書(docs/TOPOLOGY.md)に基づいています。実機の設定の確認は、E3 の記事で扱います。
2. 隔離の方針: 内部ネットワークだけを使う
2.1 VirtualBox の仕様(公式資料)
VirtualBox 7.1 の公式マニュアル「Introduction to Networking Modes」には、内部ネットワークについて次の説明があります。ここでは該当箇所を日本語に訳しています。
内部ネットワーク: 選択した仮想マシンには見えるが、ホスト上のアプリケーションや外の世界には見えない、ソフトウェアベースの別種のネットワークを作れます。
同じ節の表では、内部ネットワークで可能なのは「VM 同士の通信」のみで、「VM → ホスト」「ホスト → VM」「VM → 外部」「外部 → VM」は不可です。NAT では「VM → ホスト」と「VM → 外部」が可能で、「ホスト → VM」と「外部 → VM」にはポートフォワードが必要です。「VM 同士」の通信はできません。 VirtualBox 7.1 の公式ガイドの表から、Internal と NAT の行を示します(取得した要約からの再構成で、原文の逐語ではありません。列の順序は申告によります)。
| ネットワークモード | VM→Host | VM←Host | VM1↔VM2 | VM→Net/LAN | VM←Net/LAN |
|---|---|---|---|---|---|
| Internal | – | – | + | – | – |
| NAT | + | Port forward | – | + | Port forward |
上の説明文も、公式ガイドの要約の記載と一致しました(照合記録)。
2.2 PoC-1 の設定の確認
最初のラボ(PoC-1。client と server の 2 台。E3 のラボとは配線が違い、ラボ用のアダプターは NIC2 でした。E3 のラボは NIC3 を使います)で、アダプターの設定を確認した記録があります(PowerShell の出力を貼り付けた転記で、取得時刻は不明です。記録は data/poc-1-almalinux-lan/isolation-host-config.txt)。
PS C:\Users\<WINDOWS_USER>> & "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" showvminfo "Alma9mini-cli" --machinereadable | Select-String "^nic[0-9]=|^intnet[0-9]="
⋮
nic1="nat"
intnet2="poc1-lan"
nic2="intnet"
nic3="none"
nic4="none"
nic5="none"
nic6="none"
nic7="none"
nic8="none"
出典: data/poc-1-almalinux-lan/isolation-host-config.txt#L5(抜粋 L5,L7-15、全 31 行のうち 10 行を表示、21 行を省略)
nic1 が NAT、nic2 が内部ネットワーク poc1-lan、nic3 以降は none です。ブリッジ(ホストの LAN に直接つなぐ設定)とホストオンリーのアダプターは、ありません。server も同じ設定でした(同じファイルの #L18 以降)。この 2 台の記録の NIC 名は、enp0s8 が内部ネットワーク(NIC2)です。E3 のラボの client と server では、内部ネットワークは enp0s9(NIC3)になります(E3 の 2.6)。隔離の考え方は、どちらの配線でも同じです。
2.3 WSL2 から VirtualBox を操作する準備
この連載の VirtualBox の操作は、WSL2 の bash から行います。WSL2 からは、Windows 側の VBoxManage.exe を、パスを指定して呼べます。ただし、パスに空白(Program Files)があり、毎回書くのは長いので、~/.bashrc に vb という関数を登録します(E2b で使った方法と同じです)。
作業の内容(対象: WSL2 の対話シェル、一般ユーザー):
~/.bashrcの末尾に、次の 1 行を足します(エディターで開くか、echo '…' >> ~/.bashrcで追記します。>>は追記で、>だと上書きして中身が消えるので、使いません)。
vb() { "/mnt/c/Program Files/Oracle/VirtualBox/VBoxManage.exe" "$@"; }
- 現在のシェルに読み込みます:
source ~/.bashrc(新しい端末を開いても読み込まれます)。 - 動作を確認します:
vb --version。
- 目的:
VBoxManage.exeの長いパスを書かずに、vb snapshot …のように呼ぶ。 - 影響: 関数が 1 つ増えるだけです。VirtualBox の設定や VM は変わりません。関数は対話シェルの定義なので、スクリプトの中では使えません(スクリプトは、パスを変数
VBOXMANAGEで受け取ります。例:labs/common/create-nodes.sh)。 - 復旧: その 1 行を削除して、
source ~/.bashrcします(開いている端末では、unset -f vbでも消えます)。 - 前提: VirtualBox が Windows の既定の場所(
C:\Program Files\Oracle\VirtualBox)にあること。違う場所なら、パスを変えます。
この記事の PoC-1 の記録(2.2 と 5.1)は、当時 PowerShell で実行した出力で、記録のままです(PS C:\…> で始まる行が、それです)。同じ引数を、WSL2 では vb に続けて書きます。
3. 確認: NAT を切っても、ラボの通信は続く
アダプターの設定が正しくても、実際に通信が分離されているかは別の問題です。PoC-1では、2 台の NAT のリンクを切断して、ラボの通信が内部ネットワークだけで続くかを確認しました。切断は VirtualBox の setlinkstate1 off で行いました(申告。コマンドの出力は記録がありません)。
VirtualBox の操作(対象: VM、WSL2 の bash、一般ユーザー。上述 の vb を使います): vb controlvm "<VM名>" setlinkstate1 off
- 目的: NAT のアダプター(アダプター 1)のケーブルを抜いた状態にする。
- 影響: NAT 経由の SSH や時刻同期が止まる。VM は動き続ける。
- 復旧:
setlinkstate1 on。
その状態の client の記録です。
$ ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
enp0s3 DOWN 08:00:27:1f:fa:7c <NO-CARRIER,BROADCAST,MULTICAST,UP>
enp0s8 UP 08:00:27:af:87:fe <BROADCAST,MULTICAST,UP,LOWER_UP>
exit=0
$ ip -br addr
lo UNKNOWN 127.0.0.1/8 ::1/128
enp0s3 DOWN
enp0s8 UP 192.168.10.10/24
exit=0
$ ip route
192.168.10.0/24 dev enp0s8 proto kernel scope link src 192.168.10.10 metric 101
exit=0
出典: data/poc-1-almalinux-lan/isolation-client.txt#L3-L4(抜粋 L3-4,L10,L15、全 40 行のうち 13 行を表示、27 行を省略)
enp0s3(NAT)は DOWN(NO-CARRIER)で、アドレスがなく、既定ルートもありません。経路は、内部ネットワークの 192.168.10.0/24 だけです。この状態で、client から server への ping は、4 回とも成功しました。
$ ping -c 4 -W 2 192.168.10.20
PING 192.168.10.20 (192.168.10.20) 56(84) bytes of data.
64 bytes from 192.168.10.20: icmp_seq=1 ttl=64 time=1.82 ms
64 bytes from 192.168.10.20: icmp_seq=2 ttl=64 time=1.70 ms
64 bytes from 192.168.10.20: icmp_seq=3 ttl=64 time=1.35 ms
64 bytes from 192.168.10.20: icmp_seq=4 ttl=64 time=1.20 ms
--- 192.168.10.20 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3007ms
rtt min/avg/max/mdev = 1.203/1.515/1.819/0.250 ms
exit=0
出典: data/poc-1-almalinux-lan/isolation-client.txt#L25-L35(抜粋 L25-35、全 40 行のうち 11 行を表示、29 行を省略)
NAT 側の 10.0.2.2 への ping は、失敗しました。
$ ping -c 2 -W 2 10.0.2.2
ping: connect: Network is unreachable
exit=2
出典: data/poc-1-almalinux-lan/isolation-client.txt#L37-L39(抜粋 L37-39、全 40 行のうち 3 行を表示、37 行を省略)
この結果から言えるのは、NAT を切っても、ラボの通信は続くことと、NAT 側への経路は、その時点でなかったことです。「内部ネットワークから外部へ出られないことの、直接の証明」ではありません。外へ出られない根拠は、主にアダプターの設定(2.2)と、VirtualBox の仕様(2.1)です。この確認の限界は、PoC-1 の README にも書かれています。
4. 失敗例: アダプターを分けても、通信が NAT 側へ出た
アダプターの設定が正しくても、VM の中の設定で、ラボの通信が NAT 側へ出ることがあります。静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるで起きた例です。
状況は、次のとおりです。R1(router)では、ファイアウォール(firewalld)のゾーンを使い、ラボ側の enp0s8、enp0s9 を internal に、NAT 側の enp0s3 を public に入れようとしました。しかし、enp0s8 が最初から public に入っていました。
ファイアウォールの設定(対象: R1 router、sudo、firewalld の実行時の設定):
$ sudo firewall-cmd --zone=internal --add-interface=enp0s8
Error: ZONE_CONFLICT: 'enp0s8' already bound to 'public'
exit=18
$ sudo firewall-cmd --get-active-zones
internal
interfaces: enp0s9
public
interfaces: enp0s3 enp0s8
exit=0
出典: data/exp-static-route/from-router/exp4-router-fw-zone-on-20261023T003629.txt#L3-L5(抜粋 L3-5,L11-16、全 17 行のうち 9 行を表示、8 行を省略)
--add-interface は、すでに別のゾーンにあるインターフェースではエラーになりました(ZONE_CONFLICT。この挙動は、firewalld のマニュアルに記載がなく、記録による観察です)。enp0s9 だけが internal に移り、enp0s8 は enp0s3 と同じ public に残りました。
- 目的: ラボ側のインターフェースを
internalゾーンに入れる。 - 影響: エラーになったコマンドでは、何も変わりません(拒否されました)。同じ手順で
enp0s9がinternalに移っていて、実行時の設定だけが変わっています。 - 復旧:
firewall-cmd --reload(永続設定の状態に戻る。静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるの環境では、スクリプトのコメントとZONE_CONFLICTの記録によると、永続設定はenp0s8がpublicのままでした(--reloadの後に、ゾーンを確認した記録はありません)。新しい VM(2026-11-03〜04 に作った router と router2)では、状態が違いました(E3 の記事)。下の復旧の注意を読んでください)。
その状態で、client から server への ping(192.168.31.10 → 192.168.32.20)を行い、R1 で tcpdump -i any を取りました。R1 には、192.168.32.0/24 の経路がなく、NAT の既定ルート(default via 10.0.2.2 dev enp0s3)があった、というのが実験の記録 data/exp-static-route/README.md の記述です(漏れた時点の ip route の出力の記録は、ありません)。
$ tcpdump -n -r exp4-router-20261023T004926.pcap
⋮
00:49:39.013697 enp0s8 In IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 3, seq 1, length 64
00:49:39.013803 enp0s3 Out IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 3, seq 1, length 64
00:49:40.043212 enp0s8 In IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 3, seq 2, length 64
00:49:40.043303 enp0s3 Out IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 3, seq 2, length 64
00:49:41.065708 enp0s8 In IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 3, seq 3, length 64
00:49:41.065750 enp0s3 Out IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 3, seq 3, length 64
出典: data/exp-static-route/from-router/exp4-router-capture-20261023T004926.txt#L249-L254(抜粋 L249-254、全 256 行のうち 7 行を表示、249 行を省略)
client の echo request が、enp0s8 から入り、enp0s3(NAT 側)から出ています(3 回とも)。client の ping は、100% loss でした。応答は観測していません。
なぜ出たか、という理由は、候補です(未検証)。R1 に 192.168.32.0/24 への経路がなく、NAT の既定ルートに従って転送されたこと。そして、enp0s8 と enp0s3 が同じ public ゾーンだったため、ゾーン内の転送が許可されたことです。
対処と、確認できたこと
対処は、enp0s8 も internal へ移すことでした。--add-interface ではなく、--change-interface を使います(firewalld のマニュアルでは、--change-interface は、--remove-interface のあとに --add-interface を行うのと同じです。照合の記録の O10)。次の記録は、スクリプトを修正した後の、同じ 2026-10-23 の 02:44 の実行です。最初の対処を行ったときの実行記録は、個別のファイルにありません。
ファイアウォールの設定(対象: R1 router、sudo、実行時の設定。--permanent は付けない):
$ sudo firewall-cmd --zone=internal --change-interface=enp0s8
success
exit=0
$ sudo firewall-cmd --zone=internal --change-interface=enp0s9
success
exit=0
$ sudo firewall-cmd --get-active-zones
internal
interfaces: enp0s8 enp0s9
public
interfaces: enp0s3
exit=0
出典: data/exp-fault-ip/from-router/exp4-router-fw-zone-on-20261023T024435.txt#L3-L16(抜粋 L3-16、全 17 行のうち 12 行を表示、5 行を省略)
- 目的: ラボ側の 2 つのインターフェースを
internalに、NAT 側をpublicに分ける。 - 影響: 実行時の設定だけが変わる(永続設定は変えない)。
internalとpublicの間の転送の扱いが変わる。 - 復旧:
firewall-cmd --reloadで、永続設定の状態に戻る(実行時の変更は、すべて消える。マニュアルにも、永続設定にない実行時だけの変更は、reload で失われる、とあります)。ただし、静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるの環境では、永続設定でenp0s8がpublicで、reload の後は、漏れが起きた状態に戻ると書かれています(route-test.shのコメントとZONE_CONFLICTの記録による。reload の後に、ゾーンを確認した記録はありません)。新しい VM の router と router2(2026-11-03〜04 に作成)では、down(--reloadを含む)の約 1 分後の--get-active-zonesがpublic: enp0s3 enp0s8 enp0s9で、ラボの NIC がpublicに入っていました(E3 の記事。同じ操作の別の回では、約 4 分後に、enp0s8、enp0s9が表示されないこともありました。理由は未確認です)。ラボの通信を流す前に、ゾーンを設定し直すか、NAT の既定ルートがないことを確認してください。スクリプトのfw-zone offも、復旧の候補としてコメントにありますが、2 つのインターフェースをpublicに戻す(route-test.sh)ので、漏れが起きる状態と同じになります(この記事では実行していません)。
対処後、ラボの通信が NAT 側へ出なくなったかを、R1 の capture で見ました。
$ tcpdump -n -r exp4-router-20261023T011508.pcap
⋮
01:15:19.086099 enp0s8 In IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 4, seq 1, length 64
01:15:19.086276 enp0s8 Out IP 192.168.31.1 > 192.168.31.10: ICMP net 192.168.32.20 unreachable, length 92
01:15:20.088838 enp0s8 In IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 4, seq 2, length 64
01:15:20.088961 enp0s8 Out IP 192.168.31.1 > 192.168.31.10: ICMP net 192.168.32.20 unreachable, length 92
01:15:21.091182 enp0s8 In IP 192.168.31.10 > 192.168.32.20: ICMP echo request, id 4, seq 3, length 64
01:15:21.091270 enp0s8 Out IP 192.168.31.1 > 192.168.31.10: ICMP net 192.168.32.20 unreachable, length 92
出典: data/exp-static-route/from-router/exp4-router-capture-20261023T011508.txt#L14-L19(抜粋 L14-19、全 23 行のうち 7 行を表示、16 行を省略)
echo request は enp0s8 から入りますが、enp0s3 から出る行はありません(R1 が net unreachable を返しています)。ただし、この結果を、ゾーンの修正だけの効果とは言い切れません。この capture の直前の 01:13:55 に、NAT の既定ルートも外していたためです(defroute off)。経路がなければ、転送されないのは当然だからです。
$ sudo ip route del default via 10.0.2.2 dev enp0s3
exit=0
出典: data/exp-static-route/from-router/exp4-router-defroute-off-20261023T011355.txt#L3-L4(抜粋 L3-4、全 11 行のうち 2 行を表示、9 行を省略)
- 対象と権限: R1 router、sudo、実行時の経路(永続設定は変えない)。
- 目的: NAT の既定ルートを外して、ラボの通信が NAT 側へ出ないようにする。
- 影響: R1 から NAT 経由(10.0.2.x の外)への通信が止まります。
- 復旧:
ip route add default via 10.0.2.2 dev enp0s3 metric 100、または VM の再起動(元の経路はmetric 100でした)。
さらに、外した既定ルートは、R2 で、外してから約 7 分後の確認の時点で復活していました(復活した時刻は不明。復活の原因は未検証で、候補は NetworkManager の DHCP リースの更新です)。既定ルートを一時的に外す方法は、確実ではありません。実験では、ゾーンの設定で隔離を担保することにしました。
2026-10-31 時点のゾーンの割り当ては、R1 と R2 で同じでした(確認記録)。
## [1] router(R1)のゾーン(読み取りのみ)
<WSL_USER>:~$ ssh -t -p 2225 user@127.0.0.1 'hostname -s; sudo firewall-cmd --get-active-zones; sudo firewall-cmd --zone=internal --list-all'
router
internal
interfaces: enp0s8 enp0s9
public
interfaces: enp0s3
出典: data/lab-state/user-supplied-20261031.txt#L5-L11(抜粋 L5-11、全 103 行のうち 7 行を表示、96 行を省略)
この失敗例から言えることは、次の 2 つです。
- 隔離は、アダプターの設定(VirtualBox 側)だけでなく、VM の中の設定(経路、ゾーン)にも依存する。
- 「NAT 側へ出ていないか」は、ルーターで
tcpdumpを取って確認できる(読み取りだけで行える)。この実験では、そのように確認した。
5. 戻せる状態を作る: スナップショットと、構成の再現
5.1 スナップショット
VM の状態を保存して、あとで戻す機能が、スナップショットです。PoC-1 では、client と server に poc1-ip-configured を取りました(転記。PowerShell の出力で、取得時刻は不明です)。
VirtualBox の操作(対象: VM、一般ユーザー)。次の記録は、PoC-1 で PowerShell から実行した出力です。WSL2 では、vb snapshot "<VM名>" take "<名前>" と書きます(E2b と E3 の記録に、WSL2 の vb snapshot … take の実行があります):
PS C:\Users\<WINDOWS_USER>> & "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" snapshot "Alma9mini-cli" take "poc1-ip-configured" --description "IP設定済み・時刻同期済み"
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Snapshot taken. UUID: db8f8727-1221-4bd5-bbeb-0ceed52f2c95
出典: data/poc-1-almalinux-lan/snapshot-and-reboot-raw.txt#L7-L9(抜粋 L7-9、全 102 行のうち 3 行を表示、99 行を省略)
- 目的: IP 設定済みの状態に、名前を付けて保存する。
- 影響: スナップショットが増える(ディスク容量も増える)。VM の動作は変わらない。
- 復旧: 不要になったスナップショットは、VirtualBox マネージャー、または WSL2 の
vb snapshot <VM> delete <名前>で削除する。
複数の VM に、同名のスナップショットを一度に取るスクリプト(labs/common/snapshot-all.ps1)があります。PowerShell 用のスクリプトで、WSL2 で同じことをするスクリプトは、リポジトリにありません(baseline.sh、transfer.sh などには、.sh 版があります)。スクリプトの先頭の説明によると、次のように動きます。
- 起動中の VM を、ACPI の電源ボタンで停止してから、スナップショットを取る(VM のデータは変わらない)。
- 同名のスナップショットがある VM は、取らずにスキップする。
- スナップショットの削除はしない。
- 実行の記録は、
data/にありません(スクリプトの説明からの記述です)。
復元の注意: スナップショットを復元すると、取得後に VM の中に作ったファイル(未回収の記録)は失われます(VirtualBox 7.1 のガイドに、現在の状態が失われ、仮想ハードディスクが元に戻るため、スナップショットの後に作ったファイルと、ファイルの変更が失われる、とあります。復元の前に、新しいスナップショットを取れば、現在の状態を失わずに済む、ともあります)。復元する前に、記録を回収してください。また、復元すると、VM の設定(メモリなど)も、取得時のものに戻ります。
スナップショットを取った後の、最初の起動が失敗することがありました(再起動すると成功。原因は未特定ですが一度に複数起動すると失敗することが多く一つずつ時間を置いて起動すると成功しました。
5.2 構成の再現: baseline.sh
ラボの構成(アドレス、経路、ゾーン)は、スクリプト labs/common/baseline.sh で、一括で作ったり外したりできます(up、down、status)。変更は、各 VM の実行時の設定だけで、永続設定は変えません。NAT(enp0s3)と SSH は変えません。
ラボの構築(対象: 4 台の VM、WSL2、一般ユーザー。sudo のパスワードを聞かれる): labs/common/baseline.sh up
- 目的: 4 台のラボの構成を作り、client から server への ping で確認する。
- 事前条件: 各 VM のスナップショットか、コンソールからの操作ができること(SSH が切れても戻せるように)。WSL のラボ用 ssh-agent に鍵が載っていること(
baseline.shの「前提」)。 - 影響: 各 VM の実行時の設定が変わる。ラボの NIC(
enp0s8、enp0s9)のアドレスのほか、NetworkManager の管理(nmcli device set … managed no)、ip addr flush、ip_forward=1、ルーターのゾーン、client のguard on(192.168.0.0/16 宛の到達不能ルート)も変わる(baseline.shの先頭のコメントと、route-test.sh、fault-test.shによる)。永続設定、NAT(enp0s3)、SSH は変えない。 - 復旧:
baseline.sh down、または VM の再起動。
up の後は、client から server への ping が成功し、ttl=62 になるのが基準です(ルーターを 2 台通るので、64 から 2 減ります)。記録の例です(2026-10-30)。
### $ ping -c 3 -W 2 192.168.32.20
PING 192.168.32.20 (192.168.32.20) 56(84) bytes of data.
64 bytes from 192.168.32.20: icmp_seq=1 ttl=62 time=7.22 ms
64 bytes from 192.168.32.20: icmp_seq=2 ttl=62 time=3.64 ms
64 bytes from 192.168.32.20: icmp_seq=3 ttl=62 time=3.41 ms
出典: data/baseline/baseline-sh-up-20261030T014404.txt#L24-L28(抜粋 L24-28、全 42 行のうち 5 行を表示、37 行を省略)
ラボの撤去(対象: 4 台の VM、WSL2、一般ユーザー。破壊的な操作): labs/common/baseline.sh down
- 目的: ラボの構成を撤去して、各 VM を NetworkManager の管理に戻す。
- 影響: 実行時の設定が消える。
firewall-cmd --reload、ip addr flush、ip_forward=0、既定ルートの復旧、client のguardの解除を含む(baseline.shの先頭のコメントと、route-test.shによる)。ラボのアドレスが消えるため、ラボの通信は止まる(NAT と SSH は変えない)。 - 復旧:
baseline.sh up、または VM の再起動。 - 注意:
downの後のゾーンは、VM によって違いました。静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるの環境では、enp0s8が永続設定のpublicに戻ると書かれています(確認の記録なし)。新しい VM(2026-11-04)では、down(--reloadを含む)の約 1 分後の status で、ラボの NIC がpublicに入っていました(別の回では、表示されないこともありました。4 章の「復旧の注意」、E3 の記事)。
6. まとめ
- ラボの通信は、内部ネットワークだけを通し、NAT は管理用に限ります。
- NAT を切った状態でも、ラボの通信は続きました。ただし、これは「外へ出られないことの証明」ではありません。
- アダプターを分けるだけでは足りませんでした。静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるでは、
enp0s8がpublicゾーンに入っていた状態で、ラボの通信が NAT 側へ出るのを観測しました(理由は候補)。ゾーンをinternalに直し、tcpdumpで確認します。 - 変更の前にスナップショットを取り、復元の前に記録を回収します。
要検証(未確認・記録なし)
- NAT のリンクを切断した操作の出力(申告のみ。記録にあるのは
setlinkstate1 offまでで、controlvm "<VM名>"を付けた形と、WSL2 のvbでの実行は、一般的な使い方からの書き起こし。この記事では WSL2 から実行していません)。PoC-1 の設定の記録(2.2)の取得時刻。 - 漏れた理由(R1 に経路がなく、同じ
publicゾーン内の転送が許可された、という説明)は、候補。 - ゾーンの修正だけの効果(既定ルートの削除と同時に行ったため、分離できていない)。
- 外した既定ルートが約 7 分後に復活した原因(候補: DHCP のリースの更新)。
- スナップショット後の初回起動が失敗する原因。
- 4 章までの実験(静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるなど)の記録は、同じ構成(client、R1、R2、server)の別の環境で取ったものです。この記事の構成と同じ VM の作り方と、新しい VM での確認は、E3 にあります。ゾーンの扱いなど、環境で違った点は、本文に書き分けました。
snapshot-all.ps1の実行記録がない(スクリプトの説明からの記述)。- 4 台の NIC の実機の設定と、各 VM の資源(E3 の記事で確認)。
- 隔離の保証(ホストの LAN やインターネットへ、一切出ないこと)は、確認できていません。この記事は、確認できた範囲(NAT を切っても続く、ゾーン修正後の capture に出る行がない)を書いたものです。
付録: 操作の一覧
| 操作 | 対象・権限 | 内部で実行されるコマンド | 状態変更 | 復旧 |
|---|---|---|---|---|
| NAT のリンクを切る | WSL2(vb)、一般ユーザー | vb controlvm "<VM>" setlinkstate1 off | VM のアダプター 1 の状態が変わる | setlinkstate1 on |
| ゾーンの割り当て | VM の中、sudo | firewall-cmd --zone=internal --change-interface=<IF> | 実行時のゾーンの割り当てが変わる | firewall-cmd --reload(永続設定の状態に戻る。実行時の変更はすべて消える。ただし静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるの環境では、永続設定が enp0s8 を public にしていて、漏れた状態に戻ると書かれている(確認の記録なし)。新しい VM(2026-11-04)では、down の約 1 分後に、enp0s8、enp0s9 が public に入っていた(別の回では、表示されないこともあった。E3)。route-test.sh の fw-zone off の扱いは、静的ルートがないと、何が起きるか: 経路の欠落と、戻り経路の欠落を、ping と tcpdump で見分けるの観測) |
| 既定ルートを外す | VM の中、sudo | ip route del default via 10.0.2.2 dev enp0s3 | 実行時の経路が変わる(NAT 経由の通信が止まる) | ip route add default via 10.0.2.2 dev enp0s3 metric 100、または VM の再起動 |
| スナップショットの取得 | WSL2(vb)、一般ユーザー | vb snapshot "<VM>" take "<名前>" | スナップショットが増える | vb snapshot "<VM>" delete "<名前>" |
| スナップショットの復元 | WSL2(vb)、VM は電源オフ | vb snapshot "<VM>" restore "<名前>"(この記事では実行例なし) | 取得後の VM の変更がすべて失われる | 復元の前に記録を回収する。復元の前に、現在の状態のスナップショットを取っておけば、現在の状態を失わずに済む(VirtualBox 7.1 のガイドによる) |
| 複数 VM のスナップショット | PowerShell(WSL2 用のスクリプトはない)、一般ユーザー | labs/common/snapshot-all.ps1(VM を ACPI 停止してから取得) | VM が停止する。スナップショットが増える | 不要なスナップショットは削除する |
| ラボの構築 | WSL2、一般ユーザー(sudo) | labs/common/baseline.sh up | 各 VM の実行時の設定が変わる(アドレス、NetworkManager の管理、ゾーン、ip_forward、guard) | down、または VM の再起動 |
| ラボの撤去(破壊的) | WSL2、一般ユーザー(sudo) | labs/common/baseline.sh down | 実行時の設定が消える(--reload、ip addr flush、ip_forward=0 など)。ラボの通信が止まる | up、または VM の再起動 |