V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lanthora
V2EX  ›  宽带症候群

WireGuard 跨国组网失败后,一个新工具的诞生

  •  8
     
  •   lanthora · 9 天前 · 6458 次点击

    TL;DR

    一个可靠,低延迟,反审查的组网工具

    背景

    我在国外有一台性能非常弱但是有公网 IP 的 VPS. 国内有一台 7*24 小时开机的 mini 主机.让 mini 主机作为 VPS 的后端,不在 VPS 上存放任何数据,解决了 VPS 性能弱的问题,也解决了替换 VPS 供应商时迁移数据的问题(当然也包括对 VPS 供应商的信任问题).

    最初选择的组网方案是 WireGuard, 它平静的陪伴了我几个年头,直到 2023 年某此会议的召开.原因为会议开完我的 WireGuard 就能继续用,一个月后证明我想多了.

    于是决定解决这个问题.调研了一系列项目后,没有找到天生隐藏协议特征的组网工具(可能设计者设计之初也没有考虑这种问题把).把 VPN 套到 Proxy 里的这种诡异方案也称试过,虽然能用,但是很不喜欢

    整体设计思路

    设计的宗旨是简洁.在不牺牲性能和核心功能的情况下,用最少的代码量和最简单的概念完成设计.

    降低配置复杂度

    WireGuard 在 VPN 里配置已经相对较简单了,但对我来说依旧过于复杂.回忆一下你用多长时间完成的第一次 WireGuard 组网. WireGuard 需要强制指定虚拟地址,不适用于想要灵活接入多个客户端并动态分配地址的场景.

    用 WSS(Web Socket Secure) 处理通信,在保证链路数据安全的情况下,免去了配置公私钥的过程. 用口令校验客户端,可以轻松的让新客户端加入网络,这样就能由服务端实现地址动态分配.

    高效的断线重连

    在某些情况下 WireGuard 会断线,只有重启客户端才能解决.此时对于一个无人值守的设备,就意味着彻底失联. 曾经为了解决这个问题,给设备配置每天重启一次,这显然是一种很丑陋的解决方案.

    使用 WSS 通信,就可以用 Ping/Pong 完成 TCP 保活,即使 TCP 连接异常断开,应用也可以及时发现,迅速处理.

    支持内网穿透的对等连接

    虽然 WireGuard 支持对等连接,但要求设备之间能够直接访问,对于双方都在 NAT 后面的情况无能为力. 增加内网穿透功能,可以节约服务端转发的流量,同时还能降低通信延迟.

    内网穿透通过 STUN 服务器获取本地 UDP Socket 被映射后的公网地址和端口,通过服务端与其他客户端交换地址和端口信息,并尝试建立连接.

    高速的中继路由

    有时候两个客户端之间无法直连,但它们都能与另一个客户端直连.此时可以以这个客户端作为中继相互访问.

    这实际上是路由的问题.本项目实现的是距离向量算法.

    局域网对等连接

    通过 STUN 查到的用于对等连接的地址是公网地址,对于局域网内能够直连的设备来说,绕到最外层的路由器再回来是浪费了时间的,并且还会受到公网带宽的限制.

    通过用户配置或主动探测本机的局域网地址,可以优先尝试本地直连.

    总结

    其实最初的版本只有 WSS 中继功能,后来在用户的反馈中加上了 P2P 和利用网络中的其他客户端做中继的功能.新增的功能我自己也能用得上,体验上也有巨大的提升.

    有一些其他的组网工具有着极其丰富的功能,而我的设计初衷是让两台装了客户端的机器能够简单快速稳定的通信,因此舍弃了很多功能,甚至用"口令"这种在现代视角看上去不够零信任的方式鉴权.

    80 条回复    2024-04-29 17:52:41 +08:00
    YangMame
        1
    YangMame  
       9 天前
    zephyru
        2
    zephyru  
       9 天前
    这工具看起来蛮实用的,进入 24 年我依赖 CloudFlare Tunnel 的服务经常断链,感觉是个很好的替代
    GeekGao
        3
    GeekGao  
       9 天前
    hanguofu
        4
    hanguofu  
       9 天前
    谢谢分享,请问 CLI: https://github.com/lanthora/candy 能不能运行在 arm64 ( aarch64 ) 的 Ubuntu 22.04 中 ?
    Qetesh
        5
    Qetesh  
       9 天前
    现在使用 xray 配合 wireguard ,wireguard over websockets 。等有空试试楼主这个
    lanthora
        6
    lanthora  
    OP
       9 天前
    @hanguofu 有 aarch64 的 docker 镜像, ubuntu22.04 只编译过 x86 的版本.我感觉在你的环境上编译后是能用的,但没试过
    povsister
        7
    povsister  
       9 天前 via iPhone   ❤️ 1
    感觉这轮子造的有点重复了,xray/v2ray/clash 等工具都可以结合 tun 接口/tproxy 做到以 IP 转发模式完成对等网络配置,两侧网络的连接除了 ws 外,还有非常多的代理协议/transport 可选择
    lanthora
        8
    lanthora  
    OP
       9 天前
    @GeekGao 不错的东西,不过貌似不是一个组网的工具,更像是代理?
    lanthora
        9
    lanthora  
    OP
       9 天前
    @povsister 他们可以把一堆设备放到一个网络下通过 IP 直接相互访问吗,以前没有发现这个功能,给我文档我去看看
    povsister
        10
    povsister  
       9 天前 via iPhone
    @lanthora 可以,上面有关键词,tun (虚拟网卡),或者使用透明代理,本质都是把运行代理软件的这台机器当作网关使用,配置 ok 的话三层基本上就是通的
    GeekGao
        11
    GeekGao  
       9 天前
    @lanthora 可以 Wireguard via wstunnel
    lanthora
        12
    lanthora  
    OP
       9 天前
    @povsister 我很确定我知道什么是 TUN/TAP 也知道透明代理是什么,在这基础之上,还是没有通过 Google 简单的找到组网的方案,看样子他们不适合我
    lanthora
        13
    lanthora  
    OP
       9 天前
    @GeekGao 看看 "背景" 里的最后一句?
    weijancc
        14
    weijancc  
       9 天前
    除了 wireguard 还有别的组网工具, 我目前用的 n2n, 在客户端直接指定 ip, 而不是在服务端.
    Akitora
        15
    Akitora  
       9 天前 via Android
    gost 了解下
    lanthora
        16
    lanthora  
    OP
       9 天前
    @weijancc 这个了解过,确实是个好工具,如果所有设备都在国内的话是个很不错的选择.可惜还是有报文特征明显的问题,不适合跨防火墙
    lanthora
        17
    lanthora  
    OP
       9 天前
    @Akitora 用过 gost, 这也就是 "背景" 里最后一句话的由来.和上面提到的 wstunnel 类似,它们是转发流量,而不能组网,组网还需要依赖其他工具.
    Akitora
        18
    Akitora  
       9 天前
    @lanthora 基于 TCP 的 TUN/TAP 隧道 https://gost.run/tutorials/tuntap/#tcptuntap 这个也不能满足楼主的组网需求吗
    chairuosen
        19
    chairuosen  
       9 天前
    注意隐藏自己的信息
    lanthora
        20
    lanthora  
    OP
       9 天前
    @Akitora 这个链接里面应该可能可以满足我最初的转发流量的需求,也就是这个项目的最初版本.不过现在的实现可以内网穿透 P2P, 举一个实际中已经应用了的场景:两台电脑装好客户端后就可以联机打红警.上面的这个就不满足了
    lanthora
        21
    lanthora  
    OP
       9 天前
    @chairuosen 这是个只能用来组网的工具,应该还不用隐藏自己的信息吧.
    wskymark
        22
    wskymark  
       9 天前
    wireguard 要重启确实麻烦
    echoless
        23
    echoless  
       9 天前 via Android
    @lanthora 隐藏自己信息总没有坏处

    不懂网络 感觉很牛批 准备试试 多谢
    Fish1024
        24
    Fish1024  
       9 天前
    好,收藏。
    wuruxu
        25
    wuruxu  
       9 天前
    @wskymark wireguard 不是有 keepalive 的吗? 我一直也没有遇到 wireguard 断开的情况
    Damn
        26
    Damn  
       9 天前
    在某些情况下 WireGuard 会断线,只有重启客户端才能解决。
    ----------
    比如?
    我国内互联似乎还没遇到过,只遇到过宽带重新拨号导致 IP 变化了,需要更新 endpoint 的 ip:port 。
    frencis107
        27
    frencis107  
       9 天前
    @Damn 国内某些地区,使用 wg 跨运营商连接时,会出现一段时间(一分钟内)后自动断开的问题,只能重启重连解决。ip 没变,keepalive 参数也有设置
    lanthora
        28
    lanthora  
    OP
       9 天前
    @Damn @wuruxu 在两边都开 keepalive 的情况下还是会断,不开 keepalive 更容易断,wg 的 keepalive 貌似只是周期性的发包,不考虑对方会不会回.

    从现象上来说就是我连不会去了,而重启可以解决.国内互联没有遇到过说不定也是防火墙导致的.
    deerpine
        29
    deerpine  
       9 天前 via Android
    试一试
    Damn
        30
    Damn  
       9 天前
    @frencis107 我移动联通跨省互联的,wg 运行在原版 openwrt 上,没有遇到过你描述的情况。
    @lanthora 重启换 ip 没有呢?如果换了,是不是反向墙?有很多帖子提到过。
    lanthora
        31
    lanthora  
    OP
       9 天前
    @Damn 不确定有没有换 IP,不过从出问题的时间间隔上来看像是 NAT 换了 IP. 我已经一年多不用 WG 了,具体情况不是很清楚
    wuruxu
        32
    wuruxu  
       9 天前
    @lanthora 是的 wireguard keepalive 是单向的,只是用来标记 Peer 是否还活着
    国内七八台 openwrt 路由器组成一个 wireguard group, 这两年用下来也还正常
    跨国的 wireguard 一般都是 节点丢包率太高了,一般只要没有丢包,都挺正常的
    等你的包移植到 openwrt 上,我也去试试
    coffeesun
        33
    coffeesun  
       9 天前 via Android
    我不太懂网络,意思是可以替换掉我 zerotier 组网,并可以使组成的局域网设备通过国外的机子转发流量并翻墙么?这个能长期稳定如 v2ray 么
    andytao
        34
    andytao  
       9 天前
    @GeekGao 感谢楼主分享,袋鼠数据库工具 准备把隧道支持从 ssh/plink(PuTTY) 替换为 wstunnel 。
    wuruxu
        35
    wuruxu  
       9 天前
    @Damn 路由器重启 换了 ip , 这个目前有什么好的办法吗?
    目前我就是通过 ddns 上报新的公网 IP ,然后在其他 Peer 上,定时去 set wireguard 的 peer 域名地址,一般需要 10 分钟才可以恢复
    lanthora
        36
    lanthora  
    OP
       9 天前   ❤️ 1
    @coffeesun

    > 替换掉我 zerotier 组网

    理论上可以替换,但是如果你现在 zerotier 用着很爽,完全没有换的必要.

    > 使组成的局域网设备通过国外的机子转发流量并翻墙

    不能,没有翻墙的功能.
    Damn
        37
    Damn  
       9 天前
    @wuruxu 你是有机器没有 ipv6 且 v4 在 nat 后面么?
    如果各 peer 都有公网 ip 并配置独立的二级域名的话,除非同时换 ip 了,不然重启或者重拨都会触发解析 ip 地址这个动作,然后可以成功连接的。
    nat 后面的话原版 wg 似乎确实没什么高效的解决方法,可以选择各种修改版。
    Damn
        38
    Damn  
       9 天前
    @wuruxu 我刚刚试了一下手动重拨远端的 pppoe ,大约 10s 就恢复了。
    blankmiss
        39
    blankmiss  
       9 天前
    用 tailscale 不就行了
    KanVivii
        40
    KanVivii  
       9 天前
    哈喽 方便给个联系方式嘛!
    有个 SD-WAN 类似的项目想一起合作一下
    lanthora
        41
    lanthora  
    OP
       9 天前 via iPhone
    @KanVivii github 上有邮箱,邮件联系吧
    lanthora
        42
    lanthora  
    OP
       9 天前 via iPhone
    @blankmiss 有没有一种可能, tailscale 底层用的是 wg, 对我来说这个协议不可用

    补充: 换端口或者其他服务是正常的,显然被针对的是 wg
    s82kd92l
        43
    s82kd92l  
       9 天前
    最近一直在找有没有利用 stun/ice 完成 udp duplex 传输的工具,就是只负责包转发,不负责上层的加密/tun/路由。找到好多项目都是基于 webrtc 的 datachannel, 其基于 sctp over udp ,很重且不稳定。

    看到楼主的实现也是基于 stun 的,要不考虑加上这个功能?
    amrice
        44
    amrice  
       9 天前 via Android
    怎么都在说 wireguard ,没人用 tailscale 吗?我感觉很好用
    Archeb
        45
    Archeb  
       9 天前
    同时支持对等连接和 C/S 架构来组网的 SDWAN ,使用常用的互联网协议进行通信,足够简洁的配置和够用的安全系数。

    非常棒的思路,这正是我一直在寻找的东西。在此之前 tailscale 的 DERP 勉强可以符合我的需求(毕竟 DERP 协议也是走的 HTTP ,在大部分网络环境下可以正常使用),但 derper 的实现并不是太稳定。

    目前有点懒癌发作,等未来这个项目更完善了的时候顺便一波换了。
    uncat
        46
    uncat  
       9 天前
    @wuruxu 路由器重启导致:

    1. 导致重新拨号,所以换了 IP
    2. 路由器上的 WireGuard 也被重启,导致动态的 Endpoint 信息丢失

    解决思路:

    将 WireGuard 运行到非路由器的设备上,然后开启 WireGuard 所有 Peer 的 Keepalive ,路由器重启但 WireGuard 不重启即可。WireGuard 会根据最后一次成功收包时 Peer 的来源信息,作为发包的目的地址( Endpoint 地址,首次连接可以指定,后续会被动态更新),这个信息就是 NAT 后设备对应的 NAT 记录(即 NAT 的公网 IP 和端口),本地的 WireGuard 将通过动态 Endpoint 地址,主动连接 NAT 后的设备,NAT 后的设备收到数据包,也会主动更新 Endpoint 地址的。
    uncat
        47
    uncat  
       9 天前
    WireGuard 会动态更新 Endpoint 的地址为该 Peer 最后一次收到的有效的数据包的来源地址。

    假设你有公网 IP 且通过 DDNS 将公网 IP 通过域名进行实时更新,域名更新有延迟,所以这里面就可以利用 WireGuard 的这个特性了。

    当有公网 IP 的 WireGuard 节点地址变化时,由于这个公网节点会主动的发送保活的空数据包( Keepalive )给所有对端节点,对端节点收到包后会根据数据包的来源 IP 更新 Endpoint 地址(这个地址将作为回包的目的地址),所以即使 IP 变化,通信也不会中断。
    lanthora
        48
    lanthora  
    OP
       8 天前 via iPhone
    @s82kd92l 不考虑,除非真的有利于组网(更低的延迟或者更好的稳定性),否则就不加功能,代码越少越不容易出 BUG 。那些能配合其他工具实现的功能都不考虑
    wuruxu
        49
    wuruxu  
       8 天前
    @uncat 你这个想法,也挺好,就相当加一个 firewall rule 和一个单独的 wg 设备
    wuruxu
        50
    wuruxu  
       8 天前
    @Damn 我的 wg 在 openwrt 上,有 ipv6 和 ipv4 公网地址的
    wuruxu
        51
    wuruxu  
       8 天前
    @uncat 其实只要把上一次的 wireguard peer 信息 cache 起来,下次重启 restore 回来,也没有问题的
    maybeonly
        52
    maybeonly  
       8 天前   ❤️ 1
    @lanthora @Damn
    > 在某些情况下 WireGuard 会断线,只有重启客户端才能解决
    这是因为防火墙或者 nat 造成的。因为 wireguard 不会改变 udp 的源端口。
    同时目的 ip 和端口也不会变,这就会导致,对应的失效 nat 表项一直不会超时。
    对于自家路由器 ip 变化的情况,可以在路由器更换 ip 的时候清理出口的 conntrack 表得到解决。

    但是这也是权衡利弊的结果。只有依赖这样的固定端口 udp ,才能组成“网状网络”而非“一个一个的连接”

    其实跨国的话试试看 wireguard over ipv6 吧,感觉根本没人管啊。
    作为后备方案,可以考虑 openvpn tcp over xray/hysteria ,不要嫌弃 openvpn 重,人家原生支持 tcp ,而且组网功能完善。
    wuruxu
        53
    wuruxu  
       8 天前
    @maybeonly 是的,测试下来,wireguard over ipv6 还是很稳的
    wuruxu
        54
    wuruxu  
       8 天前
    @maybeonly 清理出口的 conntrack 表 这个怎么清理,有什么命令吗?
    maybeonly
        55
    maybeonly  
       8 天前
    @wuruxu
    conntrack -F conntrack
    小心网络波动/中断
    lanthora
        56
    lanthora  
    OP
       8 天前
    @maybeonly

    > 其实跨国的话试试看 wireguard over ipv6 吧,感觉根本没人管啊

    并非所有 VPS 都有 IPv6 地址.不太清楚有没有人管,不过现在确实有一些人即使用 IPv4 也能正常用.

    > VPN over Proxy 的方案是能用的,但是不喜欢那么复杂,单单因为重这一条就被我抛弃了.还得是自己用的爽才行
    uncat
        57
    uncat  
       8 天前
    @lanthora

    > 并非所有 VPS 都有 IPv6 地址.不太清楚有没有人管,不过现在确实有一些人即使用 IPv4 也能正常用.

    我就是长期 IPv4 WireGuard 用户。跟你场景很像,一台公网服务器作为中转,实际的所有流量和负载都在个人局域网的物理服务器上。

    > 局域网对等连接

    如果两个端都在 Symmetric NAT 后呢?也可以对等连接么?
    lanthora
        58
    lanthora  
    OP
       8 天前
    @uncat

    > 如果两个端都在 Symmetric NAT 后呢?也可以对等连接么?

    如果两个机器能通过某个局域网 IP 通的话就可以(至少能单向访问).这个功能跟 NAT 类型没有关系,也不会用到公网的任何信息.如果是两个不同 NAT 下的就不可以了
    uncat
        59
    uncat  
       8 天前
    @lanthora

    > 如果两个机器能通过某个局域网 IP 通的话就可以(至少能单向访问).这个功能跟 NAT 类型没有关系,也不会用到公网的任何信息.如果是两个不同 NAT 下的就不可以了

    明白了你的意思了,如果两个端都在同一个局域网内,基于局域网而不是绕行公网进行通信的意思。
    wacke
        60
    wacke  
       8 天前
    个人目前使用混淆版 wireguard ,也从 compat 版 port 到了 mainline ,3 年了吧,除了链路本身的波动外,基本没有不稳定的情况。。。。用户态的程序,效能还是弱了些。。。
    https://github.com/el3xyz/wireguard-linux-compat
    isSamle
        61
    isSamle  
       8 天前
    已 Start ,能不能出个带图的操作说明文档
    juzisang
        62
    juzisang  
       8 天前
    这个 P2P 是走的 UDP 吗?国内 UDP 带宽一大就会触发 QoS ,目前市面上 P2P 组网工具貌似都是走的 UDP 。
    hxse
        63
    hxse  
       8 天前
    为什么服务端不能支持 wss 协议? 抗审查效果怎么样? 小白不懂求教
    lanthora
        64
    lanthora  
    OP
       8 天前
    @juzisang 是 UDP,因为 TCP 打洞几乎不可能成功,
    wangsijie
        65
    wangsijie  
       8 天前
    有对抗 GFW 吗
    lanthora
        66
    lanthora  
    OP
       8 天前
    @hxse 加密交给外层的 web 服务就可以了,服务端没必要实现这个功能.从原理上用了比较广泛使用的 https,并且 p2p 的 udp 流量应该没有任何特征,这个项目从我做出来到现在用着还可以,效果需要用的人多了才能看出来.

    也希望有大佬来尝试识别出这东西的流量
    lanthora
        67
    lanthora  
    OP
       8 天前
    @isSamle 我没有提供带图操作的计划,在不同环境需要不同的操作,这个工作量太大了,我没有能力穷举出所有可能的用法.

    根据提得 issue, 我会尽可能的让文字版的文档清晰,我自己是意识不到哪些地方需要做提醒的.
    hikarikongou
        68
    hikarikongou  
       8 天前
    TCP over TCP 在拥塞网络上的性能会比较难看。
    lanthora
        69
    lanthora  
    OP
       8 天前   ❤️ 1
    @hikarikongou UDP 在 Qos 的时候也会很难看,所以除了 TCP 和 UDP 您还有什么好的建议吗
    RangerWolf
        70
    RangerWolf  
       8 天前
    歪个楼,从“联机打红警” 我猜楼主应该 80 后
    lanthora
        71
    lanthora  
    OP
       8 天前
    @RangerWolf 你猜错了,我三年级玩红警的(虽然现在依旧很菜),不是 80 后
    cnbatch
        72
    cnbatch  
       8 天前
    有个网络小白一直在我的项目内纠缠“套壳建 WireGuard 隧道”,很想把他转给 OP
    /t/1034681
    告诉他是网络小白,12 个小时前他开骂了,还把之前的部份 comment 删掉,哈哈哈哈
    lhtdeg
        73
    lhtdeg  
       8 天前
    已 star ,等我的 tailscale 不能用的时候我就换
    sunnysab
        74
    sunnysab  
       7 天前
    “有时候两个客户端之间无法直连,但它们都能与另一个客户端直连.此时可以以这个客户端作为中继相互访问.” 这是我最想要的一个功能!
    lanthora
        75
    lanthora  
    OP
       7 天前 via iPhone
    @sunnysab 我在 demo 环境里放了一个中继的客户端,有公网地址和端口,服务器在枣庄的数据中心,可以试试效果
    lanthora
        76
    lanthora  
    OP
       6 天前
    @cnbatch 这个人也去我项目下面开 issue 了,一开始还以为只是一个不太了解的用户,后面感觉不太对劲,虽然你的帖子没有暴露这个人的 id, 但是我发现这个人再各个项目里提得 issue 数量是能对上的,离谱
    RangerWolf
        77
    RangerWolf  
       6 天前
    @lanthora 厉害了!三年级我们还在玩泥巴
    cnbatch
        78
    cnbatch  
       6 天前
    @lanthora 没错,就是他。越是帮他,他接下来越会继续提更多 issue

    要是没帮他的情况下继续提更多 issue ,那得看着办了

    我那帖子里面 Ipsum 的评论:直接摆烂
    个人认为这是最佳应对措施
    hikarikongou
        79
    hikarikongou  
       5 天前
    @lanthora UDP 虽然丢包的时候难看,但丢包并不影响整个隧道的运行。TCP 遇到丢包保证可靠传输的时候会引入慢启动和流量控制,引发巨大的延迟。参见
    https://www.inventio.co.uk/Ideas/Why%20TCP%20Over%20TCP%20Is%20A%20Bad%20Idea.pdf

    UDP 加 FEC 其实是一个比较便利的方案。
    lanthora
        80
    lanthora  
    OP
       5 天前
    @hikarikongou 选 wss 是为了过防火墙, p2p 用普通的 udp. 为这种弱网络环境引入对于正常网络环境来说冗余的代码没有价值.而且如果真的出现了和服务器之间丢包的情况,用正常的 tcp 做拥塞控制减少流量是合理的.如果真的那么在意延迟就不要把服务器部署到容易丢包的地方.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   740 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 21:12 · PVG 05:12 · LAX 14:12 · JFK 17:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.