- Rust 97.6%
- Shell 2.4%
- Workspace version 0.4.0 -> 0.5.0 (all crates inherit; Cargo.lock updated). 0.4.0 was unreleased, so this rolls the unreleased line forward. - CHANGELOG: new [Unreleased] - 0.5.0-dev section (multi-queue dataplane, per-queue observability, block_in_place removal, F-006 kernel-NAPT port fix, upgrading note); demote the tun-rs block to [Unreleased - earlier 0.4.0-dev] per the file's convention. - AGENTS.md / CODE_STRUCTURE.md: replace the stale single-threaded block_in_place run-loop description with the thread-per-core model (dataplane.rs QueueLoop, run vs run_multi, Tun::attach_queue facade, wait-free steady path). - docs/operator.md: queue-sizing guidance tied to the bench report. |
||
|---|---|---|
| contrib | ||
| crates | ||
| docs | ||
| examples | ||
| fuzz | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| CODE_STRUCTURE.md | ||
| nat64.toml | ||
| README.md | ||
nat64
Stateful NAT64 daemon (RFC 6146 + RFC 7915) in Rust. Replaces Tayga at the routing level for Mycelium-overlay workloads that need to reach the IPv4 internet.
- PRDs:
docs/prd - ADRs:
docs/adr - Operator notes:
docs/operator.md - Example configs:
examples/nat64.toml— daemon-NAPT (v4 pool)examples/nat64-kernel.toml— kernel-NAPT (ADR-0020)
Build
cargo build --release
Binary is target/release/nat64. Run nat64 --help for subcommands.
Prefix selection
NAT64 can use either the RFC 6052 Well-Known Prefix (64:ff9b::/96)
or an operator-chosen Network-Specific Prefix (NSP). Pick based on
where your v6 clients live:
- Global IPv6 → public v4 internet: use
64:ff9b::/96. RFC 6052 §3.1 forbids combining it with RFC1918 / loopback pools; the daemon enforces that check at startup. - Overlay networks with a constrained range (e.g. Mycelium,
which only carries
400::/7): carve a /96 out of the overlay's routable range and use that as your NSP. Example:prefix = "400:dead:beef::/96". No RFC 6052 §3.1 restriction applies to NSPs, so RFC1918 pools are fine. - Corporate / lab IPv6: any /96 out of your own space works.
Side-effect worth knowing: daemon-originated ICMP (TTL-exceeded, and
PTB in v0.2) uses prefix || gateway_v4 as its v6 source per
ADR-0011. When the prefix sits inside your overlay's routable range,
replies from the translator are automatically reachable over the
overlay — no extra route needed.
NAPT modes (ADR-0020)
Two backends, selected by the napt config key:
-
napt = "daemon"(default, v0.2). Userspace NAPT over a provider-allocated v4 pool. Each v6 source gets per-flow port allocation; distinct clients take distinct pool v4s. Right choice when a provider gives you a/28(or similar) of routable v4. -
napt = "kernel"(ADR-0020). 1:1 v6 -> inner-v4 mapping; the host kernel's MASQUERADE hook owns port allocation and conntrack. The daemon never binds any v4 address on any interface, so the F-001local-table collision class cannot occur.--config geomindauto-selects this mode.
See docs/operator.md "NAPT mode selection" for
the per-mode plumbing.
Status
v0.1 scope: /96 prefix only, TCP/UDP/ICMP, stateless per-fragment
translation, 1:1 v6→v4 mapping, in-memory bindings with a 5-minute
reaper. v0.2 (PRD-0002) adds NAPT, Prometheus metrics, UDS show,
and pool affinity. ADR-0020 layers a kernel-delegated NAPT option
on top without changing the v0.2 default.
Workspace layout
crates/nat64-core— library (translation core, binding table, pool)crates/nat64— daemon binary (CLI, TUN I/O, reaper, ICMP rate limiter)