This deploy uses two containers:

- `router` is the user-facing machine. Participants connect to `R2` and add `iptables` rules there.
- `checker` is a separate verifier. It does not expose a shell and only validates the firewall behavior.

Inside `router`, the lab topology is created with Linux network namespaces:

- `r3` namespace: remote router over the VPN tunnel
- `outpost` namespace: `192.168.40.10`
- `router` namespace: `R2` with `tun0` and DMZ interface
- `dmz` namespace: `192.168.30.10` and `192.168.30.20`

Run locally:

```bash
cd deploy
docker compose up --build
```

Connect:

```bash
ssh steve@localhost -p 2231
```

Password:

```text
pass123
```

Inside `router`, add the candidate rule and then run:

```bash
iptables -A FORWARD -p tcp -s 192.168.40.0/24 -d 192.168.30.10 --dport 22 -m conntrack --ctstate NEW -j ACCEPT
python3 /opt/router/check_rule.py
```

What the checker validates:

- `192.168.40.10 -> 192.168.30.10:22/tcp` must work
- `192.168.40.10 -> 192.168.30.10:8080/tcp` must fail
- `192.168.40.10 -> 192.168.30.20:22/tcp` must fail
- `192.168.40.10 -> 192.168.30.10` via ICMP must fail
