
Network Segmentation Testing with nmap
Segmentation testing is the exercise of proving — from a defined source network — that traffic into a protected network is restricted as intended. Most commonly this is driven by PCI DSS Requirement 11.4.5 (annual segmentation testing for merchants, semi-annual for service providers) and analogous controls in HIPAA, NIST 800-53, and internal zoning standards.
The goal is not to find vulnerabilities. It is to confirm that the firewall/ACL/SDN rules between source and target zones match the documented design — no more, no less. Findings are usually “port X is reachable that shouldn’t be” or “this source IP can reach this CDE host.”
Below is the playbook I lean on with nmap. Run from a representative host inside the source segment.
Phase 1 — Host discovery
You first need to know what’s actually up in the target range without committing to a full port scan. -sn (“no port scan”) performs only discovery probes.
| Switch | Example | What it does |
|---|---|---|
-sn | nmap -sn 10.1.0.0/24 | Disable port scanning. Host discovery only (ICMP echo, TCP SYN/ACK to 443/80, ARP on local). |
-PS | nmap -PS22,80,443 10.1.0.0/24 | TCP SYN ping to listed ports — useful when ICMP is blocked. |
-PA | nmap -PA22,80,443 10.1.0.0/24 | TCP ACK ping — sometimes traverses stateless filters that drop SYN. |
-PU | nmap -PU53,161 10.1.0.0/24 | UDP ping — useful where TCP probes are filtered. |
-Pn | nmap -Pn ... | Skip discovery, treat all hosts as up. Use as a fallback only — it slows things down and produces noise. |
When you run as root, nmap will also use ARP for any targets on the local link, which is the most reliable signal you have.
sudo nmap -sn -PE -PS22,80,443 -PA22,80,443 -PU53,161 -iL targets.txt -oA discovery
-oA <basename> writes normal, grepable, and XML output in one shot — keep all three for reporting.
Phase 2 — Port coverage
Once you have the live set, you need full port coverage. Do not rely on default top-1000 for a segmentation test; partial coverage will not pass a QSA review.
TCP, all 65535 ports, with version detection and reason text (which packet flag drove each verdict — important evidence):
sudo nmap -sS -p- -sV --reason -iL alive.txt -oA tcp_full
If TCP SYN is being blocked outright by the source’s egress (e.g. an outbound proxy that only forwards established sessions), fall back to a TCP connect scan:
nmap -sT -p- -sV --reason -iL alive.txt -oA tcp_connect
UDP is slow and unreliable but required for a complete test. Cover the common service ports at minimum, and use --version-intensity 0 to keep runtime sane:
sudo nmap -sU --top-ports 200 -sV --version-intensity 0 --reason -iL alive.txt -oA udp_top200
Phase 3 — Evidence
What a reviewer (internal or external) will ask for:
- The source IP(s) the scan was run from, with date/time.
- The target scope (
targets.txt) and the alive list. - The raw nmap output for each scan (
-oAartifacts). - A diff between observed open ports and the documented allow-list. Anything reachable that isn’t on the allow-list is a finding.
For diffing, the grepable output (.gnmap) plus a one-liner like:
grep "/open/" tcp_full.gnmap | awk '{print $2}' | sort -u
…gives you a clean “hosts with any open port” list to compare against expectations.
Notes on timing and safety
-T4is usually fine on modern networks and a lot faster than the default-T3. Avoid-T5against production unless you’ve cleared it — it will trip IDS and can knock over fragile devices.- Coordinate with the SOC. A segmentation test that triggers an unannounced incident response is a bad day.
- If the target zone contains IDS/IPS or rate-limiting, your results may be incomplete by design. Document the controls observed; they’re part of the report, not a problem with your methodology.