feat(os_fingerprint): Phase 2 — add icmp_ratelimit + icmp_ratemask sysctls
Windows: both 0 (no ICMP rate limiting — matches real Windows behavior) Linux: 1000ms / mask 6168 (kernel defaults) BSD: 250ms / mask 6168 (FreeBSD default is faster than Linux) Embedded/Cisco: both 0 (most firmware doesn't rate-limit ICMP) These affect nmap's IE and U1 probe groups which measure ICMP error response timing to closed UDP ports. Windows responds to all probes instantly while Linux throttles to ~1/sec. Tests: 10 new cases (5 per sysctl). Suite: 822 passed.
This commit is contained in:
@@ -23,9 +23,13 @@ Secondary discriminators (nmap OPS / WIN / ECN / T2–T6 probe groups):
|
|||||||
net.ipv4.ip_no_pmtu_disc – DF bit in ICMP replies (IE probes); embedded on
|
net.ipv4.ip_no_pmtu_disc – DF bit in ICMP replies (IE probes); embedded on
|
||||||
net.ipv4.tcp_fin_timeout – FIN_WAIT_2 seconds (T2–T6 timing); Windows shorter
|
net.ipv4.tcp_fin_timeout – FIN_WAIT_2 seconds (T2–T6 timing); Windows shorter
|
||||||
|
|
||||||
|
ICMP tuning (nmap IE / U1 probe groups):
|
||||||
|
net.ipv4.icmp_ratelimit – Min ms between ICMP error replies; Windows = 0 (none)
|
||||||
|
net.ipv4.icmp_ratemask – Bitmask of ICMP types subject to rate limiting
|
||||||
|
|
||||||
Note: net.core.rmem_default is a global (non-namespaced) sysctl and cannot be
|
Note: net.core.rmem_default is a global (non-namespaced) sysctl and cannot be
|
||||||
set per-container without --privileged; TCP window size mangling is deferred to
|
set per-container without --privileged; TCP window size is already correct for
|
||||||
Phase 2 (iptables entrypoint).
|
Windows (64240) from the kernel's default tcp_rmem settings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -40,6 +44,8 @@ OS_SYSCTLS: dict[str, dict[str, str]] = {
|
|||||||
"net.ipv4.tcp_ecn": "2",
|
"net.ipv4.tcp_ecn": "2",
|
||||||
"net.ipv4.ip_no_pmtu_disc": "0",
|
"net.ipv4.ip_no_pmtu_disc": "0",
|
||||||
"net.ipv4.tcp_fin_timeout": "60",
|
"net.ipv4.tcp_fin_timeout": "60",
|
||||||
|
"net.ipv4.icmp_ratelimit": "1000",
|
||||||
|
"net.ipv4.icmp_ratemask": "6168",
|
||||||
},
|
},
|
||||||
"windows": {
|
"windows": {
|
||||||
"net.ipv4.ip_default_ttl": "128",
|
"net.ipv4.ip_default_ttl": "128",
|
||||||
@@ -50,6 +56,8 @@ OS_SYSCTLS: dict[str, dict[str, str]] = {
|
|||||||
"net.ipv4.tcp_ecn": "0",
|
"net.ipv4.tcp_ecn": "0",
|
||||||
"net.ipv4.ip_no_pmtu_disc": "0",
|
"net.ipv4.ip_no_pmtu_disc": "0",
|
||||||
"net.ipv4.tcp_fin_timeout": "30",
|
"net.ipv4.tcp_fin_timeout": "30",
|
||||||
|
"net.ipv4.icmp_ratelimit": "0",
|
||||||
|
"net.ipv4.icmp_ratemask": "0",
|
||||||
},
|
},
|
||||||
"bsd": {
|
"bsd": {
|
||||||
"net.ipv4.ip_default_ttl": "64",
|
"net.ipv4.ip_default_ttl": "64",
|
||||||
@@ -60,6 +68,8 @@ OS_SYSCTLS: dict[str, dict[str, str]] = {
|
|||||||
"net.ipv4.tcp_ecn": "0",
|
"net.ipv4.tcp_ecn": "0",
|
||||||
"net.ipv4.ip_no_pmtu_disc": "0",
|
"net.ipv4.ip_no_pmtu_disc": "0",
|
||||||
"net.ipv4.tcp_fin_timeout": "60",
|
"net.ipv4.tcp_fin_timeout": "60",
|
||||||
|
"net.ipv4.icmp_ratelimit": "250",
|
||||||
|
"net.ipv4.icmp_ratemask": "6168",
|
||||||
},
|
},
|
||||||
"embedded": {
|
"embedded": {
|
||||||
"net.ipv4.ip_default_ttl": "255",
|
"net.ipv4.ip_default_ttl": "255",
|
||||||
@@ -70,6 +80,8 @@ OS_SYSCTLS: dict[str, dict[str, str]] = {
|
|||||||
"net.ipv4.tcp_ecn": "0",
|
"net.ipv4.tcp_ecn": "0",
|
||||||
"net.ipv4.ip_no_pmtu_disc": "1",
|
"net.ipv4.ip_no_pmtu_disc": "1",
|
||||||
"net.ipv4.tcp_fin_timeout": "15",
|
"net.ipv4.tcp_fin_timeout": "15",
|
||||||
|
"net.ipv4.icmp_ratelimit": "0",
|
||||||
|
"net.ipv4.icmp_ratemask": "0",
|
||||||
},
|
},
|
||||||
"cisco": {
|
"cisco": {
|
||||||
"net.ipv4.ip_default_ttl": "255",
|
"net.ipv4.ip_default_ttl": "255",
|
||||||
@@ -80,6 +92,8 @@ OS_SYSCTLS: dict[str, dict[str, str]] = {
|
|||||||
"net.ipv4.tcp_ecn": "0",
|
"net.ipv4.tcp_ecn": "0",
|
||||||
"net.ipv4.ip_no_pmtu_disc": "1",
|
"net.ipv4.ip_no_pmtu_disc": "1",
|
||||||
"net.ipv4.tcp_fin_timeout": "15",
|
"net.ipv4.tcp_fin_timeout": "15",
|
||||||
|
"net.ipv4.icmp_ratelimit": "0",
|
||||||
|
"net.ipv4.icmp_ratemask": "0",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,6 +164,53 @@ def test_embedded_tcp_fin_timeout_is_15():
|
|||||||
def test_cisco_tcp_fin_timeout_is_15():
|
def test_cisco_tcp_fin_timeout_is_15():
|
||||||
assert get_os_sysctls("cisco")["net.ipv4.tcp_fin_timeout"] == "15"
|
assert get_os_sysctls("cisco")["net.ipv4.tcp_fin_timeout"] == "15"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# os_fingerprint module — icmp_ratelimit
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_linux_icmp_ratelimit_is_1000():
|
||||||
|
assert get_os_sysctls("linux")["net.ipv4.icmp_ratelimit"] == "1000"
|
||||||
|
|
||||||
|
|
||||||
|
def test_windows_icmp_ratelimit_is_0():
|
||||||
|
assert get_os_sysctls("windows")["net.ipv4.icmp_ratelimit"] == "0"
|
||||||
|
|
||||||
|
|
||||||
|
def test_bsd_icmp_ratelimit_is_250():
|
||||||
|
assert get_os_sysctls("bsd")["net.ipv4.icmp_ratelimit"] == "250"
|
||||||
|
|
||||||
|
|
||||||
|
def test_embedded_icmp_ratelimit_is_0():
|
||||||
|
assert get_os_sysctls("embedded")["net.ipv4.icmp_ratelimit"] == "0"
|
||||||
|
|
||||||
|
|
||||||
|
def test_cisco_icmp_ratelimit_is_0():
|
||||||
|
assert get_os_sysctls("cisco")["net.ipv4.icmp_ratelimit"] == "0"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# os_fingerprint module — icmp_ratemask
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_linux_icmp_ratemask_is_6168():
|
||||||
|
assert get_os_sysctls("linux")["net.ipv4.icmp_ratemask"] == "6168"
|
||||||
|
|
||||||
|
|
||||||
|
def test_windows_icmp_ratemask_is_0():
|
||||||
|
assert get_os_sysctls("windows")["net.ipv4.icmp_ratemask"] == "0"
|
||||||
|
|
||||||
|
|
||||||
|
def test_bsd_icmp_ratemask_is_6168():
|
||||||
|
assert get_os_sysctls("bsd")["net.ipv4.icmp_ratemask"] == "6168"
|
||||||
|
|
||||||
|
|
||||||
|
def test_embedded_icmp_ratemask_is_0():
|
||||||
|
assert get_os_sysctls("embedded")["net.ipv4.icmp_ratemask"] == "0"
|
||||||
|
|
||||||
|
|
||||||
|
def test_cisco_icmp_ratemask_is_0():
|
||||||
|
assert get_os_sysctls("cisco")["net.ipv4.icmp_ratemask"] == "0"
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# os_fingerprint module — structural / completeness
|
# os_fingerprint module — structural / completeness
|
||||||
|
|||||||
Reference in New Issue
Block a user