add optional IPv6 egress via NAT66 (NETWORK_IPV6=nat) - #12
Conversation
Add an opt-in IPv6 path for VMs. By default a migrant VM still has no routable IPv6 (dropped at the FORWARD chain); setting NETWORK_IPV6=nat in a Migrantfile gives the guest a ULA and masquerades it to the host's IPv6 uplink, mirroring the IPv4 NAT. Network isolation still blocks the host and LAN over IPv6. - migrant ip -6 and migrant status surface the VM's IPv6 (ULA) address - refused alongside WireGuard (fwmark routing is IPv4-only, so IPv6 would bypass the tunnel) - NETWORK_IPV6 is validated to nat/off; sample Migrantfiles set off
NETWORK_IPV6=nat)
|
Probably needs a test VM and a netcheck.py run to verify that this doesn't open up any unexpected holes. |
NETWORK_IPV6=nat mirrored the IPv4 RFC1918 rejects in FORWARD but left guest->host over IPv6 open: the host's on-link ULA is locally delivered, so it hits INPUT, not FORWARD. Every host IPv6 service was reachable from the guest, and the blanket ICMPv6 accept answered echo too — both looser than the IPv4 path. - add a per-VM ip6tables INPUT reject (CHAIN6), after LIBVIRT_INP so DHCPv6/DNS to dnsmasq still work - settle ICMPv6 at the top of INPUT: accept only NDP (133-136) and PMTUD error types (1-4), reject the rest (echo included), scoped per-tap - reference-count the shared MASQUERADE and forwarding sysctl so they are reverted on the last NAT66 VM instead of persisting after teardown - apply NAT66 masquerade even with NETWORK_ISOLATION=false (was skipped by the early-return guard) netcheck.py gains --ipv6-nat/--ipv6-host-port and NAT66-aware IPv6 tests (egress must work; host must stay unreachable over TCP and ICMPv6). New ipv6/ VM boots with NETWORK_IPV6=nat and runs the checks from post-up. Verified live: egress works, host blocked, teardown reverts cleanly.
|
Added a test VM (
Verified on a live VM: IPv6 egress works, host unreachable over both TCP and ICMPv6, IPv4 isolation unchanged, teardown reverts cleanly. |
|
Why is the test VM in the project root instead of with the other test VMs in |
… configs The NAT66 verification VM lived in the project root as ipv6/, next to the example VMs (arch/, ubuntu/, debian/), but it is a network-isolation test in the same mold as test/isolation-only/, test/lan-host/, etc. — self-contained dir, netcheck.py staged by a playbook, host-side bait listener, verify-and-exit. Move it to test/ipv6-nat/ and make it a true sibling of the other test configs: - cloud-init: use the shared test/cloud-init.yml (python3 + uv) instead of a copy of arch/'s agent cloud-init - Migrantfile: drop the unused workspace shared folder and loop-image config; trim to the terse form the other test configs use; VM_NAME -> test-ipv6-nat - playbook: drop the now-redundant uv install (cloud-init supplies it); reduce to the one-task netcheck staging the siblings use - hooks: drop the logging-only post-down for parity (pre-up/post-up/pre-down) - .gitignore: make the workspace/, wireguard.conf, and .listener*.pid patterns depth-agnostic (**/) so they cover configs nested under test/ — also closes a latent gap for the existing tcp/udp-host-port listener pidfiles - docs: update test/README.md and the CLAUDE.md example-VM note accordingly Verified end-to-end on KVM: netcheck passes — NAT66 egress works and the host stays unreachable over IPv6.
|
Good point. I moved the NAT66 verification VM out of the project root and into While relocating I also converged it onto the test-config conventions: shared Verified end-to-end on KVM — netcheck passes (NAT66 egress works; host stays unreachable over IPv6). |
|
What is the value of describing the |
…it moved under test/
|
it was leftover from before that directory moved under test -- removed. |
NETWORK_IPV6=natin aMigrantfileto give the VM a ULA that the host masquerades to its own IPv6 uplink, mirroring the existing IPv4 NAT.NETWORK_IPV6=natthe VM's IPv6 is still dropped at theFORWARDchain, so nothing changes for existing VMs.NETWORK_ISOLATIONon (the default), the VM reaches the internet but not the host or LAN.virbr-migrantso neighbor discovery to the ULA gateway works; without it NAT66 reply traffic dies on host firewalls that accept ICMPv6 only fromfe80::/10.migrant ip -6andmigrant statussurface the VM's IPv6 (ULA) address, read best-effort from the DHCPv6 lease.migrantnetwork to gain the IPv6 subnet — documented in the README with a migration walkthrough.