Chapter 39 — Firewalls, segmentation, zero trust, and VPNs
In one sentence
Perimeter firewalls and network segmentation limit where an attacker can go once inside; zero trust drops the assumption that "inside" is safe; VPNs extend an authenticated encrypted boundary across untrusted networks.
Firewalls — what each type actually does
PACKET FILTER (stateless) allow/deny by IP, port, protocol, flags.
Fast, dumb, no memory of connections.
STATEFUL FIREWALL tracks connection state (NEW/ESTABLISHED/
RELATED). "Allow replies to connections I
let out." The default model: nftables,
pf, iptables, AWS security groups (SGs are
stateful; NACLs are stateless).
APPLICATION / NEXT-GEN (NGFW) parses L7: HTTP, TLS SNI, app-ID; can do
IPS, URL filtering, user-ID. A WAF (Part 10)
is the web-specific cousin.
HOST firewall on the endpoint itself (nftables/ufw,
Windows Defender FW). Defence in depth --
survives a breached perimeter.
Default-deny is the only sane posture: deny everything inbound, allow the specific ports you serve; deny outbound by default too on sensitive segments (egress filtering catches exfiltration and C2 callbacks).
Minimal server ruleset (concept):
inbound: allow tcp 443 from anywhere
allow tcp 22 from bastion_subnet only
allow established/related
deny all (log)
outbound: allow tcp 443 to package-mirrors, monitoring, APIs you call
allow udp 53 to your resolvers
deny all (log) <- an alert here often means "we're breached"
Segmentation — blast-radius control
FLAT NETWORK: one compromised web server can reach the database, the
domain controller, the backup server, every workstation. Ransomware
loves a flat network.
SEGMENTED:
+------------+ +-------------+ +-----------+ +-----------+
| DMZ | | app tier | | data tier | | mgmt/ |
| web/proxy |-->| services |-->| DB, cache | | bastion |
+------------+ +-------------+ +-----------+ +-----------+
only :443 only from DMZ only from only from
from internet on service ports app tier on admin VPN,
5432 to all tiers
Each boundary = a firewall/SG rule. East-west traffic is filtered, not
just north-south. MICROSEGMENTATION takes this to per-workload identity
(service mesh, host firewalls driven by labels, Illumio-style).
Zero trust
OLD MODEL ("castle and moat"): authenticate at the perimeter; once
inside the VPN/LAN you're trusted. One breach -> lateral movement
everywhere.
ZERO TRUST (NIST SP 800-207): "never trust, always verify."
* No implicit trust from network location. The office LAN is treated
like the internet.
* Every request to every resource is authenticated (strong user
identity + device posture) and authorised (least privilege,
policy-based), per-session, and logged.
* Access is brokered by a policy enforcement point in front of each
app -- not a flat network tunnel.
* mTLS / SPIFFE identities between services (Part 7).
In practice: identity-aware proxies (BeyondCorp, Cloudflare Access,
Tailscale, Teleport), device attestation, short-lived credentials
(Part 8 certs), and per-app authorisation instead of "on the VPN = in".
Zero trust doesn't abolish firewalls and segmentation — it adds identity as the primary control so a network foothold alone buys the attacker very little.
VPNs — what they are actually for
A VPN gives you an AUTHENTICATED, ENCRYPTED tunnel over an untrusted
network, and makes remote devices appear on (a slice of) a trusted one.
LEGITIMATE USES:
* remote workers reaching internal services
* site-to-site links between offices/clouds
* protecting traffic on hostile Wi-Fi (though TLS already covers most)
* hiding your source IP / location from destination sites (commercial
"privacy" VPNs -- you're trusting the VPN provider instead of the ISP)
WHAT A VPN IS NOT:
* not anonymity (the provider sees everything; so can they log it)
* not a substitute for endpoint security or app authz
* not "zero trust" -- a classic full-tunnel VPN is the castle-and-moat
model; compromise a VPN-connected laptop and you're on the LAN
The VPN protocols
| Protocol | Crypto | Notes |
|---|---|---|
| WireGuard | Curve25519, ChaCha20-Poly1305, BLAKE2s, fixed suite | ~4k lines, in-kernel, fast, hard to misconfigure. Default choice. Roaming-friendly. No crypto agility (by design). |
| IPsec (IKEv2) | negotiable (AES-GCM, etc.) | The standards-based incumbent; strong when configured well; complex; great vendor support; MOBIKE for roaming. |
| OpenVPN | TLS-based (OpenSSL), any TLS suite | Mature, flexible, runs over TCP/UDP 443 (NAT/firewall friendly); slower than WireGuard; userspace. |
| TLS-based commercial (e.g. AnyConnect/OpenConnect) | TLS/DTLS | Enterprise remote-access; captive-portal friendly. |
| PPTP, L2TP-only, IKEv1 | broken / legacy | Do not use. PPTP's MS-CHAPv2 is crackable. |
WireGuard mental model:
- each peer has a static Curve25519 keypair (like SSH keys)
- you list peers by public key + allowed source IPs (a crypto-keyed
routing table)
- handshake every ~2 min (Noise protocol), forward secret
- "AllowedIPs" is BOTH the routing rule AND the ACL -- get it right
- add a PresharedKey per peer for a post-quantum hedge today
- it's silent: no response to unauthenticated packets (stealthy,
but you add your own liveness monitoring)
Practice (40 min)
# 1. Read your current firewall state
sudo nft list ruleset 2>/dev/null || sudo iptables -S # Linux
# macOS: sudo pfctl -sr ; sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
# Identify: is it default-deny inbound? what's allowed? any egress rules?
# 2. Build a minimal default-deny ruleset in a throwaway VM/container (nft)
sudo nft -f - <<'EOF'
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
tcp dport 22 ip saddr 10.0.0.0/24 accept
tcp dport 443 accept
ct state invalid drop
counter comment "dropped"
}
chain output { type filter hook output priority 0; policy accept; }
}
EOF
sudo nft list ruleset
# 3. Test segmentation logic with nmap (against hosts you own / your lab)
nmap -sS -p 22,80,443,5432 10.0.20.0/24 # what's reachable from here?
# run the same scan from different segments and compare -- that's your
# segmentation, verified.
# 4. Stand up WireGuard between two machines/VMs you control
umask 077
wg genkey | tee a.key | wg pubkey > a.pub
wg genkey | tee b.key | wg pubkey > b.pub
# peer A:
sudo ip link add wg0 type wireguard
sudo ip addr add 10.9.0.1/24 dev wg0
sudo wg set wg0 private-key ./a.key listen-port 51820 \
peer "$(cat b.pub)" allowed-ips 10.9.0.2/32 endpoint <B_IP>:51820
sudo ip link set wg0 up
# peer B mirrors it with 10.9.0.2/24 and peer=A. Then:
ping 10.9.0.2
sudo wg show # handshake time, transfer, endpoint
# 5. Confirm the tunnel is encrypted + authenticated
sudo tcpdump -i <wan_iface> -n udp port 51820 -c 10 # opaque UDP, no plaintext
# send an unauthenticated packet -> no reply (WireGuard is silent).
# 6. Egress-filtering demo: block outbound 443 except to one host, then
# watch a "curl https://example.com" fail and your rule counter tick.
Mini-project (60 min): segment SecureShop
Model SecureShop (Ch 4) as 4 segments in Docker networks or VMs:
edge (nginx :443) | app (orders-api :8080) | data (postgres :5432)
| mgmt (bastion :22)
1. Write firewall rules so:
- internet -> edge:443 only
- edge -> app:8080 only
- app -> data:5432 only
- mgmt -> everything on :22 only; nothing -> mgmt except admin VPN
- default deny inbound AND outbound on data (allow only 5432 from app
+ DNS + package mirror)
2. From a shell in each segment, run nmap at the others. Produce a
reachability matrix and confirm it matches the intended design.
3. "Compromise" the edge container (you have a shell). Show you can reach
app:8080 but NOT data:5432 directly, and not mgmt at all.
4. Add host firewalls on app and data as defence in depth; re-test.
5. Bonus: put app<->data on mTLS (Part 7) so even reachable != usable.
6. Write ~/sec-lab/reports/part9-network.md with the matrix and findings.
Common confusions
- "The firewall makes us secure." It controls reachability. It does nothing about a vulnerable app on an allowed port, or a phished credential. Defence in depth.
- "We have a VPN, so we're zero trust." Opposite — a full-tunnel VPN is the castle-and-moat model. Zero trust authorises every request per-app regardless of network position.
- "Egress filtering is paranoid." Outbound rules are how you catch and slow data exfiltration and malware C2. On sensitive segments they're essential.
- "WireGuard has no crypto agility — that's bad." It's a deliberate simplification that removes negotiation-downgrade bugs; you rev the whole protocol version instead. Add a PresharedKey for PQ hedging.
- "Internal = trusted." Flat internal networks are why one phished laptop becomes company-wide ransomware. Segment.
Check yourself
- Stateful vs stateless firewall — what does "stateful" buy you?
- What is the security value of network segmentation, in one phrase?
- State the zero-trust principle and how it differs from castle-and-moat.
- What is a VPN good for, and name two things it is not.
- Why is WireGuard's lack of cipher negotiation considered a feature?
- What does
AllowedIPsdo in WireGuard (two roles)?
Further reading
- Standard: NIST SP 800-207, Zero Trust Architecture — readable, the canonical reference. Plus Google's BeyondCorp papers.
- Book: Zero Trust Networks (2nd ed.), Gilman & Barth.
- Docs: WireGuard whitepaper (
wireguard.com/papers/wireguard.pdf) — short and excellent;nftableswiki;strongSwanIKEv2 docs. - Guidance: CISA Zero Trust Maturity Model; PCI-DSS segmentation guidance (even if you're not doing payments, it's a good checklist).
- Article: "How WireGuard works" (Tailscale blog) and Julia Evans's firewall zines.