From b1f6c3b84a38c03229ffc115cb92ed66effe14c0 Mon Sep 17 00:00:00 2001 From: anti Date: Fri, 10 Apr 2026 16:19:32 -0400 Subject: [PATCH] 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. --- decnet/os_fingerprint.py | 2 +- tests/test_os_fingerprint.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/decnet/os_fingerprint.py b/decnet/os_fingerprint.py index aa17b86..25cc129 100644 --- a/decnet/os_fingerprint.py +++ b/decnet/os_fingerprint.py @@ -48,7 +48,7 @@ OS_SYSCTLS: dict[str, dict[str, str]] = { "net.ipv4.tcp_window_scaling": "1", "net.ipv4.tcp_sack": "1", "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", }, "bsd": { diff --git a/tests/test_os_fingerprint.py b/tests/test_os_fingerprint.py index 970655b..ffa7afb 100644 --- a/tests/test_os_fingerprint.py +++ b/tests/test_os_fingerprint.py @@ -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" -def test_windows_ip_no_pmtu_disc_is_0(): - assert get_os_sysctls("windows")["net.ipv4.ip_no_pmtu_disc"] == "0" +def test_windows_ip_no_pmtu_disc_is_1(): + # 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():