Use a genuinely random ULA /48 for auto-allocated IPv6 subnets
The old fd00:168:0::/48 base was never actually generated via RFC 4193's randomization procedure -- just a memorable placeholder chosen to visibly pair with the IPv4 10.168.x.x scheme. Replaced with fdf0:f243:f06f::/48, a real randomly-generated ULA prefix. That /48 consumes all three "identity" hextets a ULA prefix has room for, leaving only the subnet-id (4th) hextet -- the same one the per-network auto-allocation index already lived in -- with nowhere left to also place a fixed "168" marker without colliding with either the random prefix or the index itself. Per the user's own choice (offered two options): the per-network index is now offset by a constant 168 instead of matching IPv4's index number-for-number, so the first auto-allocated network's IPv6 block is fdf0:f243:f06f:168::/64 (paired with 10.168.0.0/24), second is ...:169::/64 (paired with 10.168.1.0/24), and so on -- deterministic and still visibly project-stamped, just via a constant offset instead of an identical digit. network_subnet.cpp's new ipv6_ula_prefix48/ipv6_subnet_id_base constants hold the new prefix and offset. Verified as root via the doas rule: two freshly created extern networks got fdf0:f243:f06f:168::/64 and fdf0:f243:f06f:169::/64 exactly as expected, correctly paired with their IPv4 subnets. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gv3s5jckJKzh6JkMoi2Akz
This commit is contained in:
@@ -103,13 +103,18 @@ than one extern network and didn't disambiguate.
|
||||
network (`10.168.1.0/24`, `10.168.2.0/24`, ...), with an optional
|
||||
`--subnet <cidr>` override at `-n/--network` creation time.
|
||||
- **IPv6 is a per-network on/off option, defaulting to enabled.** When on,
|
||||
also auto-allocates a ULA `/64` alongside the IPv4 block from a matching
|
||||
incrementing base (proposed: `fd00:168:0:1::/64`, `fd00:168:0:2::/64`, ...
|
||||
— mirroring the `168` from the v4 base so the two are visibly paired), with
|
||||
a `--subnet6 <cidr>` override. `--no-ipv6` at creation time skips both the
|
||||
v6 allocation and the IPv6-forwarding sysctl for that network entirely
|
||||
(there's no `ip6tables` setup to skip — see "Mechanism" above for why one
|
||||
is never added at all).
|
||||
also auto-allocates a ULA `/64` alongside the IPv4 block: a randomly
|
||||
generated `/48` (RFC 4193 — `fdf0:f243:f06f::/48`, replacing an earlier
|
||||
`fd00:168:0::/48` placeholder that was never actually randomly generated;
|
||||
see the "Resolved" IPv6 randomization section further below) with the
|
||||
subnet-id hextet offset by a fixed `168` — `fdf0:f243:f06f:168::/64`,
|
||||
`fdf0:f243:f06f:169::/64`, ... — keeping the same project-recognizable
|
||||
`168` stamp the old scheme's fixed 2nd hextet had, now as a constant
|
||||
offset rather than a numerically-identical index. `--subnet6 <cidr>`
|
||||
overrides it per network as before. `--no-ipv6` at creation time skips
|
||||
both the v6 allocation and the IPv6-forwarding sysctl for that network
|
||||
entirely (there's no `ip6tables` setup to skip — see "Mechanism" above for
|
||||
why one is never added at all).
|
||||
|
||||
## CLI surface
|
||||
|
||||
@@ -195,7 +200,9 @@ pass.
|
||||
parallel to `VolumeEntry`/`volumes`.
|
||||
- New `network_subnet.{h,cpp}`: IPv4 `/24` auto-allocation starting at
|
||||
`10.168.0.0/24` incrementing per existing network, `--subnet` override;
|
||||
paired IPv6 ULA `/64` auto-allocation (`fd00:168:0:N::/64`) when enabled
|
||||
paired IPv6 ULA `/64` auto-allocation (`fd00:168:0:N::/64` at the time —
|
||||
**later replaced with a genuinely randomly generated `/48`, see the
|
||||
"Resolved" IPv6 randomization section further below**) when enabled
|
||||
(default), `--subnet6` override, `--no-ipv6` to skip. Pure allocation
|
||||
logic against the already-loaded config's existing networks — no kernel/
|
||||
`ip`/`iptables` calls in this commit.
|
||||
@@ -489,6 +496,34 @@ way later) — only the `ip6tables` MASQUERADE call itself, and the
|
||||
still means "skip IPv6 addressing entirely," an orthogonal decision from
|
||||
whether NAT is ever attempted for the addresses that are assigned.
|
||||
|
||||
## Resolved: IPv6 base prefix is now genuinely randomly generated
|
||||
|
||||
**Trigger**: a user asked directly, once IPv6 NAT was already dropped (see
|
||||
above) — the original `fd00:168:0::/48` base was never actually generated
|
||||
via RFC 4193's randomization procedure, just a memorable placeholder picked
|
||||
to visibly pair with the IPv4 `10.168.x.x` scheme. Since ULA's whole
|
||||
collision-avoidance property depends on the /48 actually being randomly
|
||||
chosen (not on it being memorable), a real generator was worth using.
|
||||
|
||||
**Replaced with `fdf0:f243:f06f::/48`** (user-provided, from an external ULA
|
||||
generator). Confirmed with the user (`AskUserQuestion`, two options offered)
|
||||
how to keep the old scheme's recognizable `168` stamp: the /48 alone
|
||||
consumes all three "identity" hextets a ULA prefix has room for, leaving
|
||||
only the subnet-id (4th) hextet — the same one the per-network auto-
|
||||
allocation index already lived in — with nowhere left to also place a fixed
|
||||
marker without colliding with either the random prefix or the index. Chosen
|
||||
answer: **offset the per-network index by a constant `168`** rather than
|
||||
matching IPv4's index number-for-number as before. First auto-allocated
|
||||
network's IPv6 block is now `fdf0:f243:f06f:168::/64` (paired with IPv4's
|
||||
`10.168.0.0/24`), second is `fdf0:f243:f06f:169::/64` (paired with
|
||||
`10.168.1.0/24`), and so on — deterministic and still visibly
|
||||
project-stamped, just via a constant offset instead of an identical digit.
|
||||
`network_subnet.cpp`'s `ipv6_ula_prefix48`/`ipv6_subnet_id_base` constants
|
||||
hold the new prefix and the `168` offset respectively. Verified as root via
|
||||
the `doas` rule: two freshly created `extern` networks got
|
||||
`fdf0:f243:f06f:168::/64` and `fdf0:f243:f06f:169::/64` exactly as
|
||||
expected, correctly paired with `10.168.0.0/24`/`10.168.1.0/24`.
|
||||
|
||||
## Explicitly out of scope for now
|
||||
|
||||
- **Rootless networking.** An earlier draft of this design considered a
|
||||
|
||||
Reference in New Issue
Block a user