test: add fingerprinting and TCP analysis tests
- test_sniffer_p0f.py: p0f passive OS fingerprinting tests - test_sniffer_tcp_fingerprint.py: TCP fingerprinting accuracy tests - test_sniffer_retransmit.py: retransmission detection and analysis
This commit is contained in:
117
tests/test_sniffer_p0f.py
Normal file
117
tests/test_sniffer_p0f.py
Normal file
@@ -0,0 +1,117 @@
|
||||
"""
|
||||
Unit tests for the passive p0f-lite OS fingerprint lookup.
|
||||
|
||||
Covers:
|
||||
- initial_ttl() TTL → bucket rounding
|
||||
- hop_distance() upper-bound clamping
|
||||
- guess_os() signature matching for Linux, Windows, macOS, nmap,
|
||||
embedded, and the unknown fallback
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from decnet.sniffer.p0f import guess_os, hop_distance, initial_ttl
|
||||
|
||||
|
||||
# ─── initial_ttl ────────────────────────────────────────────────────────────
|
||||
|
||||
class TestInitialTtl:
|
||||
def test_linux_bsd(self):
|
||||
assert initial_ttl(64) == 64
|
||||
assert initial_ttl(59) == 64
|
||||
assert initial_ttl(33) == 64
|
||||
|
||||
def test_windows(self):
|
||||
assert initial_ttl(128) == 128
|
||||
assert initial_ttl(120) == 128
|
||||
assert initial_ttl(65) == 128
|
||||
|
||||
def test_embedded(self):
|
||||
assert initial_ttl(255) == 255
|
||||
assert initial_ttl(254) == 255
|
||||
assert initial_ttl(200) == 255
|
||||
|
||||
def test_very_short(self):
|
||||
# anything <= 32 rounds to 32
|
||||
assert initial_ttl(32) == 32
|
||||
assert initial_ttl(1) == 32
|
||||
|
||||
def test_out_of_range(self):
|
||||
# Packets with TTL > 255 (should never happen) still bucket.
|
||||
assert initial_ttl(300) == 255
|
||||
|
||||
|
||||
# ─── hop_distance ───────────────────────────────────────────────────────────
|
||||
|
||||
class TestHopDistance:
|
||||
def test_zero_when_local(self):
|
||||
assert hop_distance(64) == 0
|
||||
assert hop_distance(128) == 0
|
||||
assert hop_distance(255) == 0
|
||||
|
||||
def test_typical(self):
|
||||
assert hop_distance(60) == 4 # 4 hops from Linux
|
||||
assert hop_distance(120) == 8 # 8 hops from Windows
|
||||
|
||||
def test_negative_or_weird_still_bucketed(self):
|
||||
# TTL=0 is anomalous but we still return a non-negative distance.
|
||||
# TTL 0 bucket is 32 → distance = 32 - 0 = 32.
|
||||
assert hop_distance(0) == 32
|
||||
|
||||
|
||||
# ─── guess_os ───────────────────────────────────────────────────────────────
|
||||
|
||||
class TestGuessOs:
|
||||
def test_linux_default(self):
|
||||
# Modern Linux: TTL 64, window 29200+, WScale 7, full options
|
||||
result = guess_os(
|
||||
ttl=64, window=29200, mss=1460, wscale=7,
|
||||
options_sig="M,S,T,N,W",
|
||||
)
|
||||
assert result == "linux"
|
||||
|
||||
def test_windows_default(self):
|
||||
# Windows 10: TTL 128, window 64240, WScale 8, MSS 1460
|
||||
result = guess_os(
|
||||
ttl=128, window=64240, mss=1460, wscale=8,
|
||||
options_sig="M,N,W,N,N,T,S",
|
||||
)
|
||||
assert result == "windows"
|
||||
|
||||
def test_macos_ios(self):
|
||||
# macOS default: TTL 64, window 65535, WScale 6, ends with EOL
|
||||
result = guess_os(
|
||||
ttl=64, window=65535, mss=1460, wscale=6,
|
||||
options_sig="M,N,W,N,N,T,S,E",
|
||||
)
|
||||
assert result == "macos_ios"
|
||||
|
||||
def test_nmap_sYn(self):
|
||||
# nmap -sS uses tiny/distinctive windows like 1024 or 4096
|
||||
result = guess_os(
|
||||
ttl=64, window=1024, mss=1460, wscale=10,
|
||||
options_sig="M,W,T,S,S",
|
||||
)
|
||||
assert result == "nmap"
|
||||
|
||||
def test_nmap_alt_window(self):
|
||||
result = guess_os(
|
||||
ttl=64, window=31337, mss=1460, wscale=10,
|
||||
options_sig="M,W,T,S,S",
|
||||
)
|
||||
assert result == "nmap"
|
||||
|
||||
def test_embedded_ttl255(self):
|
||||
# Any TTL bucket 255 → embedded
|
||||
result = guess_os(
|
||||
ttl=250, window=4128, mss=536, wscale=None,
|
||||
options_sig="M",
|
||||
)
|
||||
assert result == "embedded"
|
||||
|
||||
def test_unknown(self):
|
||||
# Bizarre combo nothing matches
|
||||
result = guess_os(
|
||||
ttl=50, window=100, mss=0, wscale=None, options_sig="",
|
||||
)
|
||||
assert result == "unknown"
|
||||
Reference in New Issue
Block a user