Lab 02 — Segmentation & Egress-Filtering Analyzer

Lens: A firewall ruleset is a policy over a graph of zones. WARMUP: Chapter 8 (segmentation), Chapter 9 (egress filtering & allow-listing), Chapter 10 (the telemetry that catches what gets through). ATT&CK: Command and Control — Application-Layer Protocol (T1071), Non-Standard Port (T1571), Protocol Tunneling (T1572); Exfiltration Over C2 Channel (T1041).

The problem

Lab 01 found the lateral path. This lab decides whether the segmentation policy stops it — and audits the ruleset for the holes that let a beacon out. Two roles ask the same questions of one ruleset:

  • The firewall decides every flow: deny-by-default, first-match-wins.
  • The auditor (red or blue) asks: which rules are too broad? Does this policy block that lateral path? What egress allow-list should replace the sloppy internet rules?

The dangerous rules are predictable: an any-any allow, and broad egress to the internet on a non-standard port — the classic command-and-control / exfiltration channel. An egress allow-list that pins outbound traffic to the standard ports through a proxy is the control that closes it.

What you build (lab.py)

A Rule(src_zone, dst_zone, port, proto, action) is one firewall line (port is an int or "any"). A Flow(src_zone, dst_zone, port, proto) is a packet's worth of metadata.

  • flow_permitted(flow, rules)deny-by-default, first-match-wins evaluation.
  • over_permissive(rules) — flag any-any allows, broad-egress (internet on a non-standard/wildcard port — possible C2), and wildcard-port allows; returns {index, rule, reason} findings.
  • blocks_path(path, rules) — does the ruleset block a lateral path? A path is blocked iff any one hop is denied — one closed door stops the chain. (first_blocked_hop says where.)
  • egress_findings(rules) — egress-allow-list recommendations: for each over-permissive internet rule, a tightened replacement and the reason.

Attack cases the tests cover

  • Deny-by-default: a flow that matches no rule is denied; an empty ruleset denies everything.
  • First-match-wins: an explicit vpn->server:1521 deny beats a later allow.
  • Audit: any-any is flagged; user->internet:4444 and dmz->internet:any are flagged as broad-egress; legitimate server->internet:443 and specific user->server:445 are not.
  • Path composition: the segmented policy permits the designed vpn->dmz->server path (Lab 01's pivot) but blocks the direct vpn->server:1521 shortcut; removing the dmz->server allow breaks the designed path at hop index 1.
  • Clean rulesets produce no findings; all output is deterministic.

Run

pip install -r requirements.txt
cd <this dir>
LAB_MODULE=solution pytest -q   # reference passes (20 tests)
pytest -q                        # your implementation after the TODOs
# fallback interpreter:
# LAB_MODULE=solution /Users/s0x/src/10xdev/ai-enigneer/.venv/bin/python -m pytest -q

Hardening / detection

This lab is the hardening tool — it turns an attack path into the segmentation and egress controls that close it, and the audit findings into a remediation list:

  • Segment: feed Lab 01's choke point in as a deny rule; blocks_path proves the lateral path now breaks (and regression-tests that the designed traffic still flows).
  • Egress allow-list: egress_findings recommends pinning outbound traffic to tcp/443,tcp/80, udp/53 through the proxy and denying/logging the rest — which is exactly where a beacon on tcp/4444 or DNS-tunneled C2 gets caught (WARMUP Ch. 9–10).
  • The detection pairing: every broad-egress finding is a Zeek/Suricata + proxy-log alert — long connections to a rare destination on an odd port, or high-entropy DNS — see WARMUP Ch. 10 and the HITCHHIKER'S GUIDE.

Extensions

  • Add CIDR/IP matching with ipaddress instead of opaque zone labels.
  • Score each finding by blast radius (how many lateral paths the over-permissive rule enables).
  • Emit findings as Sigma-style detection logic for the proxy/Zeek log.
  • Parse a real (sanitized, owned) firewall export — iptables/nftables, AWS security groups, or a pfSense rule dump — into Rule tuples.
  • Multi-language build spec: reimplement flow_permitted as a Go or Rust library that ingests an nftables ruleset and answers reachability queries for a CI segmentation test.

Interview / resume

"Built a segmentation & egress analyzer that evaluates flows against a firewall ruleset (deny-by-default, first-match-wins), flags over-permissive rules — any-any and broad internet egress on non-standard ports as likely C2 channels — proves whether a segmentation policy blocks a given lateral path, and emits egress-allow-list recommendations, pairing each finding with its proxy/Zeek detection."

Limitations: zone/port model (no full CIDR/IP matching — ports are ints or the literal "any", zones are opaque labels); first-match-wins with an implicit final deny; C2-egress heuristics use a fixed standard-port allow-list and internet-zone label set; synthetic rules and flows only — no live firewall is touched.