A zero-trust segmentation advisor: takes a network inventory (live nmap scan or replayed YAML), classifies every host by role and sensitivity, and produces a least-privilege segmentation plan - zones, an inter-zone firewall ruleset where every rule cites the NIST SP 800-207 / PCI DSS principle it implements, and a before/after attack-path simulation that shows how much lateral movement the plan cuts.
Scanning a network is table stakes; nmap already exists. The point here is the advisory engine on top: explainable, framework-grounded recommendations, plus enforceable config (iptables / pfSense) rather than prose advice.
ws-01 compromised (phished workstation)
before (flat): owns 11 of 13 other hosts - including both databases and the domain controller
after (segmented): owns 3 (its own VLAN) - 0 critical assets reachable on a pivot port
discovery (nmap) ──┐
├──> Inventory (YAML) ──> classifier ──> recommender ──> attack_path ──> reporter
mock_inventory.yaml ┘ hosts/ports/svcs role + zones + rules before/after report.md, diagram,
sensitivity + violations simulation iptables, pfSense
Discovery is the only module that touches the network. Everything downstream runs against a YAML file - meaning the entire advisory engine works offline against a mock inventory, which is also how it's tested.
flowchart TB
subgraph dmz["dmz (10.10.10.0/24)"]
web01["web-01<br/>web-server"]
web02["web-02<br/>web-server"]
end
subgraph app_tier["app-tier (10.10.20.0/24)"]
app01["app-01<br/>app-server"]
end
subgraph data_tier["data-tier (10.10.30.0/24)"]
db01["db-01<br/>database"]
db02["db-02<br/>database"]
end
subgraph user_vlan["user-vlan (10.10.40.0/24)"]
ws["ws-01 … ws-04<br/>workstations"]
end
subgraph iot_vlan["iot-vlan (10.10.50.0/24)"]
printer["printer-01"]
cam["cam-01"]
end
subgraph management["management (10.10.60.0/24)"]
dc["dc-01<br/>domain-controller"]
jump["jump-01<br/>jump-host"]
end
user_vlan -->|80,443| dmz
dmz -->|8080| app_tier
user_vlan -->|8080| app_tier
app_tier -->|3306,5432| data_tier
user_vlan -->|53,88,389,636| management
app_tier -->|53,88,389,636| management
user_vlan -->|631,9100| iot_vlan
management -->|22| dmz
management -->|22| app_tier
management -->|22| data_tier
management -->|3389| user_vlan
Every edge above is an explicit allow rule; everything else is default-deny. Note what's missing: no user-vlan → data-tier edge, and SMB (445) to the domain controllers is deliberately excluded from the client allow set - the classic lateral-movement channel.
git clone https://github.com/MetaMaaz/Network-Segmentation-Advisor
cd Network-Segmentation-Advisor
pip install -r requirements.txt
python cli.py analyze # console summary against the mock network
python cli.py report # full bundle -> output/report writes report.md (inventory, violations, zones, justified ruleset, attack-path comparison), zones.mmd (Mermaid diagram), iptables.rules and pfsense_rules.txt. A committed sample lives in docs/sample-output/.
pip install python-nmap && brew install nmap # or apt install nmap
python cli.py discover --target 192.168.1.0/24 --out inventory.yaml
python cli.py report --inventory inventory.yamlScans save to YAML, so you can replay the same capture through the advisory engine as many times as you want without re-scanning. Only scan networks you own or are explicitly authorised to test.
docker-compose.yml stands up a fake flat network (nginx ×2, MySQL, PostgreSQL, Redis, a Python app) on one bridge subnet. Docker on macOS doesn't route host→container, so a scanner container runs discovery from inside the topology - instructions are at the top of the compose file.
The classifier (advisor/classifier.py) assigns each host a role and sensitivity tier from signatures in data/role_signatures.yaml: port/service heuristics with priorities and negative evidence. SMB + RDP present → workstation, not file server. Adding a new device type means editing the YAML; a unit test covers this by loading a custom SCADA signature.
The recommender (advisor/recommender.py) groups hosts into trust zones - DMZ, app-tier, data-tier, user-vlan, iot-vlan, management, and quarantine for anything unclassified - then derives the minimal allow set from roles actually observed. Ports are never opened speculatively. It also flags violations in the current layout: flat network, databases one hop from workstations, exposed management interfaces, cleartext Telnet, IoT devices mixed with users. Each violation maps to NIST SP 800-207 or PCI DSS.
The attack-path simulator (advisor/attack_path.py) models reachability as a graph and runs breadth-first lateral-movement from a chosen foothold, twice: against the flat network and against the proposed policy. Deliberately conservative - reaching any port counts as exposure; pivoting requires a remote-admin service (SSH/RDP/SMB/RPC/Telnet/WinRM). The report keeps honest caveats: intra-zone movement isn't modelled, and services exposed by design are still attack surface.
The exporters (advisor/exporters/) emit the ruleset as iptables FORWARD-chain commands and pfSense per-interface pass rules, each line annotated with its framework justification.
Rules, not ML. A recommendation you can't explain is one you can't defend - to an interviewer or a change-advisory board. Every output traces to a named signature or a cited framework principle.
Discovery and reasoning are completely separated: the advisory logic never touches the network. That makes it fully unit-testable (30 tests, CI on 3.11/3.12) and means it runs in air-gapped environments against replayed scans.
The generated policy only opens a port if a destination host in that zone actually exposes it - least privilege applied to the ruleset itself, not just the design philosophy.
The attack-path simulation states its assumptions upfront and reports residual risk rather than overclaiming what segmentation solves.
| Output | Principle |
|---|---|
| Default-deny inter-zone baseline | NIST SP 800-207 §3.1.2 (micro-segmentation); PCI DSS v4.0 Req 1.2/1.3 |
| Per-rule justifications | NIST SP 800-207 §2.1 Tenet 3 (least-privilege, per-session access) |
| Quarantine zone for unknown assets | NIST SP 800-207 §2.1 Tenet 4 (no implicit trust from location) |
| Data-tier isolation from user VLAN | PCI DSS v4.0 scoping/segmentation guidance |
| Cleartext-protocol flags | PCI DSS v4.0 Req 2.2.5 (insecure services) |
pip install -r requirements-dev.txt
pytestClassifier, recommender, attack-path and model suites all run against the mock inventory - no network, no Docker, sub-second.
- Host-level micro-segmentation within zones (NIST SP 800-207 §3.1.1)
- UDP service handling and OS-fingerprint-aware classification
- pfSense
config.xmlgeneration for direct import - A second mock topology (already-segmented network) to test violation detection in non-flat layouts
MIT - see LICENSE.