Skip to content

feat: sniffer support stun protocol#2761

Open
BLxcwg666 wants to merge 1 commit intoMetaCubeX:Metafrom
BLxcwg666:Meta
Open

feat: sniffer support stun protocol#2761
BLxcwg666 wants to merge 1 commit intoMetaCubeX:Metafrom
BLxcwg666:Meta

Conversation

@BLxcwg666
Copy link
Copy Markdown

Problem Background

In redir-host mode, WebRTC STUN traffic can leak the user's real IP address because STUN traffic cannot be correctly routed to the proxy in the following scenarios:

  1. DNS mapping cache miss — The withMapping middleware uses DNS TTL as the cache expiration time. After expiration, FindHostByIP fails to reverse lookup, metadata.Host is empty, and rule matching can only rely on the IP address.
  2. Browser bypasses DNS lookup — WebRTC can directly connect to the STUN server via IP address, and the corresponding record does not exist in the mapping.

In these cases, STUN traffic lacks domain name information for rule matching. Without precise IP rule coverage, it will reach DIRECT, causing the STUN server to see the user's real exit IP address.

image

FakeIP mode is unaffected because all domains have a bidirectional mapping from FakeIP to the domain name.

Proposal

Add STUN protocol sniffing and a general SNIFF-PROTOCOL rule type, allowing users to define proxy rules based on protocols.

STUN Protocol Detection

Based on three characteristics from RFC 8489 Section 6, a single packet can be used to determine:

  • The first byte's high 2 bits are 00 (distinguishing between RTP/RTCP/DTLS)
  • Bytes 4-7 are Magic Cookie 0x2112A442
  • Message Length is a multiple of 4

Magic Cookie This is an identifier specifically designed by the RFC for protocol multiplexing, with a false positive rate of approximately 1/2^32. It can be safely detected across all ports without relying on port numbers.

Unlike QUIC/TLS/HTTP sniffers, the STUN protocol does not carry domain name information. Therefore, a new mechanism is needed for the rule engine to utilize the protocol detection results.

SNIFF-PROTOCOL Rule

Add a SniffProtocol field to the Metadata. When the sniffer recognizes the protocol but cannot extract the domain name (SniffData returns an empty host), set this field to the protocol name (e.g., "stun"). Add a SNIFF-PROTOCOL rule type to match this field:

sniffer:
  enable: true
  sniff:
    TLS:
      ports: [443]
    STUN:
      ports: [3478, 5349, 19302-19305]  ## Optional
rules:
  - SNIFF-PROTOCOL,stun,Proxy   # Setting rules for STUN
  - MATCH,DIRECT

Design Considerations

  • SNIFF-PROTOCOL is general — Although currently only STUN is supported, the framework can be extended to other domain-free protocols (DNS-over-UDP, WireGuard handshake, etc.) without needing to add separate rule types for each protocol
  • Non-destructive — Does not modify existing sniffer behavior and does not affect existing configurations; routing effects only occur when users explicitly use SNIFF-PROTOCOL rules
  • STUN sniffer is automatically registered by default — Because the detection is highly reliable and has no performance overhead, the sniffer automatically takes effect when enabled, and users do not need to manually declare STUN in the sniff.

Test Results

It passed the tests on several WebRTC Leak Test websites.

image

问题背景

redir-host 模式下,WebRTC 的 STUN 流量会泄露用户真实 IP,原因是 STUN 流量在以下场景中无法被正确路由到代理:

  1. DNS mapping 缓存未命中 — withMapping 中间件使用 DNS TTL 作为缓存过期时间,过期后 FindHostByIP 反查失败,metadata.Host 为空,规则匹配只能依赖 IP

  2. 浏览器绕过了 DNS 查询 — WebRTC 可以直接通过 IP 地址连接到 STUN 服务器,mapping 中根本不存在对应记录
    在这些情况下,STUN 流量没有域名信息可供规则匹配,如果没有精确的 IP 规则覆盖,就会走到 DIRECT,导致 STUN 服务器看到用户的真实出口 IP

image

FakeIP 模式不受此影响,因为所有域名都有 FakeIP 到域名的双向映射

提案

新增 STUN 协议嗅探和通用的 SNIFF-PROTOCOL 规则类型,让用户可以基于协议来制定代理规则

STUN 协议检测

基于 RFC 8489 Section 6 的三个特征,单个数据包即可判定:

  • 首字节高 2 位为 00(区分 RTP/RTCP/DTLS)
  • 字节 4-7 为 Magic Cookie 0x2112A442
  • Message Length 为 4 的倍数

Magic Cookie 是 RFC 专门为协议多路复用设计的标识符,误报率约 1/2^32,无需依赖端口号即可安全地在全端口范围检测
与 QUIC/TLS/HTTP sniffer 不同的是,STUN 协议不携带域名信息,因此需要一种新的机制来让规则引擎利用协议检测结果

SNIFF-PROTOCOL 规则

在 Metadata 上新增 SniffProtocol 字段,当 sniffer 识别到协议但无法提取域名时(SniffData 返回空 host),设置该字段为协议名称(如 "stun")。新增 SNIFF-PROTOCOL 规则类型匹配该字段:

sniffer:
  enable: true
  sniff:
    TLS:
      ports: [443]
    STUN:
      ports: [3478, 5349, 19302-19305]  ## 可选
rules:
  - SNIFF-PROTOCOL,stun,Proxy   # 为 STUN 设定规则
  - MATCH,DIRECT

设计考量

  • SNIFF-PROTOCOL 是通用的 — 虽然当前只有 STUN,但该框架可以扩展到其他无域名协议(DNS-over-UDP、WireGuard 握手等),不需要为每种协议单独加规则类型
  • 非破坏性 — 不修改现有 sniffer 行为,不影响已有配置;只有在用户显式使用 SNIFF-PROTOCOL 规则时才会产生路由效果
  • STUN sniffer 默认自动注册 — 因为检测可靠性极高且无性能开销,sniffer 启用时自动生效,用户无需手动在 sniff 中声明 STUN

测试结果

在数个 WebRTC Leak Test 网站上均可通过检测
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant