A MESA Lab task tracker records the assignment "TSG: determine how many clients are behind an IP address," and a companion technical design document details the method: identify distinct TLS clients sharing one public IP using a <JA3 fingerprint, server domain, server IP> 3-tuple (JA3 alone collides across different apps), then use TLS Session Ticket reuse/lifetime sequences per identified client to detect multiple concurrent devices (i.e. NAT) behind that IP.
《TSG》判断一个IP地址后面有多少个客户端 ... 根据之前的分析,可以通过<ja3指纹,服务端域名,服务端IP>这个3元组来标识一个TLS客户端,进而区分不同的TLS客户端发出的Client Hello报文。
Defense implications
- NAT/multi-user detection here keys off TLS Client Hello JA3 + destination SNI/IP + Session Ticket reuse timing, not payload content -- clients sharing a proxy/relay IP should randomize JA3 (cipher-suite/extension order) per session and avoid predictable Session Ticket reuse patterns, since a stable JA3+destination pairing with a clean Session Ticket sequence can itself be read as 'one physical device' vs. an anomalous multi-client relay.
Related findings
TSG's TLS ClientHello parser (MESA_Platform/ssl GitLab component) explicitly parses the ec_point_format extension from ClientHello, confirming deep TLS extension-level fingerprinting beyond simple SNI extraction.
A 3-month E21 (Ethiopia) investigation into unreliable YouTube blocking found two independent, structural detection gaps: (1) at IGW (international gateway) sites, load-balanced multi-path routing causes TSG to see only single-direction (C2S-only or S2C-only) traffic for a meaningful fraction of sessions (~5-10% baseline, worse under load), breaking stateful app-ID/deny; (2) under peak load, NPB boards' CPU-triggered self-protection "bypass" (fail-open passthrough) hit ~50% of new sessions at the busiest site (Bole-IGW, ~86k new sessions/sec at 7.8Gbps/NPB), and TSG explicitly deprioritizes bypass protection for non-HTTP/SSL traffic to preserve web blocking under load.
An internal field-mapping schema for TLS/SSL session logging (cross-referenced against multiple internal system versions, one explicitly labeled "tsg") shows JA3 and JA3S TLS ClientHello/ServerHello fingerprint hashes are captured as standard logged fields alongside SNI, negotiated cipher suites, and the full server and mutual-TLS client certificate chains (issuer, subject, serial, validity window, raw public key).
Session records carry client and server TLS fingerprints (ssl_ja3_hash, ssl_ja3s_hash) and equivalent DTLS fingerprints (dtls_ja3_fingerprint, dtls_ja3_hash) as first-class columns, and the same schema separately includes an SSH client/server fingerprint field (ssh_hassh) alongside ssh_cipher_alg/ssh_kex_alg/ssh_host_key_alg -- confirming JA3/JA3S-style and HASSH-style fingerprinting is computed and retained per session across TLS, DTLS, and SSH traffic, not just TLS.
relationship-gtpc-user derives a single per-subscriber correlation key as Hashkey = md5(IMEI + IMSI + phone_number + vsys_id) from mobile-core GTP-C signaling, and a separate per-tunnel key gtp_uuid = md5(uplink_teid + "|" + downlink_teid). On every update it writes not just the primary user<->TEID row (tsg_galaxy:relation_user_teid) but up to four additional secondary-index rows into tsg_galaxy:gtpc_knowledge_base, one per identifier (IMEI, IMSI, phone number, APN) with a type-digit prefix ("0"/"1"/"2"/"3") and — for phone number and APN — the value's characters reversed before use as the row key, a range-scan-friendly key design that lets any of the four identifiers be used to look up the associated tunnel/session independently.
radius-relationship-hbase (galaxy/tsg_olap) builds a bidirectional, MD5-keyed RADIUS accounting index in HBase — a framed-IP-to-account table and its account-to-IP mirror — so any subscriber account or assigned IP can be looked up in O(1) from either direction, per multi-tenant vsys_id. Each direction is fronted by a Guava write-through cache (10M-entry cap, 24h TTL) so lookups do not hit HBase on the hot path.