Phantun - Rust 写的轻量级 UDP -> TCP 混淆器

2021-09-19 17:43:46 +08:00
 dndx

GitHub: https://github.com/dndx/phantun

Crates: https://crates.io/crates/phantun

Phantun 的初衷跟 @wangyucn 的 udp2raw 很类似,都是为了实现一种简单的用户态 TCP 状态机来对 UDP 流量做伪装。主要的目的是希望能让 UDP 流量看起来像是 TCP,又不希望受到 TCP retransmission 或者 congestion control 的影响。

目标

实现

整个项目使用 Rust 实现,没有额外的依赖。I/O 部分使用了久经考验的 Tokio。在可能的情况下尽量避免了多进程之间的锁争抢(比如使用原子操作来增加 TCP SEQ/ACK )。

TCP 状态机部分做成了一个单独的库作为 Phantun 的依赖,方便在别的项目里集成:

https://crates.io/crates/fake-tcp

感想

这是我第一个用 async Rust 写的程序,不得不说 async Rust 和 Tokio 的性能大大超出了我的预期。目前这个只有最基本优化的版本在单 CPU 和多 CPU 的情况下性能均超过了基于 libev 和 C++ 的 udp2raw 。Rust 的安全检查也非常的舒服,基本上编译通过了以后不会有任何内存问题的可能。Rust 的 Drop 支持对管理 TCP 的状态也是帮助非常大。总体来说,这个代码量不大的项目的开发效率,执行效率和稳定性都大大超出了我的预期。

目前 Phantun 在几台机器上跑了一段时间,没有出现任何不稳定的现象,任何时候内存占用都未超过 2MB 。核心之间的 CPU 占用也很均匀。用 perf 看了一下火焰图,90% 以上的 CPU 时间都花在了内核态,说明 Tokio 的 runtime 实现是非常的高效的。

Rust 的 build 环境简直不要太舒服,交叉编译不同的架构也就是两行命令的事情,跟原来写 C 比起来开发体验上了一个档次。

唯一的缺点就是 async Rust 因为 Futures 用的比较多,build 出来的二进制文件也比较大,超过了 6MB 。对比之下 udp2raw 的二进制文件只有 5 MB (而且代码量比 Phantun 要多了不少)。

跟 udp2raw 的主要区别

Phantun 的目标不是为了替代 udp2raw,从一开始 Phantun 就希望设计足够的简单高效,所以 udp2raw 支持的 ICMP 隧道,加密,防止重放等等功能 Phantun 都选择不实现。

Phantun 假设 UDP 协议本身已经解决了这些问题,所以整个转发过程就是简单的明文换头加上一些必要的 TCP 状态控制信息。对于我日常使用的 WireGuard 来说,Phantun 这种设计是足够安全的,因为 WireGuard 的协议已经更好的实现了这些安全功能。

Phantun 使用 TUN 接口来收发 3 层数据包,udp2raw 使用 Raw Socket + BFP 过滤器。个人感觉基于 TUN 的实现要稍微的 clean 一点,而且跨平台移植也要更容易(不过目前只做了 Linux 的支持)。

Phantun 的 TCP 连接是按需创建的,只启动 Client 不会主动去连接服务器,需要第一个数据包到达了后才会按需创建。每个 UDP 流都有自己独立的 TCP 连接。这一点跟 udp2raw 很不一样,udp2raw 所有的 UDP 连接共用一个 TCP 连接。这样做的坏处就是 udp2raw 需要额外的头部信息来区分连接,更加增加了头部的开销。跟纯 UDP 比较,Phantun 每个数据包的额外头部开销是 12 byte,udp2raw 根据我的测试达到了 44 bytes 。

跟 udp2raw 的详细功能和性能比较,请查看 README.md

13285 次点击
所在节点    分享创造
48 条回复
tulongtou
2022-12-03 16:00:34 +08:00
好东西,今天用上了
kcc2home
2023-03-03 21:07:14 +08:00
支持 macos 吗
kcc2home
2023-03-03 21:10:14 +08:00
@kcc2home 另外,tcp 阻断可以规避的吗? 佬
sikeer
2023-03-17 21:39:14 +08:00
的确好东西。和 udp2raw 比起来,好象是无状态,不需要握手,不知理解是否正确。
sikeer
2023-03-17 21:43:01 +08:00
@dndx 感谢,我用了好久的 UDP2RAW, 先不说性能,就说 UDP2RAW 握手,不知道为什么经常要好久才能成功。但 phantun 好象不需要握手协议,非常快,请问一下,phantun 是无状态协议,对吗?
dndx
2023-03-19 00:42:55 +08:00
@sikeer 不太清楚,不过 Phantun 跟 udp2raw 这块设计本身就不一样,每个 UDP 会话都有单独的 TCP 连接,udp2raw 是所有会话共享一个 TCP 的。
kcw294196204
357 天前
vsp 的客户端一直报错 ERROR client > Unable to connect to remote 154.18.*.*:4567 怎么破?一直连不上服务端的 IP 和端口
kcw294196204
357 天前
连上了 但是无法上网?
服务器日志
INFO fake_tcp > Sent SYN + ACK to client
INFO fake_tcp > Connection from 42.51.*.*:12122 established
INFO server > New connection: (Fake TCP connection from 192.168.201.2:4567 to 42.51.*.*:12122)
INFO server > No traffic seen in the last 180s, closing connection
INFO fake_tcp > Fake TCP connection to (Fake TCP connection from 192.168.201.2:4567 to 42.51.*.*:62333) closed
客户端日志
INFO client > Remote address is: 154.18.*.*:4567
INFO client > 1 cores available
INFO client > Created TUN device tun0
INFO client > New UDP client from 127.0.0.1:59487
INFO fake_tcp > Sent SYN to server
INFO fake_tcp > Connection to 154.18.*.*:4567 established

客户端 ping
ping: www.google.com: Temporary failure in name resolution


DNS 没问题的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/802949

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX