Repository navigation
Port Scan Detection Coverage
Back to Port Scan Detection.
Generated by daemon/portscan/testdata/coverage. Do not edit by hand:
the table below is produced by replaying the capture corpus through the
detection engine, so it says what the code does rather than what it is
meant to do.
| Code | Meaning |
|---|---|
D_FULL |
Reliably visible to this sensor. |
D_PARTIAL |
Visible, with a documented blind spot. |
D_INDIRECT |
The scan itself is not visible; only a side effect is. |
U_UNREACHABLE |
Structurally invisible from the target host. The reason is stated. |
U_OUT_OF_SCOPE |
Detectable in principle, deliberately not covered. The reason is stated. |
Scan is whether the activity can be seen. Attribution is whether the
address in the packets can be believed to be its origin's. The two differ
for every indirection technique, and that difference is why blocking is
gated by policy rather than automatic.
| Technique | Option | Scan | Attribution | Exercised by | Observed |
|---|---|---|---|---|---|
| TCP SYN scan | -sS |
D_FULL |
D_FULL |
tcp-syn.pcap |
tcp-syn, 9 ports, score 108 |
| TCP connect scan | -sT |
D_FULL |
D_FULL |
tcp-connect.pcap |
tcp-syn, 9 ports, score 108 |
| TCP FIN scan | -sF |
D_FULL |
D_FULL |
tcp-fin.pcap |
tcp-fin, 7 ports, score 112 |
| TCP NULL scan | -sN |
D_FULL |
D_FULL |
tcp-null.pcap |
tcp-null, 7 ports, score 112 |
| TCP Xmas scan | -sX |
D_FULL |
D_FULL |
tcp-xmas.pcap |
tcp-xmas, 7 ports, score 112 |
| TCP Maimon scan | -sM |
D_PARTIAL |
D_FULL |
tcp-maimon.pcap |
tcp-maimon, 25 ports, score 100 |
| TCP ACK scan | -sA |
D_PARTIAL |
D_FULL |
tcp-ack.pcap |
tcp-ack, 25 ports, score 100 |
| TCP window scan | -sW |
U_UNREACHABLE |
D_FULL |
tcp-window.pcap |
tcp-ack, 25 ports, score 100 |
| Custom flag combinations | --scanflags |
D_FULL |
D_FULL |
tcp-custom-flags.pcap |
tcp-custom-flags, 7 ports, score 112 |
| SYN|FIN scan | --scanflags SYNFIN |
D_FULL |
D_FULL |
tcp-synfin.pcap |
tcp-syn-fin, 7 ports, score 112 |
| UDP scan | -sU |
D_PARTIAL |
U_UNREACHABLE |
udp.pcap |
udp, 25 ports, score 100 |
| IP protocol scan | -sO |
D_FULL |
D_FULL |
ip-protocol.pcap |
protocol scan, 260 probes |
| Decoy scan | -D |
D_FULL |
U_UNREACHABLE |
tcp-syn-decoy.pcap |
tcp-syn, 9 ports, score 108 |
| OS fingerprinting | -O |
D_FULL |
D_FULL |
tcp-os-fingerprint.pcap |
tcp-syn, 9 ports, score 108 |
| Fragmented probes | -f / --mtu |
D_PARTIAL |
D_FULL |
tcp-syn-fragmented.pcap |
tcp-fragmented, 9 ports, score 108 |
| Slow scan | -T0 / -T1 |
D_PARTIAL |
D_FULL |
tcp-syn-slow.pcap |
tcp-syn, 10 ports, score 107 |
| Idle (zombie) scan | -sI |
D_FULL |
U_UNREACHABLE |
- | not exercised here |
| FTP bounce scan | -b |
D_FULL |
U_UNREACHABLE |
- | not exercised here |
| Spoofed source | -S |
D_FULL |
U_UNREACHABLE |
- | not exercised here |
| SCTP INIT / COOKIE ECHO scan | -sY / -sZ |
U_OUT_OF_SCOPE |
D_FULL |
- | not exercised here |
| Horizontal scan of the network | - |
U_UNREACHABLE |
U_UNREACHABLE |
- | not exercised here |
| Single-port brute force | - |
U_OUT_OF_SCOPE |
D_FULL |
benign-single-port.pcap |
not reported (2 probes) |
| IPv6 port scan | -6 |
D_FULL |
D_FULL |
tcp-syn-v6.pcap |
tcp-syn, 9 ports, score 108 |
| IPv6 FIN scan | -6 -sF |
D_FULL |
D_FULL |
tcp-fin-v6.pcap |
tcp-fin, 7 ports, score 112 |
| IPv6 Xmas scan | -6 -sX |
D_FULL |
D_FULL |
tcp-xmas-v6.pcap |
tcp-xmas, 7 ports, score 112 |
| IPv6 UDP scan | -6 -sU |
D_PARTIAL |
U_UNREACHABLE |
udp-v6.pcap |
udp, 25 ports, score 100 |
| Extension-header evasion | Topera |
D_FULL |
D_FULL |
- | not exercised here |
| Out-of-band enumeration | DNS / rDNS / certificate logs |
U_UNREACHABLE |
U_UNREACHABLE |
- | not exercised here |
TCP SYN scan (-sS): scan D_FULL, attribution D_FULL.
a bare SYN to a port where nothing listens is the nominal case.
TCP connect scan (-sT): scan D_FULL, attribution D_FULL.
connect(2) puts the same bare SYN on the wire; the difference is in the scanner, not in the packets.
TCP FIN scan (-sF): scan D_FULL, attribution D_FULL.
a FIN outside an established connection cannot be legitimate.
TCP NULL scan (-sN): scan D_FULL, attribution D_FULL.
no control bits at all is not something a stack emits.
TCP Xmas scan (-sX): scan D_FULL, attribution D_FULL.
FIN, PSH and URG together cannot open or continue a connection.
TCP Maimon scan (-sM): scan D_PARTIAL, attribution D_FULL.
FIN|ACK carries ACK, the shape of a connection's teardown, so it is treated as an ACK scan is: counted at the lowest weight, not counted in the ephemeral range, and not enough on its own to block.
TCP ACK scan (-sA): scan D_PARTIAL, attribution D_FULL.
a lone ACK is also what a straggler from a just-closed socket looks like, so it is counted at the lowest weight; the connection table removes most of the ambiguity, which a network sensor cannot do at all.
TCP window scan (-sW): scan U_UNREACHABLE, attribution D_FULL.
byte-identical to -sA on the wire: the two differ only in how the scanner reads the window field of the reply. Reporting anything more specific would be a fabrication, so it is reported as an ACK scan.
Custom flag combinations (--scanflags): scan D_FULL, attribution D_FULL.
anything that is not a legitimate combination is caught as 'not matched above' rather than by a list of known ones, so a novel combination is still caught.
SYN|FIN scan (--scanflags SYNFIN): scan D_FULL, attribution D_FULL.
a classic filter-evasion combination, named explicitly.
UDP scan (-sU): scan D_PARTIAL, attribution U_UNREACHABLE.
legitimate multi-port UDP traffic is common (mDNS, SSDP, games, P2P) so the weight is low; and a UDP source address costs nothing to forge, so RequireTCPEvidence refuses to block on UDP-only evidence.
IP protocol scan (-sO): scan D_FULL, attribution D_FULL.
counting distinct IP protocol numbers is cheap and unambiguous; the method is legitimately mixed because -sO also emits real TCP and UDP headers.
Decoy scan (-D): scan D_FULL, attribution U_UNREACHABLE.
the scan is fully visible but the forged sources are indistinguishable from the real one. This is the reason the default block policy asks rather than acts.
OS fingerprinting (-O): scan D_FULL, attribution D_FULL.
mixes a port scan with fingerprinting probes, so several probe families arrive from one source.
Fragmented probes (-f / --mtu): scan D_PARTIAL, attribution D_FULL.
the first fragment ends after the eighth byte of the TCP header, so the ports are readable and the flags are not. The scan is detected; the technique behind it is reported as indeterminate rather than guessed, because an unread flag octet reads as zero and would otherwise be reported as a NULL scan.
Slow scan (-T0 / -T1): scan D_PARTIAL, attribution D_FULL.
a leaky bucket detects a scan whose probes arrive faster than it leaks, but how fast is not the whole answer: as the interval approaches the point where gain equals leak, the time to reach the threshold diverges. Config.SlowestDetectableScan reports the slowest scan the running configuration reports WITHIN AN HOUR, which is the figure worth quoting; slower scans are either invisible or detected long after the scanner has gone.
Idle (zombie) scan (-sI): scan D_FULL, attribution U_UNREACHABLE.
every probe reaches us from the zombie, so the scan is plainly visible; the attacker never sends us a packet, so their address is not in anything we can observe.
FTP bounce scan (-b): scan D_FULL, attribution U_UNREACHABLE.
the connections arrive from the FTP server. Largely obsolete, but the attribution limit is the same as the idle scan's.
Spoofed source (-S): scan D_FULL, attribution U_UNREACHABLE.
the source address is chosen by the sender; nothing in the packets contradicts it.
SCTP INIT / COOKIE ECHO scan (-sY / -sZ): scan U_OUT_OF_SCOPE, attribution D_FULL.
IP protocol 132 is counted towards the protocol-scan total, but SCTP chunk parsing is not implemented: it would add a third transport parser to the kernel program for a technique that is vanishingly rare on desktops.
Horizontal scan of the network: scan U_UNREACHABLE, attribution U_UNREACHABLE.
a sweep of one port across many hosts is, from any single host, one packet. There is nothing to count. This is a property of the vantage point, not a gap in the implementation.
Single-port brute force: scan U_OUT_OF_SCOPE, attribution D_FULL.
repeated attempts on one port are a credential attack or an application failing to reach a stopped service, not reconnaissance. Counting them is the mistake PortSentry and flowhawk make.
IPv6 port scan (-6): scan D_FULL, attribution D_FULL.
identical to the IPv4 techniques once the target address is known; address-space size protects the network, not the host.
IPv6 FIN scan (-6 -sF): scan D_FULL, attribution D_FULL.
the flag analysis is address-family independent.
IPv6 Xmas scan (-6 -sX): scan D_FULL, attribution D_FULL.
the flag analysis is address-family independent.
IPv6 UDP scan (-6 -sU): scan D_PARTIAL, attribution U_UNREACHABLE.
same weighting and same refusal to block on UDP-only evidence as IPv4.
Extension-header evasion (Topera): scan D_FULL, attribution D_FULL.
hiding the TCP header behind more IPv6 extension headers than the parser walks (eight, and 1024 bytes) is itself the signature: the host answers such a probe, ordinary traffic never sends one, so each packet that exhausts the walk scores like a SYN to a system port and the scan is reported as ipv6-extension-evasion. The ports themselves are not readable, and the probes are not evidence for blocking.
Out-of-band enumeration (DNS / rDNS / certificate logs): scan U_UNREACHABLE, attribution U_UNREACHABLE.
no packet reaches the host at all. Detecting it is not a network-sensor problem.
These are derived from the configuration, not asserted: the slowest scan a leaky bucket can detect is a function of its threshold, its decay rate and the weight of one probe. As a scan slows towards the rate at which the bucket leaks, the time it takes to be reported grows without bound, so each figure below is the slowest scan reported within an hour of its first probe.
Score threshold 100, decay one point per 10s.
| Probe | Weight | Slowest detectable interval |
|---|---|---|
| SYN to a closed system port (< 1024) | 12 | 1m36s |
| SYN to a closed registered port | 6 | 47s |
| SYN to a closed dynamic port | 3 | 23s |
| anomalous flags, system port | 16 | 2m9s |
| UDP to a closed dynamic port | 1 | 7s |
For reference, nmap -T1 waits 15s between probes and nmap -T0 waits
5 minutes. A scan slower than the figures above is reported late or not at
all. A lower threshold or a slower decay moves the figures, at the price of
reporting ordinary traffic; no setting makes a leaky bucket see a scan that
is slower than its leak.