项目地址#
注:开发者的全部言论仅代表个人观点,代码开源,不提供任何关于协议的额外说明。
项目属性#
-
优点
- 可与现有 TCP 代理工具无缝集成
- 抗检测、通报、嗅探
- 不加密明文模式对中转设备性能开销极低
- 代码开源,可自行修改以使用 DPDK,eBPF 等技术实现大吞吐。
- 针对目前全部防火墙的弱点(即使用 TCP 三 / 四元组对链接进行追踪)
-
缺点
- 不加密时对于二进制匹配无抵抗力
- 加密流会增强防火墙对于流量的关注度,出现延迟升高或丢包,但 5TB 单向未出现端口阻断。
- 会导致 DDoS 缓解机制误判,进而阻塞流量或重置现有链接。
-
玩具
该项目的本质只是作者的玩具和对于一个概念的验证,并不打算持续维护。
开放的原因仅打算为当前环境提供一点新的思路。
实现#
楔子#
如今互联网上如此之多的翻墙协议,各类实现层次不齐但却都有着各自的问题在。以 Shadowsocks 为首的全加密流在解决了主动嗅探以及全随机流量精准识别的问题后仍然是不少人的首选。R 佬所开发的各类基于 TLS 的花活也成功将个人流量代表的一棵树隐藏在一片森林之中。
但这些协议在实际应用的过程中仍有自己的软肋:在防火墙逐步将审查、监测等功能下放到边缘设备上进行的今日,个人用户设备上流出的全加密流量如同社区区域网络中的一盏明灯;普通用户在中转设备上使用 R 佬提供的偷证书功能时往往忘记了来自于信管局的嗅探和监测,最终被通报、清退。
并且两种设计思路都具有严重的一个问题:加密开销。绝大多数代理工具的客户端设备往往使用着近 5 年生产的 CPU 和完整的物理设备性能,可以轻松提供 OpenSSL 加密套件运行需要的性能;而服务端往往是性能限制严格的虚拟主机。为了实现更高的吞吐带宽主流 1core512MB 的配置早已显得捉襟见肘。常用开发语言 Golang 对于内存的开销更是让服务端雪上加霜。
目的#
针对防火墙监控流量的原理设计协议以降低服务端加密强度成为了项目的首要目标。而在回顾过去的各类开源项目之后,一个痛苦的事实浮出水面 —— 早年提出的西厢计划,是目前唯一一个从原理层面出发,绕过防火墙识别,进而访问外界网络的项目。
就如今而言,这样的漏洞已经几乎不可能找到了,必须从防火墙识别流量的原理上着手去处理。现代防火墙以及目前市售防火墙的流量嗅探均基于三元组或更精细的四元组,即:
(source IP, destination IP, destination PORT)
(source IP, source PORT, destination IP, destination PORT )
一个想法在我们脑海浮出水面:将原本的一个三元组拆分为两个不同的三元组之后,防火墙是否还有能力对内部数据包建立关联或监控?
设计思路#
内部早有提前归纳 usenix23 中列举的防火墙流量豁免规则甚至更为深入,我们设计了一个几乎完全符合该五条规则的一个握手响应,全部由可打印字节构成,在字符层面随机,二进制层面低熵。
鉴于可能没有公网 IP 的场景,该设计中全部链接均由客户端主动建立,数据流传输到服务端后合并。
考虑到部分省市地区和一些特殊场合使用的防火墙和规则具有二进制匹配能力,我们仍然在协议中集成了可选的加密套件。
不足#
-
在通过明文握手包初步令防火墙忽略该 TCP 链接后,我们未对该三元组延迟增大程度和丢包情况做持续检测,无法确认大流量情况下是否存在目前没有发现的探测机制接入。
-
我们进行了单边大流量测试以及泉州新疆等地区的简单测试均确认了连通性,但对于伊朗等地区的情况仍无法深入测试。
-
在持续运行 48 小时左右,移动会直接阻断链接,但不知道触发了什么机制。电信联通未见任何异常。
-
无法确认是明文握手包起了作用还是对于三元组的切割起了作用。(考虑可能存在的 AES 特征爆破…… 个人认为都起了作用
配置文件#
范例#
[app]
alignment=4096
mode=client
ip=::
port=30000
inbound-ip=localhost
inbound-port=10000
outbound-ip=localhost
outbound-port=20000
turbo=true
backlog=511
fast-open=true
keep-alived=true
connect.timeout=10
handshake.timeout=5
protocol=tcp
更多配置参考 samples 目录
参数解释#
-
alignment
alignment_malloc 内存对齐参数
-
mode
运行模式,[client, server]
-
ip
若运行模式为 client,则该值表示监听 IP;若运行模式为 server,该值表示原本的 destination IP
-
port
若运行模式为 client,则该值表示监听 PORT;若运行模式为 server,该值表示原本的 destination PORT
-
inbound-ip
设置承载上行链路的 TCP 链接使用的 IP
-
inbound-port
设置承载上行链路的 TCP 链接使用的 PORT
-
outbound-ip
设置承载下行链路的 TCP 链接使用的 IP
-
outbound-port
设置承载下行链路的 TCP 链接使用的 PORT
-
turbo
TCP 链接加速
-
backlog
TCP 链接 backlog 参数
-
fast-open
启用 TCP-Fast-Open
-
keep-alived
启用 TCP Keep-alive
-
connect.timeout
设置 TCP 超时时间
-
handshake.timeout
设置协议握手超时时间
-
protocol
传输协议,TCP 表示除握手包之外不加密。
使用案例#
warp+uds#
Cloudflare 提供的 warp 常常作为改善国际路由的工具部署于一些网络质量一般的虚拟主机上。Cloudflare 针对大多数 Linux 发行版均提供了包管理器安装方式
-
安装 WARP
此处请参考Cloudflare 官方教程 -
切换模式
成功安装 warp 并注册客户端之后,将客户端运行模式切换为 proxy 模式。warp-cli set-mode proxy
-
更改 warp 使用的端口(可选)
warp 在 proxy 模式下默认监听 1080 端口。warp-cli set-proxy-port [PORT]
warp 默认只监听 127.0.0.1 上的端口,不用担心该 socks5 端口被扫描到。
-
启动 UDS 服务端
配置文件如下
[app]
alignment=4096
mode=server
ip=127.0.0.1
port=1080
inbound-ip=::
inbound-port=10000
outbound-ip=::
outbound-port=20000
turbo=true
backlog=511
fast-open=true
keep-alived=true
connect.timeout=10
handshake.timeout=5
protocol=tcp
启动 uds 服务端
./udss --config=config.ini
- 启动 UDS 客户端
[app]
alignment=4096
mode=client
ip=127.0.0.1
port=1080
inbound-ip=[remote IP]
inbound-port=10000
outbound-ip=[remote IP]
outbound-port=20000
turbo=true
backlog=511
fast-open=true
keep-alived=true
connect.timeout=10
handshake.timeout=5
protocol=tcp
- 连接
使用你喜欢的工具连接 socks5://127.0.0.1:1080 即可
Dante + UDS#
如果不是 warp 能够通过 Cloudflare 的网络对国际路由进行优化和减少被送中的可能,我个人更加喜欢轻量的 Dante 来创建 socks5 连接
操作流程和 warp 非常接近,不再赘述
现有中转接入 UDS#
测试中可不加密中转纯 vless 数据流
-
在落地设备上下载 udss
-
设置服务端目标端口为原有代理的监听端口
-
在中转机上下载 udsc
-
设置客户端上行连接和下行连接与服务端对应
-
设置客户端监听地址和端口
如果需要平滑迁移则不可使用原有端口,建议中断原有服务再启动 UDS
-
启动 uds 客户端
尾言#
uds 只是一个概念性实现,不建议在生产环境中大规模使用,并且不适合用于 UDP over TCP 的传输场景。如有 UDP 流量的需求请自行修改代码实现。
uds 全部代码遵循 MIT 协议。