使用 wireguard ,分别在 A 与 B 作为 Peer 相互通信,并将 A 机器的 default_route 设置为 wg 网口,拓扑如下,其中 A 、B 均为 Openwrt
| Internet(v6) |
[ A: gateway ] | | [ B: Server ]
| |
(wg0) <-----> (ens1_100M) < - - - - > (ens1_1G) <----> (wg0)
在不考虑 Internet 带宽下(假设 Internet 速率为 1G ,B 的接口速率亦为 1G ),由于 A 的接口速率只有 100m ,这种方案可以实现 100m 的数据传输。 目前方案存在的问题: Gateway 提供了有 4 个 100M 的网口(有着不一样的四个公网 iPv6 地址),按照以上方案只能利用一个网口进行对外通信,也就是仅能提供 100M 的带宽,剩下 3 个 100M 的网口无法充分发挥作用。如何在一台配置不高(成本、物理空间有限)的设备上实现充分利用剩下 3 个 100M 的网口达到 400M 的上网冲浪速率? 感觉应该不需要考虑应用粘滞、各种应用会在两个宽带上面来回跳的问题,因为最终出到互联网全部都是以 B 的 ip 作为出口 ip ,所以不会出现说一个 app 发出通信对端服务器收到两个 incoming ip 的问题。
在 A 机器上部署多个 wg 网口,每个网口的 peer 都指向 B 机器,拓扑如下图 目前存在的问题是wg 似乎会从默认网口进行出口,这就导致了所有 wg client 全都只会从一个网口出站,搜寻一下互联网发现这篇文章 How do I configure a Wireguard Interface to connect to a remote peer through a specific network interface? ,采用的是 IP 路由表分流的方案,这篇文章可以解决 B 机器有多 IP 的分流。但是在本情景下,由于 B 机器只有一个 IP ,无法采用这种方案
| Internet |
[ A: gateway ] | | [ B: Server ]
| |
(wg0) <-----> (ens1_100M) < - - - - > (ens1_1G) <----> (wg0)
| / / |
| / / |
(wg1) <-----> (ens2_100M) < - / |
· | / |
· (省略若干 wg)| | |
· | / |
(wg3) <-----> (ens3_100M) < - |
虚拟机方案,将 4 个网口分别虚拟 4 个 openwrt 分别架设 wg client ,再虚拟一个路由系统做负载均衡,缺点是性能开销大而且可能有性能损失
来问问大佬们有没有什么低成本方法可以解决这个问题 谢谢大家喵
1
vcn8yjOogEL 250 天前
可以给 WG 出站包打标签, 然后再按标签走不同的路由表
|
2
pagxir 249 天前 via Android
要么走二层的链路集合比如 bond ,要么用 mptcp
|
3
maybeonly 249 天前
用单个 wg 的话
给自己发 4 个配置文件,然后起 4 个 wg 隧道 假如四个 wg 客户端 ip 分别是 198.51.100.1-198.51.100.4 ,接口分别是 wg1-wg4 那么可以加路由 ip r a default dev wg1 table 1001 ... ip r a default dev wg4 table 1004 然后加规则 ip ru a f 198.51.100.1 table 1001 ... ip ru a f 198.51.100.4 table 1004 然后加出口 nat 规则(可能需要适当调整一下,比如结合默认路由的 srcip ) iptables -t nat -A POSTROUTING -m statistic --mode random --probability 0.25 -j SNAT --to 198.51.100.1 iptables -t nat -A POSTROUTING -m statistic --mode random --probability 0.33 -j SNAT --to 198.51.100.2 iptables -t nat -A POSTROUTING -m statistic --mode random --probability 0.5 -j SNAT --to 198.51.100.3 iptables -t nat -A POSTROUTING -j SNAT --to 198.51.100.4 然后就可以把不同的连接丢到不同的 wg 上了…… 必要时调整 rp_fillter 。 如果用多个 wg ,或者其他 vpn ,可以考虑类似 ecmp 的实现,或者分别随机打标签…… 单个 wg 不能这么做是因为客户端地址是同一个的话,wg 这种三层 vpn 没办法路由到不同的客户端去。 |
4
gregy 249 天前 1
OP 这个需求和户外直播使用的多卡聚合的功能类似,使用一台聚合服务来实现多条公网链路的聚合打到带宽叠加,故障冗余的效果。
https://www.openmptcprouter.com/ B 端的服务器可以直接运作聚合服务,不需要额外的聚合服务器了。不过这个并不能达到 1+1=2 的效果,最多也就是 1+1=1.7 |
5
MFWT 249 天前
为 OP 的提问方式先点个赞,清晰明了
我贡献一下我自己之前的一个研究吧,就是我手头的机器还是比较富裕的时候 当时我手头有两台香港良心云的轻量,内网互通,单机上行(出站) 30Mbps 我当时做的一个实验是: 1. A 机安装 SS ,B 机不装 2. B 机做一个端口转发,**通过内网地址**,转发到 A 机的 SS 服务 3. 我这边用 v2 做一个客户端,用他的负载均衡(其实就是轮询各个服务器,顺序发包)建立连接,分别填上两台服务器的地址 4. 去 speedtest 测速,多线程模式,测出来 60Mbps ( 30+30 ) 要点是: 1. SS 的特性是:无连接。换句话说只要数据包到了(当然要满足校验规则什么的)就能直接建立连接,可以看作是 state-less 的代理服务 2. 多线程测速就保证了『产生多个 HTTP 连接』,这样客户端就可以轮流给两个服务器上强度,实现均衡的效果 3. 最后流量还是走内网聚合(保证延迟低,以及稳定)到一台机器上,走一个机器的出口,这就是 OP 提到的『 IP 不乱跳』 4. 类似 SS 这样的四层代理,是把数据『抠』出来再处理的,在实操中比直接搞三层流量要方便些 以上应该可以作为参考 |
6
Kinnice 249 天前 1
启动个 clash-meta (可配置出口网口),配置四个 DIRECT 分别走四个 wg 网口,然后这个策略组使用 loadblance 就可以了
为什么不直接在 clash 里面配置 wg? => 效率低,慢 |
7
yyy134341 OP @Kinnice #6 确实可以利用 clash 去做 load-balance ,但是问题出在 wg 出口。 理想情况下 4 个 WG client 应该沿着 4 个 WAN 口出站,即 wg1 -> wan1 -> serverB, wg2 -> wan2 -> serverB, 以此类推,但是我在问题描述的时候提过,「 wg 似乎会从默认网口进行出口」,也就是说所有 wg client (wg1,wg2,wg3,wg4) 全部都会走默认网口出站(比如 wan1 ),所以即使 load-balance 到四个 wg 网口去,由于四个 wg 网口最终都只使用 wan1 出站,所以最终只能够实现 100m 的数据传输
|
8
yyy134341 OP 我先梳理一下上面各层大佬提出的 solution ,有好多技术我还是第一次接触到、、如果有什么没弄懂的还烦请各位帮忙解答、、感谢各位大佬 :)
|
9
yyy134341 OP @MFWT #5 我和你的 case 似乎不太一样,应该是刚好反过来,你的是在本地端拥有 1 个 IP 地址,远端有多个 IP 地址;我的是在本地端有多个 IP 地址,需要连接同一个远端服务器 IP 并将请求平均分配到本地的数个 IP 进行出口,其实有点像多宽带聚合的场景。只不过在我的场景是一个环境更复杂的多宽带分流( iPv6 + 4in6 )
你的实验也挺有趣的,但是我对这个实验发现有个问题,我理解的实验设计如下面拓扑所示, ``` PC ----> serverA (proxy server) --> speedtest.net \ ^ | | port forward \ | --> serverB -- ``` 最终发送到互联网请求连接的是 serverA ,那这样子的话最终访问互联网的速度应该仍然受限于 serverA <----> speedtest.net 的 30Mbps 限制才对啊,为什么可以跑得到 60Mbps 呢 |
10
yyy134341 OP @MFWT #5
原来回复不支持 Markdown 的么、、 那我换成文字版 PC -------> ServerA (proxy server) -----链路 a-----> speedtest.net PC -------> ServerB --- Port forward ---> ServerA -----链路 a---> speediest.net 也就是说最终 serverA 都是使用同一个方式进行对 speedtest 进行访问(也就是 proxy server 发出请求),为什么这种方式可以实现绕过 30Mbps 的作用呢? |
11
Kinnice 248 天前 1
@yyy134341 #7
1. B 机器看起来应该是可以搞到多个 ipv6 地址的(一般国内 ipv6 给的还是富足的),然后 A 机器就可以设置路由让指定的目的 ip 走指定网口(very Easy), 接着就可以了 2. A 机器如果性能还不错,可以试试直接 clash 上面配置 wg 和出口网口,全在 clash 里面做,但是缺点可能是性能不太高。(或许可以换一个协议比如 ss/vless 之类的) |
12
MFWT 248 天前
@yyy134341
首先需要明白一个点(其实我描述中也漏了一点):我提到的测试中的速度,实际上是『下行速度』,其具体实现是:浏览器请求一个文件,并统计接收该文件的速度。换句话说,实际上测试下行速度的时候,流量的流向是: Speedtest 服务器 =( 1 )=> 良心云服务器 =( 2 )=> 我的客户机 良心云的限速 30Mbps ,其实是限制出站方向 30Mbps ,对于入站方向则限制不大(至少大于等于 100Mbps ),也就是说,1 号段相当于是没有限速,2 号段本来应该是 30Mbps 的,但是因为两台机器分开了多个请求的流量,所以可以叠加加速 |
13
MFWT 248 天前
@yyy134341
其实你的 case 和我的本质上还是一样的,主要就是谁主动连接谁的问题 这其实就是流量聚合的一个难点:以目前网络中比较常用的 TCP 协议为例,如果不是对端配合,他『并不能』在实现多路径传输(不然就不会有 MPTCP 之类的玩意出现了),在这个情况下,链路聚合能体现加速的一般就以下几个场景: 1. 多个 TCP 同时使用(比如说,多机使用,多线程下载) 2. 多用户从不同链路进来 所以这也就是我提到,为什么是 SS:像是 SS 这种代理协议和 VPN 不同,他提前终结了 TCP ,只是拿着数据跑来跑去,这就比 VPN 那种单纯的三层路由要好得多。我可能描述得不太准确,但大概就是这个意思 |
14
MFWT 248 天前
@yyy134341
就目前而言,据我所知,WireGuard 的官方版本并没有实现指定出口的功能,而且对于对等点的认证也没有想象中的那么快捷(至少如果某个 Peer 有新的对端地址(此处地址指代『地址:端口 二元组』,下同)连入,那么原先的连接似乎会被放弃,也就是说两个接口会不停地等到超时之后重新握手,也就是说可能是同时也就一条链路被用上) 我有个稍微显得 dirty 的解决方法,同样是类似于『把数据抠出来』的思路,这就需要双方配合: 1. 你的 B 机上面,安装 gost (或者其他 UDP 端口转发软件,不能是 iptables 的 REDIRECT ,必须是不保留源地址的转发工具),监听一个端口,并把数据转发到 WG 的监听端口 2. 你的 A 机上面,用 gost 监听某个端口,配合虚拟节点功能(或者选择其他有负载均衡功能的 UDP 端口转发软件),注意指定不同出口,但是填一样的地址(就是刚刚 B 机 gost 监听那个端口)实现负载均衡功能 3. 你的 A 机的 WG ,指定对端地址为你本机的 GOST 画图就是: A 机 WG -------> A 机 GOST -----(多网卡出线)-----> B 机 GOST ----> B 机 WG 核心思想还是:保持两端 WG 所看到的对端地址不变(都是 127.0.0.1 + 固定端口),然后中间偷梁换柱 |
15
yyy134341 OP @Kinnice #11
1. 这个是个好思路,确实可以试试实现看看 2. Openwrt 里面有支持多网卡分流的 Clash 插件吗,在用的 OpenClash 好像不支持通过 interface-name 绑定多网卡 [Openclash 开启后多线多拨下行速度无法叠加]( https://github.com/vernesong/OpenClash/issues/301) |