Add -p/--port-forward: iptables DNAT into extern-joined containers
Commit 5/6 of the network isolation feature (docs/networking-design.md).
port_forward.{h,cpp}: parse_port_forward_spec() parses
"[<network>:]<host-port>:<container-port>"; add_port_forward()
resolves the network (by name, or the container's sole extern network)
against join_networks()'s result and adds the DNAT/FORWARD rules;
remove_port_forward() undoes them. join_networks() (network_join.{h,cpp})
now returns the joined networks with their assigned IPs (was a bare
bool) so port-forward setup knows where to send traffic. -p requires
-r, is repeatable, network names may no longer contain ':' (needed to
keep the spec syntax unambiguous -- is_valid_network_name(),
network_subnet.h).
Two real corrections from testing, not assumed:
- The DNAT rule needs both nat PREROUTING and nat OUTPUT -- PREROUTING
never sees locally-generated packets (e.g. curl run on the same
host), only OUTPUT does. PREROUTING-only left the host's own real IP
connection-refused despite the container being directly reachable.
- curl localhost:<port> still doesn't work even with both chains --
a separate problem, NAT hairpinning: the container sees an inbound
packet claiming a loopback source arriving on a non-loopback
interface and drops it as martian. A net.ipv4.conf.*.route_localnet
sysctl was tried and confirmed not to fix this alone, then removed
rather than left in as dead code. Not solved here (would need scoped
source masquerading or a userland proxy); curl <host's real IP> is
the actually-relevant, verified-working path for real clients.
Also surfaced (unrelated to -p, found while testing it, not fixed
here): -x/--exec doesn't join the net namespace -- written when this
project never isolated networking at all -- so it currently sees the
host's own network stack instead of a network-isolated session's own.
Verified end-to-end as root (via a scoped doas rule): a container
serving HTTP on an extern network with -p 8080:80 was reachable via
curl <host's real IP>:8080; the rule was confirmed gone after the
session was killed.
This commit is contained in:
@@ -266,6 +266,19 @@ pass.
|
||||
- Verify: `-p 8080:80` against a container on an extern network answering
|
||||
on port 80 is reachable via `curl localhost:8080` from the host; the
|
||||
rule is gone after the container exits.
|
||||
- **Landed with two real corrections found by testing** (see
|
||||
`CLAUDE.md`'s `port_forward.{h,cpp}` entry for the full detail): the
|
||||
`DNAT` rule needs both `PREROUTING` *and* `OUTPUT` (locally-generated
|
||||
traffic never traverses `PREROUTING`); and `curl localhost:<port>`
|
||||
specifically still doesn't work even so (NAT hairpinning — the
|
||||
container sees an inbound packet claiming a loopback source on a
|
||||
non-loopback interface and drops it as martian) — verified instead via
|
||||
`curl <host's real IP>:<port>`, the actually-relevant path for real
|
||||
clients. Also surfaced, unrelated to `-p` itself but found while
|
||||
testing it: `-x/--exec` doesn't join the `net` namespace (written back
|
||||
when this project never isolated networking at all), so it currently
|
||||
sees the *host's* network stack, not a network-isolated session's own —
|
||||
not fixed as part of this commit.
|
||||
|
||||
6. **Crash-orphan cleanup sweep**
|
||||
- Extend `--clean-processes` (or add a dedicated `--clean-networks`,
|
||||
|
||||
Reference in New Issue
Block a user