fix(os_fingerprint): set ip_no_pmtu_disc=1 for windows to eliminate TI=Z

When ip_no_pmtu_disc=0 the Linux kernel sets DF=1 on TCP packets and uses
IP ID=0 (RFC 6864). nmap's TI=Z fingerprint has no Windows match in its DB,
causing 91% confidence guesses of 'Linux 2.4/2.6 embedded' regardless of
TTL being 128. Setting ip_no_pmtu_disc=1 allows non-zero IP ID generation.

Trade-off: DF bit is not set on outgoing packets (slightly wrong for Windows)
but TI=Z is far more damaging to the spoof than losing DF accuracy.
This commit is contained in:
2026-04-10 16:19:32 -04:00
parent 5fdfe67f2f
commit b1f6c3b84a
2 changed files with 5 additions and 3 deletions

View File

@@ -48,7 +48,7 @@ OS_SYSCTLS: dict[str, dict[str, str]] = {
"net.ipv4.tcp_window_scaling": "1", "net.ipv4.tcp_window_scaling": "1",
"net.ipv4.tcp_sack": "1", "net.ipv4.tcp_sack": "1",
"net.ipv4.tcp_ecn": "0", "net.ipv4.tcp_ecn": "0",
"net.ipv4.ip_no_pmtu_disc": "0", "net.ipv4.ip_no_pmtu_disc": "1", # avoid TI=Z: forces non-zero IP IDs
"net.ipv4.tcp_fin_timeout": "30", "net.ipv4.tcp_fin_timeout": "30",
}, },
"bsd": { "bsd": {

View File

@@ -133,8 +133,10 @@ def test_linux_ip_no_pmtu_disc_is_0():
assert get_os_sysctls("linux")["net.ipv4.ip_no_pmtu_disc"] == "0" assert get_os_sysctls("linux")["net.ipv4.ip_no_pmtu_disc"] == "0"
def test_windows_ip_no_pmtu_disc_is_0(): def test_windows_ip_no_pmtu_disc_is_1():
assert get_os_sysctls("windows")["net.ipv4.ip_no_pmtu_disc"] == "0" # Set to 1 (not 0) to avoid TI=Z IP ID signal: when ip_no_pmtu_disc=0 the
# kernel uses IP ID=0 for DF packets, which nmap classifies as Linux embedded.
assert get_os_sysctls("windows")["net.ipv4.ip_no_pmtu_disc"] == "1"
def test_embedded_ip_no_pmtu_disc_is_1(): def test_embedded_ip_no_pmtu_disc_is_1():