Linux integration fixtures
==========================

These scripts exercise kernel routing and transparent sockets. Bash syntax and
mocked command tests do not establish their results. Run them as root on a
recoverable Linux test host; macOS and cross-compilation cannot run these tests.
Required tools for linux_docker_route.sh: util-linux (unshare, mount, flock),
iproute2, iptables with matching NAT/CONNMARK/addrtype support, ipset, Python 3,
and ordinary GNU shell tools. The test does not install packages or load a real
Docker daemon.

Bridge publishing, multiple ingress interfaces, and original destination:

  sudo bash test/integration/linux_docker_route.sh

The script always creates fresh network and mount namespaces before any network
mutation. A private /run tmpfs contains named namespace handles; environment or
command-line flags cannot disable isolation. Configuration, lock, CIDR lists,
destination lists, and route inventory are created under a temporary /tmp
folder. Production network-apply, network-check, and network-remove receive
explicit paths to that state. They do not read or write their default /etc
configuration. Docker inventory is a temporary test executable, so no host
Docker socket is queried. The namespace and temporary files are discarded at
exit; no service is restarted.

Checks:

- The baseline marked transparent connection to a Docker-equivalent OUTPUT
  DNAT target times out, proving the fixture reproduces the original failure.
- The actual production network application puts the CF NAT hook before an
  existing synthetic Docker PREROUTING hook. Applying twice keeps one CF hook
  and retains the foreign Docker hook.
- A marked backend connection receives a reply from the bridge service, which
  observes the non-local simulated visitor address 198.18.0.123.
- Two ingress interfaces reach one configured gateway listener. Kernel
  SO_ORIGINAL_DST retains each original local IP and the published port despite
  DNAT to the shared listener address.
- A direct untrusted client continues through the original Docker-equivalent
  publishing rule without going to the gateway listener.
- network-check leaves rules, routes, policy, ipsets, and route inventory
  unchanged.
- Production removal clears owned hooks/routes while retaining foreign Docker
  publishing rules.

This is a kernel-network equivalent of bridge publishing, not a test of Docker
itself or the Go gateway's Proxy Protocol parser. A success cannot establish
actual Cloudflare reachability, customer login, UDP/IPv6 support, Docker nftables
backend support, performance at the configured connection limit, or behavior
under overlapping container and client IP ranges. Keep those results separate.

Full compiled gateway / PPv1 test:

  go build -o /tmp/cfpp-test-gateway ./cmd/cf-pp-gateway
  sudo bash test/integration/linux_netns.sh \
    /tmp/cfpp-test-gateway "$(pwd)/packaging/network"

linux_netns.sh tests the Go gateway with PPv1, binary stream preservation, real
client IP, header rejection, original-port validation, missing-header fallback,
and removal of the generated state. It also forces fresh network and mount
namespaces, private /run handles, temporary inventory and lock paths, and an
empty Docker fixture before creating its named namespaces and veth interfaces.
Run it on the isolated test host. Retain its output and the private bridge
fixture output as release evidence, together with actual Docker and upstream
CF tests.
