# NAT-traversal simulation (Covalence direct, SYNC_PROTOCOL §3.3)

Drives the **real** STUN + hole-punch core (`Sources/NucleicProtocol/Sync/Direct`, via the
`nucleic-punch-harness` executable) across Linux network namespaces joined by NAT gateways —
so results are evidence about the shipping punch logic, not a mock.

## Running

Needs root (netns + nftables), `iproute2`, `nftables`, and a built harness. Run inside a
privileged Linux container or VM:

```sh
swift build --product nucleic-punch-harness
sudo scripts/nat-sim/run.sh cone        # both NATs port-preserving  → punch should succeed
sudo scripts/nat-sim/run.sh symmetric   # both NATs random-port      → detect symmetric, give up
```

Topology: `peerA ── natA ── inet(STUN) ── natB ── peerB`, private home subnets deliberately
**not** cross-routed so the only path between peers is through their public reflexive
addresses (a genuine punch).

## What it validates

- **STUN discovery + NAT classification** against real NATs: `cone` mode is detected as
  `cone` (same mapped port from both STUN servers), `symmetric` mode as `symmetric`
  (differing ports). This is the signal the punch *policy* keys off
  (`punchWorthAttempting`), and it passes.
- **Candidate gathering**: each peer produces its reflexive + local candidates with the
  correct ports (cone preserves the port; the reflexive port equals the local port).

## Punch-through caveat

The reflexive punch-through leg in the netns sandbox depends on the host's
`nf_conntrack` module behaving as an endpoint-independent-mapping / address-restricted-
filtering NAT — which not every CI kernel/container exposes identically. The punch *logic*
itself is proven directly and deterministically elsewhere and does not depend on this
harness:

- `PunchEngineTests` — the state machine, incl. lossy convergence, over injected I/O.
- `PunchEngineTests.liveLoopbackPunchValidatesBothSides` — two real UDP sockets, real
  round-trip validation.
- `DirectPathLoopbackTests` (macOS) — the full punch → QUIC port-handoff → framed transfer.

Treat this harness as the STUN/classification check and a manual punch-through probe on a
kernel you control; the automated punch-correctness guarantee lives in the unit + loopback
tests above.
