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

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

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

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 和利用网络中的其他客户端做中继的功能.新增的功能我自己也能用得上,体验上也有巨大的提升.

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

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

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

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

> 替换掉我 zerotier 组网

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

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

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

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

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

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

目前有点懒癌发作,等未来这个项目更完善了的时候顺便一波换了。
uncat
    46
uncat  
   48 天前
@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  
   48 天前
WireGuard 会动态更新 Endpoint 的地址为该 Peer 最后一次收到的有效的数据包的来源地址。

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

当有公网 IP 的 WireGuard 节点地址变化时,由于这个公网节点会主动的发送保活的空数据包( Keepalive )给所有对端节点,对端节点收到包后会根据数据包的来源 IP 更新 Endpoint 地址(这个地址将作为回包的目的地址),所以即使 IP 变化,通信也不会中断。
lanthora
    48
lanthora  
OP
   48 天前 via iPhone
@s82kd92l 不考虑,除非真的有利于组网(更低的延迟或者更好的稳定性),否则就不加功能,代码越少越不容易出 BUG 。那些能配合其他工具实现的功能都不考虑
wuruxu
    49
wuruxu  
   48 天前
@uncat 你这个想法,也挺好,就相当加一个 firewall rule 和一个单独的 wg 设备
wuruxu
    50
wuruxu  
   48 天前
@Damn 我的 wg 在 openwrt 上,有 ipv6 和 ipv4 公网地址的
wuruxu
    51
wuruxu  
   48 天前
@uncat 其实只要把上一次的 wireguard peer 信息 cache 起来,下次重启 restore 回来,也没有问题的
maybeonly
    52
maybeonly  
   48 天前   ❤️ 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  
   48 天前
@maybeonly 是的,测试下来,wireguard over ipv6 还是很稳的
wuruxu
    54
wuruxu  
   48 天前
@maybeonly 清理出口的 conntrack 表 这个怎么清理,有什么命令吗?
maybeonly
    55
maybeonly  
   48 天前
@wuruxu
conntrack -F conntrack
小心网络波动/中断
lanthora
    56
lanthora  
OP
   48 天前
@maybeonly

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

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

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

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

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

> 局域网对等连接

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

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

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

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

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

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

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

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

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

UDP 加 FEC 其实是一个比较便利的方案。
lanthora
    80
lanthora  
OP
   45 天前
@hikarikongou 选 wss 是为了过防火墙, p2p 用普通的 udp. 为这种弱网络环境引入对于正常网络环境来说冗余的代码没有价值.而且如果真的出现了和服务器之间丢包的情况,用正常的 tcp 做拥塞控制减少流量是合理的.如果真的那么在意延迟就不要把服务器部署到容易丢包的地方.
hikarikongou
    81
hikarikongou  
   35 天前
@lanthora 问题是 TCP 强制性的保序会干扰隧道中实时流量(比如 UDP 承载的 RTP )的正常传输,况且中国互联网出口是有普遍性的拥塞的,QoS 等级和丢包比率是没办法控制的。伪装过墙不如考虑假 WSS 握手后 faketcp 的方案。
lanthora
    82
lanthora  
OP
   34 天前
@hikarikongou 最终都是各种取舍的结果罢了.去实现 "假 WSS 握手后 faketcp" 的方案是需要时间代价的,同时对我来说没有可以感知到的收益,这种代价不能接受,更不用说按照你说的这个方案做了以后就没法把服务端当成一个普通 Web 服务导致的各种问题.比如没法套一层 cloudflare 了.当它还是个普通 Web 应用的时候,可以很低代价的增强服务端的功能.
rebecca554owen
    83
rebecca554owen  
   3 天前
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2873 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 28ms · UTC 14:15 · PVG 22:15 · LAX 07:15 · JFK 10:15
Developed with CodeLauncher
♥ Do have faith in what you're doing.