V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
dndx
V2EX  ›  分享创造

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

  •  
  •   dndx · 70 天前 · 3227 次点击
    这是一个创建于 70 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    目标

    • 高性能
    • 低并且可预测的 MTU overhead (用最小的数据包头部,最大限度的为 UDP payload 保留空间)
    • 多核友好
    • 低资源占用

    实现

    整个项目使用 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

    26 条回复    2021-11-06 20:04:46 +08:00
    Tink
        1
    Tink   70 天前 via Android
    牛啊,这个感觉是 wireguard 绝配
    meanmachine
        2
    meanmachine   70 天前
    mark... udp2raw 跑单核确实蛋疼了一点
    makelove
        3
    makelove   70 天前
    太牛了,而且这种真是生活必须品。
    我当前用 upd2raw,确实对我用来 fq 的垃圾小鸡性能有点压力。
    codehz
        4
    codehz   70 天前 via Android
    测试过可以穿透一些常见的 tcp 反代 /负载均衡吗(
    dndx
        5
    dndx   70 天前 via iPhone
    @codehz 7 层反代是不行的,7 层反代的 TCP 栈是操作系统的,这种只能用真的 TCP 来实现,就没有了 Fake TCP 的性能优势。
    messense
        6
    messense   70 天前
    > 唯一的缺点就是 async Rust 因为 Futures 用的比较多,build 出来的二进制文件也比较大,超过了 6MB

    可以用 upx 压缩一下,应该可以小很多;也可以再试试开启 LTO and/or opt-level = "z"
    kkocdko
        7
    kkocdko   70 天前 via Android
    @messense 个人认为 binary 大小不算太大问题,比起 golang 自带 runtime 那动辄 10M+的体积,已经算很理想了。
    lto pgo 之类的楼主这个水平应该会考虑到,optz 就算了,这项目的初衷大概就是性能? optz 开倒车呢
    dndx
        8
    dndx   70 天前 via iPhone
    @kkocdko
    @messense 目前 release 用 zip 压缩一下两个 binary 一共也不到 4MB,还算可以接受。
    plko345
        9
    plko345   69 天前 via Android   ❤️ 1
    楼主,请教你这些网络编程相关的知识有哪些书推荐,或课程
    codehz
        10
    codehz   69 天前
    @dndx 我是说 cloudflare spectrum 这样的服务,理论上是 layer 4 的反代
    dndx
        11
    dndx   69 天前 via iPhone
    @codehz 这种肯定没有问题,MTU 调好就行。
    onlyu
        12
    onlyu   69 天前
    很棒啊,这样的分享是最想看到的
    dndx
        13
    dndx   69 天前
    @codehz 又看了一下,Spectrum 宣称可以提供请求日志,感觉像是在 CF Edge 终结了 TCP 连接,如果是这样的话应该不行,最好实际测一下。
    dndx
        14
    dndx   69 天前 via iPhone   ❤️ 1
    @plko345 网络编程入门的话我看的是 UNIX Network Programming 。写 Phantun 主要就是看 RFC793 和 API 文档了。
    lookas2001
        15
    lookas2001   69 天前 via Android
    好项目,赞
    vinsoncou
        16
    vinsoncou   67 天前
    @dndx 按步骤测试下来发现 linux server 上没有端口监听,不知道问题出在哪里。
    dndx
        17
    dndx   67 天前
    @vinsoncou 本身就不是系统的 socket,看不到监听是正常的,只要 tun 设备出现就 ok 了
    vinsoncou
        18
    vinsoncou   67 天前
    @dndx 客户端的 wg 的 endpoint 要改为 Phantun client 的监听 ip,如示例中的 127.0.0.1:1234 么?
    dndx
        19
    dndx   67 天前
    @vinsoncou 是的,客户端连接 `./phantun_client --local` 设置的端口。
    wangyucn
        20
    wangyucn   66 天前
    来滋瓷一个, 用 tun 实现很不错。
    raysonx
        21
    raysonx   65 天前
    挺有意思的的项目,已关注。后面如有用的话希望能够贡献代码。
    NeedforV2
        22
    NeedforV2   62 天前
    LZ 牛 B,赞一个
    F0nebula
        23
    F0nebula   59 天前 via Android
    以性能为代价可以优化二进制文件大小吗 校园网是百兆 但是路由器 ROM 只有 16MB
    dndx
        24
    dndx   59 天前   ❤️ 1
    @F0nebula 可以按照 @messense 的建议尝试修改 Rust 的编译选项。再不济也可以下载到 tmpfs 里来执行(如果 RAM 够的话)。
    hronro
        25
    hronro   59 天前
    能实现类似 udp2raw 的那种底层掉线上层不掉线吗?
    xiaoun001
        26
    xiaoun001   22 天前   ❤️ 1
    感谢楼主 github 中不厌其烦的解释,前后折腾很久,终于用上了。话说真的真稳定,也非常不错。之前一直不通,楼主指导用 TCPDUMP 抓包,终于找到原因了。
    注意两个坑:1 、服务端、客户端地址本地有效,最直观用途就是用来做 NAT 转发的。是无法 ping 通对端的。
    2 、Linux tun 设备是成对出现的,因此系统 tun0 地址并不是实际发包的地址(用 TCPDUMP 抓包才看到)。
    tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
    inet 192.168.200.1 netmask 255.255.255.255 destination 192.168.200.2
    此例,发包的地址是 192.168.200.2 ,也就是 snat 目标地址,而不是 200.1 。
    3 、phantun 在 bash 下运行的很好,在 sh 下面运行报错。因此,注意 shell 解释器选择。之前在我的客户机 rc.local 就这句不行,服务器就可以。不经意发现客户机的 rc.local 靠头是
    #!/bin/sh 改成 bash 正常。测试,的确在 sh 下运行报错。
    4\ 楼主说明书客户端 那条比较宽泛 iptables 命令,对我的环境 多出口无效(策略路由环境),其实只要明白 iptables 是为了解决本地 tun0 接口出去,回来,就是让通过 tun0 口 192.168.200.2 能够上网,问题迎刃而解。若您有同样问题,请参考我下面的配置。

    用上了,很好。楼主的 phantun ,速率接近 UDP 速率,差不多是 4/5 左右. 王宇大神的 udp2raw 高峰期差不多 2/3 。两个产品都很好,所以我同时用上了。我自己不会写网络程序,感谢两位大神。感谢楼主 isuse 不厌其烦解释。

    phantun 配置
    服务端:
    /sbin/iptables -t nat -A POSTROUTING -s 192.168.201.1/24 -j SNAT –to-source 服务器 IP
    /usr/local/bin/phantun_server -l 3389 -r 127.0.0.1:3389 2>1&
    /sbin/iptables -t nat -A PREROUTING -p tcp -i eth0 –dport 3389 -j DNAT –to-destination 192.168.201.2


    客户端
    /sbin/iptables/iptables -t nat -A POSTROUTING -s 192.168.200.1/24 -j SNAT –to-source 172.16.0.222
    /usr/local/bin/phantun_client -l 127.0.0.1:3389 -r 服务器 IP:3389 2>1&
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1060 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:23 · PVG 07:23 · LAX 15:23 · JFK 18:23
    ♥ Do have faith in what you're doing.