Three zones · one firewall · defense-in-depth, by design.
Verified live build · 2026-05-05 · ML350p Gen8 · Proxmox VE 8.2.2
ping 1.1.1.1 fail from LAN but curl works?The school's classroom network. Provides DHCP for our pfSense WAN, hands us internet, and gives us the management path to https://10.10.10.10:8006.
| Device | IP |
|---|---|
| School gateway | 10.10.10.1 |
| Proxmox host (mgmt) | 10.10.10.10 |
| pfSense WAN | 10.10.110.10 |
Both 10.10.10.10 and 10.10.110.10 live in the same /16, so they can talk directly.
Three NICs spanning all three subnets. Every internal packet goes through here.
.100–.200 on each internal subnet1.1.1.1If pfSense2 goes down, nothing on the internal subnets can reach the internet, get an IP, or look up a name.
School LAN / mgmt
10.10.0.0/16
Bridges eno1 physical NIC. Where we manage Proxmox from.
DMZ — Demilitarized Zone
172.16.0.0/24
No physical port. Hosts the jumpbox. Cannot reach LAN by default.
LAN — Internal
192.168.0.0/24
No physical port. Hosts the WinSrv and LinuxServer. Hardened.
Each bridge is a virtual switch inside Proxmox — VMs plug their virtual NICs into a bridge and can talk to other VMs on the same bridge.
10.10.10.10
tctmachine · Proxmox VE 8.2.2
vmbr0 so the school network can reach it directly.110.10) — that's how outbound traffic exits the labhttps://10.10.10.10:8006172.16.0.100
Ubuntu Server 26.04 LTS
10.10.10/24, 172.16.0/24, 192.168.0/24)Real-world parallel: bastion / jump host pattern in cloud architectures (AWS, Azure, GCP all do this).
192.168.0.15
Windows Server 2025 Eval · 24H2
Future: AD · DNS · DHCP · IIS
192.168.0.20
Ubuntu Server 26.04 LTS
Future: NGINX · MariaDB · NTP
192.168.0.25
Ubuntu 24.04 Desktop · GUI
Role: Client tester · Firefox
All three static IPs (.15 · .20 · .25) — outside pfSense's DHCP pool (.100–.200) — so leases never clash. Dashed card = install pending.
9 rules on vmbr2's firewall — order matters (top down, first match wins). This is what separates "default allow LAN to any" from real production posture.
| # | Action | Source → Dest | Description |
|---|---|---|---|
| 1 | PASS | LAN → pfSense (ICMP echoreq) | Ping the gateway only |
| 2 | PASS | LAN → pfSense (UDP/123) | NTP to local server |
| 3 | PASS | LAN → pfSense (UDP/53) | DNS to local resolver |
| 4 | BLOCK | LAN → pfSense (any other) | No web GUI / SSH access from LAN VMs |
| 5 | BLOCK | LAN → DMZ_NET | No lateral move into DMZ |
| 6 | BLOCK | LAN → RFC1918 | No reach to other private subnets |
| 7 | PASS | LAN → OUTBOUND_WEB alias (TCP/UDP) | Internet-bound · ports 80, 443, 53, 123 only |
| 8 | PASS | LAN → port 5985–5986 | WinRM / Windows Update |
| 9 | PASS | LAN → port 445 | SMB |
Default-deny catches everything else. ping 1.1.1.1 from LAN fails — by design, ICMP only allowed to gateway. Anti-fingerprinting + anti-data-exfiltration posture.
curl https://www.google.comwww.google.com. First, DNS lookup: queries 192.168.0.1 (its DNS server, which is pfSense Unbound).
142.251.x.x.
142.251.x.x:443. Default route via 192.168.0.1 → packet arrives at pfSense LAN interface.
192.168.0.20 to pfSense's WAN IP 10.10.110.10, picks a random source port, records the translation in the state table.
vmbr0 through eno1, hits the school LAN, goes to the school gateway 10.10.10.1, and out to the internet.
10.10.110.10, pfSense looks up the state, rewrites destination back to 192.168.0.20, returns it to LinuxServer. TLS handshake completes, HTML returned, browser/curl is happy.
.15 · LinuxServer at static .20.25 · Firefox-based client testingCritical: change pfSense admin password before next class.
Three zones · one firewall · 5 VMs · 9 hardened rules — all built, all verified, all documented.
Full verification doc: week2-verification.html · Service install playbook: week2.html