Forwarding, and why NAT is next
The VLANs are up, but the router doesn't route yet. A fresh Debian install has IP forwarding off: the kernel accepts packets addressed to itself and drops everything it would have to pass on. Staff can't reach the server VLAN.
/etc/sysctl.d/99-router.conf turns it on: sysctl --system applies it now, and systemd applies it at every boot. Now staff reach the server, and so does a guest, because with no firewall a router forwards everything. That's the reason the firewall comes straight after this step: a router with forwarding on and no firewall connects every network to every other.
The internet still fails. The router forwards staff's request to the ISP unchanged, so it arrives from 10.10.10.20, a private address that the internet can't route back to; the capture on the ISP's side shows the SYNs arriving and nothing returning, and curl gives up (exit code 28, timeout). The fix is NAT, in the firewall configuration.
(Docker Desktop, which runs this lab, starts every container with forwarding on. The lab's setup script turns it off on the router first, so what you see here is what a real Debian install does.)
# /etc/sysctl.d/99-router.conf: route between the WAN and the VLANs.
net.ipv4.ip_forward = 1root@staff:~# ping -c 2 -W 1 10.10.30.10 | tail -2
2 packets transmitted, 0 received, 100% packet loss, time 1018ms
root@router:~# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
root@router:~# cp 99-router.conf /etc/sysctl.d/ && sysctl --system | grep ip_forward
net.ipv4.ip_forward = 1
root@staff:~# ping -c 2 -W 1 10.10.30.10 | tail -2
2 packets transmitted, 2 received, 0% packet loss, time 1024ms
rtt min/avg/max/mdev = 0.055/0.061/0.067/0.006 ms
root@guest:~# curl -s -o /dev/null -w "%{http_code}\n" -m 2 http://10.10.30.10/
200
root@isp:~# timeout 5 tcpdump -lnni eth0 -c 2 tcp port 80
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
21:59:25.284219 IP 10.10.10.20.57186 > 198.51.100.10.80: Flags [S], seq 2259599004, win 64240, options [mss 1460,sackOK,TS val 4198235809 ecr 0,nop,wscale 10], length 0
21:59:26.324529 IP 10.10.10.20.57186 > 198.51.100.10.80: Flags [S], seq 2259599004, win 64240, options [mss 1460,sackOK,TS val 4198236850 ecr 0,nop,wscale 10], length 0
2 packets captured
2 packets received by filter
0 packets dropped by kernel
root@staff:~# curl -s -o /dev/null -w "%{http_code}\n" -m 3 http://198.51.100.10/; echo "exit code $?"
000
exit code 28- Lines 1–2: Staff to the server VLAN: nothing, because forwarding is off.
- Lines 5–9: Off, then on with the sysctl.d file: now, and at every boot.
- Lines 11–13: Staff reach the server.
- Lines 15–16: So does a guest: with no firewall, a router forwards everything.
- Lines 18–22: At the ISP: SYNs from 10.10.10.20, a private address nobody on the internet can reply to.
- Lines 27–29: So the internet fails: curl's exit code 28 is a timeout.
Check your understanding
Forwarding is on and there's no firewall yet. What can a guest reach?
- Every VLAN, but not the internet, because there's no NAT yet.
- Only the internet.
- Nothing, because the guest VLAN is separate.
- Only its own VLAN.