Both VoIP-correlation implementations are boundary-aware rather than treating every SIP/RTP flow uniformly. The legacy pipeline (log-stream-voip-relation) has a configurable check.inner.network toggle and an isInnerIp() check that classifies purely-internal-network SIP flows into a distinct "sip-in" type which is passed straight to output unmerged (never fed into the correlation cache); the newer Easy-Stream rewrite (sip-rtp-correlation) exposes the same internal/external distinction as first-class Flink Table UDFs (IS_INTERNAL_IP_ADDRESS, HAS_EXTERNAL_IP_ADDRESS).
check ip is Inner network;0 off, 1 on.
Defense implications
- The correlation pipeline is architected to distinguish traffic that stays inside the monitored network from traffic that crosses to an external address, which is consistent with the correlator's purpose being reconstruction of calls that traverse the monitored boundary (subscriber-to-outside-world) rather than pure LAN telephony -- relevant when reasoning about which VoIP-based circumvention traffic patterns this subsystem is actually built to prioritize.
Cited artifacts
mesalab_git—galaxy/tsg_olap/log-stream-voip-relation.bundle:src/main/java/com/zdjizhi/tools/utils/RelationUtils.java(source-code)mesalab_git—galaxy/tsg_olap/log-stream-voip-relation.bundle:src/main/java/com/zdjizhi/operator/window/VoipCalibrationWindowFunction.java(source-code)mesalab_git—galaxy/tsg_olap/sip-rtp-correlation.bundle:src/main/java/com/geedgenetworks/flink/easy/application/voip/udf/IsInternalIpAddress.java(source-code)mesalab_git—galaxy/tsg_olap/sip-rtp-correlation.bundle:src/main/java/com/geedgenetworks/flink/easy/application/voip/udf/HasExternalIpAddress.java(source-code)
Provenance pointers only — no leak content is rehosted. Raw material: Enlace Hacktivista.
Related findings
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.
The VoIP-fusion correlation key linking a SIP signaling record to its RTP media record is not timing/heuristic-based -- it is an exact match between the negotiated media endpoint fields parsed out of the SIP record (from_rtp_ip/from_rtp_port/to_rtp_ip/to_rtp_port, i.e. the SDP-negotiated RTP endpoints carried in the SIP signaling) and the actual observed RTP flow's four-tuple (common_client_ip/port, common_server_ip/port). A separate normalization rule sorts every four-tuple by port then IP (smaller first) before use as a join key, and common_vsys_id is the default grouping/partition key.
VoipCalibrationWindowFunction only auto-merges a candidate group when it is exactly one-to-many (1 RTP matched to N SIP records, or 1 SIP matched to N RTP records); any other cardinality within a correlation-key bucket (e.g. 2 SIP + 2 RTP) is explicitly logged as anomalous ("Not logical") and every record in that bucket is emitted individually as an unmerged "violation" log rather than being forced into a merge or silently dropped.
VoIP correlation runs in two sequential time windows, not one -- an initial tumbling window (voip.calibration.window.time, configured at 30s) attempts to fuse SIP/RTP records sharing a key, and any record still unmatched after that window is held in a second in-memory cache and retried against a longer secondary window (sec.combine.sr.cache.secs, configured at 60s) before finally being emitted unmerged -- giving the pipeline up to ~90s of tolerance for SIP and RTP legs of the same call arriving out of sync.
TSG's VoIP-fusion pipeline (galaxy/tsg_olap/log-stream-voip-relation) does not just correlate SIP/RTP metadata into call records -- when both correlated RTP legs carry a stored packet-capture file path (rtp_pcap_path), the pipeline concatenates the two paths and writes the combined path into the final merged VoIP record, i.e. the correlated call record carries a pointer to the actual retained audio capture(s) for that call, not just flow statistics.