将一台腾讯云轻量和一台瓦工中, 通过 mimic 传输进行 WireGuard 组网
原来我是用 Phantun 的, 前两天听一个群友在研究这个, 也想玩一下
2026-09-27 更新
把 p330 改成了: wg直连腾讯云+ wg + mimic 连瓦工,顺带再研究一下上次没挖到底的 MTU 坑
2026-09-26 更新
把家里的 p330 也接进来了
拓扑与地址规划
| 项目 | 腾讯云 | 瓦工 | 本地 p330 |
|---|---|---|---|
| 系统 | Debian 13 (trixie), kernel 6.12.107 | Debian 13 (trixie), kernel 6.12.107 | Debian 13 (trixie), kernel 6.12.107 |
| 虚拟化 | KVM / virtio_net | KVM | 物理机 / Intel e1000e |
| 网卡可见地址 | 10.0.X.X/22(NAT 后) | 真实公网地址 | 家宽内网地址(PPPoE, 外层 MTU 1492) |
| WireGuard 地址 | 192.168.X.1/24(wg0)+ 192.168.X.1/32(wg1) | 192.168.X.2/24 | 192.168.X.3/32(两条隧道共用) |
| 监听端口 | 51820(mimic)+ 51821(直连) | 51820 | 51820(mimic 到瓦工)+ 51821(直连腾讯云) |
| mimic 过滤条件 | local=腾讯云内网IP:51820 | local=真实公网地址:51820 | remote=瓦工IP:51820 |
配置
/etc/wireguard/wg0.conf
腾讯云
| |
瓦工
| |
/etc/mimic/eth0.conf
腾讯云
| |
瓦工
| |
nftables
腾讯云 — /etc/nftables.conf
| |
瓦工 — 这台机器是老机器, 所以追加这几行就好了
| |
踩到的坑
mimic 配置文件的 filter 只接受一个 origin
GitHub master 分支的 man page 写的是 {origin}={ip}:{port},并举例可追加覆盖项,容易让人以为能写:
| |
实际 0.7.0 会直接拒绝:
| |
逗号后面只能跟 padding / handshake / keepalive 这类覆盖项,不能跟第二个 origin。
| |
NAT
腾讯云的 mimic 过滤器必须写内网地址,而不是 鹅提供的EIP。因为 eBPF 挂在 TC/XDP 上,看到的是 NAT 转换前的包。
MTU黑洞
mimic 官方文档推荐的隧道 MTU 是 1408,但在本环境中 100% 丢包。实测最大可用值为 1392,最终采用了个 1380, 我到现在还没彻底明白这个坑是怎么来的
mimic 文档给出的算法是"在 WireGuard MTU 基础上减 12":以太网 1500 → WireGuard 1420 → mimic 1408。按此配置后现象是:
- 小包正常:ping 通、TCP 三次握手成功
- 大包全丢:iperf3 显示
0.00 Bytes、大量重传,随后Connection refused - 典型 MTU 黑洞(PMTUD 失效)特征
实测 DF 位探测(内层 IP 包大小 vs 连通性):
| 内层 IP 包 | 结果 |
|---|---|
| 1380 | 通 |
| 1392 | 通 |
| 1393 | 不通 |
| 1400 / 1408 | 不通 |
最大可用内层 MTU = 1392。最终取 1380,留 12 字节安全余量(防 mimic 在特定情况下追加 TCP 选项导致外层包变大)。
排除掉的其它可能性:
- 公网基线路径 MTU 实测为 1500(
ping -M do -s 1472成功),排除腾讯云 overlay 封装 - 切换 XDP 模式无改善,排除 eBPF 处理问题
- 双向均验证(瓦工→腾讯云在 MTU 1380 下大包也全通)
推测原因为 mimic 生成的 TCP 报文头带选项(时间戳/SACK/窗口缩放等),使外层 TCP 头达到约 40+ 字节而非 20 字节,实际每包开销约 108 字节而非文档所述的 74 字节,故上限落在 1392 而非 1416。
XDP native 模式在 virtio_net 上触发连接中断
腾讯云是 KVM + virtio_net 网卡。mimic 以默认的 native 模式挂载 XDP 的瞬间,当前 SSH 会话被 RST(kex_exchange_identification: read: Connection reset by peer),但 ICMP 与重建连接均正常。
这与文档中提示的 issue #11 现象一致——部分宿主机阻断 guest 的 virtio_net native XDP。按文档建议改用:
| |
由于腾讯云出口带宽只有 6 Mbps,skb 模式相对 native 的性能损失(generic XDP 走 skb 路径)完全无关紧要*
max_window 显著降低重传
mimic 伪造的 TCP 默认窗口约 13 KB。腾讯云↔瓦工 的 RTT 是 130 ms,13 KB / 130 ms ≈ 0.8 Mbps,在高 RTT 链路上窗口会成为瓶颈并引发大量重传。
开启后(两端都要开):
| |
重传次数实测从 1525 降到 102(同样 6 Mbps 饱和链路、6~8 秒测试)。抓包可见窗口变为 win 65535。
防火墙必须同时放行 TCP 和 UDP
mimic 的透明改写发生在 eBPF 层,netfilter 在不同方向看到的东西不一样:
| 观测点 | 看到的协议 |
|---|---|
| 出口方向(TC 在 netfilter OUTPUT 之后执行) | UDP |
| 入口方向(XDP 在 netfilter INPUT 之前执行,已还原) | UDP |
| 链路中间的真实抓包 | TCP(出口) |
所以规则必须TCP/UDP都写
| |
实测抓包证据(腾讯云的 eth0):
| |
验证结果
连通性
| |
mimic 效果
腾讯云的 mimic show -c eth0:
| |
抓包证明出口全部为 TCP、UDP 捕获数为 0:
| |
把家里的机器也接进来
前几天把家里的 p330 也接进了这个网, 分配 192.168.X.3。
| 腾讯云 | 瓦工 | 本地 p330 | |
|---|---|---|---|
| 角色 | hub | 海外hub | 家用服务器 |
| 网络位置 | 公网 EIP, 网卡上是内网地址 | 真实公网 IP | 家宽 NAT 后, PPPoE |
| 网卡 | virtio_net | — | Intel e1000e (其实还插了个82599ES, 但是这块卡不用来走这条路线) |
| XDP 模式 | skb | skb | skb |
| mimic filter | local= 本机地址 | local= 本机地址 | remote= 对端地址 |
p330 侧
/etc/wireguard/wg0.conf
| |
/etc/mimic/eno1.conf
| |
p330 的地址是 DHCP 分的, 一旦 DHCP 换了地址, mimic 就匹配不上任何包, 所以客户端这边按对端匹配:
man page 里 stale 参数的说明也是围绕 remote filter 描述"客户端本地端口变化"的场景, 算是官方暗示了这种用法。
但是话又说回来了, 家里到腾讯云感觉直接跑wg就行了……一共6M带宽, 运营商也 QoS 不到哪里去
这次 p330 是物理机, Intel e1000e, 正好也在 mimic 文档点名的那份"原生 XDP 可能不稳定"的驱动列表里 (e1000/e1000e/igb/igc)。
所以直接写 xdp_mode = skb, 生效后 ip link show eno1 能看到 xdpgeneric:
| |
腾讯云侧
之前在腾讯云的 filter 写的是
| |
它匹配的是"本机地址 + 端口", 跟对端是谁无关 —— 所以加第二个 peer 时, 这条 filter 天然就覆盖了新连接, 一行都不用动。
mimic show -c eth0 也确实直接变成两条:
| |
WireGuard 那边暂时用 live 的方式加 peer, 不重启接口,家宽后也没有什么 Endpoint 好写:
| |
瓦工侧
要让 p330 能访问瓦工, 得把瓦工上"腾讯云"这个 peer 的 AllowedIPs 从 /32 放宽:
| |
/32 会同时卡住两件事: 不放行源地址是 .3 的包, 也不把去 .3 的回程路由进隧道
MTU 测试
上次在这条 腾讯云↔瓦工 链路上测出来的最大内层 MTU 是 1392, 当时还推测了一通"mimic 的 TCP 头带选项"云云。这次在 p330 这条链路上重新做 DF 位探测, 结果对不上。
先测外层路径本身 (直接 ping EIP, 不经隧道):
| 外层 IP 包 | 结果 |
|---|---|
| 1492 | 通 |
| 1493 | 不通 |
家宽是 PPPoE, 外层 MTU 是 1492 而不是 1500。
再临时把 p330 的 wg0 MTU 调大, 在隧道内测:
| 内层 IP 包 | 结果 |
|---|---|
| 1424 | 通 |
| 1425 | 不通 |
有个细节我还没完全想明白: 外层 1492 − 内层 1424 = 68 字节开销。按"mimic +12、TCP 头 20、IP 头 20"算是 52, 对不上, 中间差 16。大概率是 WireGuard 自己按 16 字节对齐 padding、或者 mimic 那个 fragment 的排布在起作用。
最终仍然用 1380, 没有跟着调到 1424。 原因是 wg0 的 MTU 是 per-interface 的, 一个接口上所有 peer 共用一个值 —— 腾讯云那边 wg0 已经是 1380, 而且 腾讯云↔瓦工 那条链路的上限本来就是 1392。单独把 p330 调到 1424 就变成非对称 MTU, 迟早出问题。1380 在这条链路上留了 44 字节余量, 够用。
验证
连通性
三方两两互通。从 p330 出发:
| |
p330→瓦工 的 148 ms ≈ p330→腾讯云 的 18 ms + 腾讯云→瓦工 的 130 ms, 和上次测的 130 ms 对得上。从瓦工 traceroute 也确认是绕腾讯云过去的:
| |
mimic 效果
p330 的 mimic show -c eno1:
| |
在 p330 的 eno1 上抓包, 出口 TCP / 入口 UDP 的分裂现象和上次完全一致:
| |
win 65535 说明 max_window = true 也生效了。
吞吐
| 方向 | 吞吐 | 说明 |
|---|---|---|
| p330 → 腾讯云 | 88.0 Mbps | 跑的是家宽上行, 重传 79 |
| 腾讯云 → p330 | 5.77 Mbps | 6 Mbps 出口跑满了, 重传 676 |
下行那 676 次重传和上次的现象一致 —— 6 Mbps 出口被打满时, mimic 伪造的 TCP 会大量重传 (上次 max_window 没开的时候是 1525)。
p330 改直连腾讯云, 另开一条到瓦工
2026-09-27 更新
上次 p330 是经 mimic 连腾讯云, 去瓦工靠腾讯云中转。这样有两个问题:
- RTT 白涨: p330→瓦工 148 ms = p330→腾讯云 18 ms + 腾讯云→瓦工 130 ms, 中间那一跳纯属绕路
- 去瓦工的流量得过腾讯云那 6 Mbps 出口, 直接被卡死
所以拆成两条独立隧道:
- wg0 直连腾讯云, 不走 mimic
- wg1 经 mimic 连瓦工
腾讯云的第二个接口
换个端口就完事, mimic 一行都不用改
/etc/wireguard/wg1.conf:
| |
nftables 补两行:
| |
p330: 两条隧道共用一个 IP, 必须改成 /32
p330 两条隧道都用 192.168.X.3。这里有个必须改的地方: wg0 原来是 /24, 现在得改成 /32。
因为 /24 会在 p330 上生成一条 192.168.X.0/24 dev wg0 的子网路由, 两条隧道会抢整段, 去瓦工的流量会被塞进连腾讯云的那条。
改成 /32 之后, 每条隧道只按对端的 /32 主机路由转发:
| |
两个接口扛同一个 /32 地址是没问题的, 因为源地址恒为 .3, 不存在选择歧义。
/etc/wireguard/wg0.conf (直连腾讯云):
| |
/etc/wireguard/wg1.conf (mimic 连瓦工):
| |
mimic 过滤器跟着改成指向瓦工:
| |
瓦工
加一个新 peer:
| |
WireGuard 的 allowed-ips 是最长前缀优先: 去 .3 命中 /32 走 p330 直连, 去 .4 还是走 /24 经腾讯云。
加 peer 用热加载, 不重启接口 (当时瓦工↔腾讯云正在传数据):
| |
同时写进 /etc/wireguard/wg0.conf, 保证重启后还在。
验证
| 路径 | 方式 | RTT |
|---|---|---|
| p330 → 腾讯云 | 直连, 明文 UDP | 13 ms |
| p330 → 瓦工 | mimic, 混淆成 TCP | 139 ms |
| (上次) p330 → 瓦工, 绕腾讯云 | 148 ms |
抓包确认两条隧道行为
| |
win 65535 说明 max_window 生效了。两条隧道都做了满包 DF 探测 + 真实 HTTP 请求 (200 / 301), 排除了 MTU 黑洞。
回看 MTU 问题
这次测下来的发现:
- 开销恒为 72 字节, 而且没有 padding
直接在腾讯云出口抓包, 量已知内层大小的包:
| 内层 IP | 外层 TCP IP |
|---|---|
| 1392 | 1464 |
| 1400 | 1472 |
差值恒为 72。而且内层 1400 发出去的就是 1472, 不是 1480, 说明 WireGuard 并没有做 16 字节对齐 padding。
符合理论: WG 头 32 + TCP 头 20 + IP 头 20
- 只有 TCP 包有这个限制
逐字节探边界:
| 内层 IP | 外层 TCP IP | 结果 |
|---|---|---|
| 1392 | 1464 | 通 |
| 1393 | 1465 | 不通 |
外层卡在 1464。
可是同一条路径:
- ICMP: 两个方向都能过 1500 (1504 才失败)
- UDP: 从腾讯云打向瓦工, 载荷 1472 (IP 1500) 0% 丢包
也就是说 路径对 UDP/ICMP 是 1500, 对 mimic 的 TCP 却卡在 1464, 应该是腾讯云针对 TCP 的限制。
- 两个方向的上限还不一样
反方向 (瓦工→腾讯云) 再测:
| 内层 IP | 外层 TCP IP | 结果 |
|---|---|---|
| 1424 | 1496 | 通 |
| 1440 | 1512 | 不通 |
1512 > 1500, 这个失败就是路径 MTU 本身; 而 1496 能过。
所以:
- 腾讯云 → 瓦工: 上限 1464
- 瓦工 → 腾讯云: 上限 1496 (受路径 MTU 约束)
两个方向根本不是同一个机制。
(顺带一提, 中间点 1472 测到过一次 25% 丢包, 样本太小, 可能只是抖动, 没有深究。)
- 抓包
结论是: 1464 = 1424 + 20 + 20。而 1424 这个数在 mimic show 里出现过:
| |
上次只能写"这个巧合很可疑"。这次直接把握手包抓下来了 —— 在腾讯云重启 mimic 触发一次新握手, 抓到的 SYN:
| |
mimic 通告的 MSS 是 1460 —— 1500 MTU 下的标准值, 本身完全正常。
可是瓦工那边收到的是 1424:
| |
中间有设备在握手路径上把 MSS 改写掉了, 砍了 36 字节。 然后按这个值丢弃超长段 —— 于是外层上限 = 1424 + 20 + 20 = 1464, 和实测边界严丝合缝。
这也解释了为什么反方向没这个现象: 两个方向走的中间设备和策略不一样, 一边做了钳制, 一边没做。
附: 单侧重启 mimic 导致 mimic 断掉
这个地方我自己其实也没特别搞懂,因为时间很短,属于随便猜一下,主要是复述一下现象
我在给出这个列表之外还有一个老家那边的小电脑 分配了 .4 地址, 通过 mimic + wg 连接到腾讯云
重启腾讯云的 mimic 抓到的SYN 包。抓完发现: 瓦工几秒内自己恢复了, 但 .4 家宽的的设备直接断了, 而且不会?自愈(感觉也不是, 不太容易自愈
盲猜的原因: mimic 的连接状态是两端的, 单侧重启只清掉一半。
- 腾讯云重启 → 忘了这条连接, 于是主动发 SYN 想重建
- .4 没重启 → 它那边仍认为连接是 Established, 收到 SYN 也不理会, 继续按老连接发数据
- 腾讯云在
SYN_SENT状态收到数据包 → 判定invalid TCP state→ 回 RST → 销毁重试
日志里就是这个循环:
| |
超时不会自愈 mimic 的 keepalive / stale 超时都以"对端无活动"为前提, 而腾讯云一直在发 SYN/RST —— 对 .4 来说这一直算"有对端活动", 超时永远不触发。死锁。
感觉最后是运气好: .4 的 NAT 出口端口正好换了 (37135 → 45733), 新五元组被 mimic 当成一条全新连接, 直接建起来, 把旧的那条晾在一边变成 Idle。
upd: 我傻逼了, reboot了腾讯云, 又断了, 可能只能使用 “叫妈妈重启家里云” 了