#1586·hysteria

引入强制 UDP 填充以绕过基于包大小的 DPI 审查(针对伊朗网络环境)

Author: sekaiyichibanhentaiCreated May 23, 2026Updated Jul 30, 2026
Labelsenhancement

[English Version] Hi,

I am opening this issue on behalf of a fellow internet user and developer from Iran who is currently facing severe censorship and requested my assistance in conveying this critical feature request. Here is their report and analysis:

Background & Problem Analysis (Iran Network Crisis) Currently, the censorship system in Iran has implemented an aggressive, behavior-based UDP blocking mechanism. The firewall strictly monitors the length of UDP packets. Through extensive network analysis and MTU/packet-size probing, it was discovered that the DPI system instantly drops, throttles, or mutes any unknown or obfuscated UDP packet that is under 1473 bytes. This applies heavily to the initial QUIC handshake (Client Hello) and early protocol negotiations, resulting in persistent client-side timeouts (no recent network activity).

Crucially, any UDP packet with a total size of 1473 bytes or higher completely bypasses this specific DPI filter. The firewall seems to systematically whitelist or ignore large-MTU UDP payloads to prevent breaking legitimate heavy streaming, gaming, or enterprise tunneling traffic that operates at the edge of standard MTU limits.

Temporary Solution & Test Results To bypass this network barrier, the user modified the WriteTo method inside Hysteria's extras/obfs/conn.go. Before the obfuscated packet hits the socket, it is intercepted. If the packet size (nn) is lower than 1473 bytes, the remainder of the pre-allocated writeBuf is manually padded with null bytes (zeros) to force the output slice to a minimum size of 1475 bytes (ensuring it stays strictly above the 1473-byte censorship threshold while remaining within safe Ethernet MTU bounds to avoid fragmentation).

Since Hysteria runs on top of QUIC, the server-side QUIC layer inherently processes the stream, recognizes the trailing padding frames, and discards them seamlessly without causing any protocol or state errors. This simple modification immediately completely restored connection functionality in Iran, enabling instant handshakes and full-speed transport.

Native Feature Request However, a hardcoded static padding value can eventually be fingerprinted. Therefore, we highly recommend introducing a native configuration option for Forced Minimum UDP Padding.

Ideally, users should be able to define parameters in the obfs or transport config, such as:

min_udp_packet_size: A threshold (e.g., set to 1475) that forces all outbound UDP packets—including the very first handshake—to be padded up to this size if they are smaller.

padding_byte_type: An option to use either null bytes (0x00) or randomized junk bytes to prevent entropy-based detection.

Implementing this parameter would give Hysteria unprecedented resilience against cutting-edge, size-sensitive censorship systems like the one currently deployed in Iran, without requiring any changes to the underlying QUIC transport logic.

Thank you for your time, dedication, and for keeping the internet open. We look forward to hearing your technical insights on incorporating this feature natively.

[中文版本] Hi,

我是替一位来自伊朗的朋友(开发者/用户)代发这个 Issue 的。由于当地严重的网络审查,他无法直接提交,因此委托我向项目组转达这个紧急的功能请求。以下是他的详细分析与测试报告:

背景与问题分析(伊朗当前网络现状) 目前,伊朗的防火墙实施了极具攻击性的行为分析型 UDP 阻断机制。防火墙开始严格监控 UDP 数据包的长度。通过大量的网络分析和 MTU/包大小探测,发现:防火墙会立即丢弃、限速或屏蔽任何小于 1473 字节的未知/混淆 UDP 数据包。这一策略严重影响了 Hysteria 初始的 QUIC 握手(Client Hello)及早期的协议协商阶段,导致客户端频繁出现持续超时(提示 no recent network activity)。

然而,任何总大小等于或大于 1473 字节的 UDP 数据包,都能完全绕过这一特定的 DPI 过滤器。防火墙似乎系统性地放行或忽略了接近标准 MTU 上限的大数据包,以避免误杀合法的流媒体、游戏或企业级隧道流量。

临时解决方案与测试结果 为了验证这一猜想,该用户修改了 Hysteria 源码中 extras/obfs/conn.go 的 WriteTo 方法。在混淆后的数据包发送到 Socket 之前进行拦截:如果包大小(nn)小于 1473 字节,就手动用空字节(null bytes / Zeros)将预分配的 writeBuf 剩余部分填满,强制使输出切片(Slice)的最小尺寸达到 1475 字节(确保严格大于 1473 字节的审查阈值,同时保持在以太网安全 MTU 范围内以避免分片)。

由于 Hysteria 基于 QUIC 运行,服务端底层的 QUIC 层在处理流时,会自动识别并丢弃这些尾部的填充帧(Padding Frames),不会引发任何协议或状态错误。这一微小的修改立刻完全恢复了 Hysteria 在伊朗的连接能力,握手瞬间完成,传输速度拉满。

原生功能建议 由于硬编码的固定填充值最终可能会形成特征(Fingerprint),因此强烈建议在 Hysteria 中引入原生的强制最小 UDP 填充(Forced Minimum UDP Padding)配置项。

理想情况下,用户可以在 obfs 或 transport 配置中自定义以下参数:

min_udp_packet_size: 设置一个阈值(例如 1475)。当所有出站 UDP 数据包(包括最开始的握手包)小于该值时,强制将其填充至该大小。

padding_byte_type: 提供填充类型的选项,支持使用空字节 (0x00) 或 随机垃圾字节 (Randomized junk bytes),以防止审查系统通过信息熵(Entropy)检测特征。

总结 实现该参数可以让 Hysteria 在对抗像伊朗目前部署的这种“对数据包大小敏感”的尖端审查系统时,拥有极强的弹性,且不需要对底层的 QUIC 传输逻辑做任何大改。

非常感谢开发者的时间、付出以及对互联网自由做出的贡献!期待您对该功能原生实现的看法。