使用 mimic + WireGuard 组网

将一台腾讯云轻量和一台瓦工中, 通过 mimic 传输进行 WireGuard 组网

原来我是用 Phantun 的, 前两天听一个群友在研究这个, 也想玩一下

2026-09-27 更新

把 p330 改成了: wg直连腾讯云+ wg + mimic 连瓦工,顺带再研究一下上次没挖到底的 MTU 坑

2026-09-26 更新

把家里的 p330 也接进来了


拓扑与地址规划

项目腾讯云瓦工本地 p330
系统Debian 13 (trixie), kernel 6.12.107Debian 13 (trixie), kernel 6.12.107Debian 13 (trixie), kernel 6.12.107
虚拟化KVM / virtio_netKVM物理机 / 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/24192.168.X.3/32(两条隧道共用)
监听端口51820(mimic)+ 51821(直连)5182051820(mimic 到瓦工)+ 51821(直连腾讯云)
mimic 过滤条件local=腾讯云内网IP:51820local=真实公网地址:51820remote=瓦工IP:51820

配置

/etc/wireguard/wg0.conf

腾讯云

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Interface]
Address = 192.168.X.1/24
ListenPort = 51820
PrivateKey = 不告诉你
MTU = 1380

[Peer]
PublicKey = 不告诉你
AllowedIPs = 192.168.X.2/32
Endpoint = 瓦工IP:51820
PersistentKeepalive = 25

瓦工

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Interface]
Address = 192.168.X.2/24
ListenPort = 51820
PrivateKey = 不告诉你
MTU = 1380

[Peer]
PublicKey = 不告诉你
AllowedIPs = 192.168.X.1/32
Endpoint = 腾讯云EIP:51820
PersistentKeepalive = 25

/etc/mimic/eth0.conf

腾讯云

1
2
3
4
5
log.verbosity = info
link_type = eth
xdp_mode = skb
max_window = true
filter = local=内网地址:51820

瓦工

1
2
3
4
5
log.verbosity = info
link_type = eth
xdp_mode = skb
max_window = true
filter = local=公网地址:51820

nftables

腾讯云 — /etc/nftables.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state vmap { established : accept, related : accept, invalid : drop }
        meta l4proto { icmp, ipv6-icmp } counter accept
        iifname lo accept
        iifname "wg0" accept
        tcp dport 22 accept
        tcp dport 51820 accept
        udp dport 51820 accept
    }
    chain forward { type filter hook forward priority filter; policy drop; }
    chain output  { type filter hook output  priority filter; policy accept; }
}

瓦工 — 这台机器是老机器, 所以追加这几行就好了

1
2
3
        iifname "wg0" accept
        tcp dport { 51820 } accept
        udp dport { 51820 } accept

踩到的坑

mimic 配置文件的 filter 只接受一个 origin

GitHub master 分支的 man page 写的是 {origin}={ip}:{port},并举例可追加覆盖项,容易让人以为能写:

1
filter = local=腾讯云内网IP:51820,remote=瓦工IP:51820   # 0.7.0 报错

实际 0.7.0 会直接拒绝:

1
2
Error unsupported option type: 'remote'
Error failed to read configuration file

逗号后面只能跟 padding / handshake / keepalive 这类覆盖项,不能跟第二个 origin。

1
filter = local=腾讯云内网IP:51820

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。按文档建议改用:

1
xdp_mode = skb

由于腾讯云出口带宽只有 6 Mbps,skb 模式相对 native 的性能损失(generic XDP 走 skb 路径)完全无关紧要*

max_window 显著降低重传

mimic 伪造的 TCP 默认窗口约 13 KB。腾讯云↔瓦工 的 RTT 是 130 ms,13 KB / 130 ms ≈ 0.8 Mbps,在高 RTT 链路上窗口会成为瓶颈并引发大量重传。

开启后(两端都要开):

1
max_window = true

重传次数实测从 1525 降到 102(同样 6 Mbps 饱和链路、6~8 秒测试)。抓包可见窗口变为 win 65535。

防火墙必须同时放行 TCP 和 UDP

mimic 的透明改写发生在 eBPF 层,netfilter 在不同方向看到的东西不一样:

观测点看到的协议
出口方向(TC 在 netfilter OUTPUT 之后执行)UDP
入口方向(XDP 在 netfilter INPUT 之前执行,已还原)UDP
链路中间的真实抓包TCP(出口)

所以规则必须TCP/UDP都写

1
2
tcp dport 51820 accept
udp dport 51820 accept

实测抓包证据(腾讯云的 eth0):

1
2
出: IP 腾讯云内网IP.51820 > 瓦工IP.51820: Flags [.], win 65535, length 128   ← TCP
入: IP 瓦工IP.51820 > 腾讯云内网IP.51820: UDP, length 128                    ← UDP

验证结果

连通性

1
2
3
$ ping -c 4 192.168.X.2          # 从 腾讯云
4 packets transmitted, 4 received, 0% packet loss
rtt min/avg/max/mdev = 130.352/163.151/261.358/56.699 ms

mimic 效果

腾讯云的 mimic show -c eth0:

1
2
3
Connection 腾讯云内网IP:51820 => 瓦工IP:51820
  State: Established
  Peer MSS: 1332

抓包证明出口全部为 TCP、UDP 捕获数为 0:

1
2
3
4
--- TCP 51820 ---
IP 腾讯云内网IP.51820 > 瓦工IP.51820: Flags [.], win 65535, length 128
--- UDP 51820 ---
0 packets captured

把家里的机器也接进来

前几天把家里的 p330 也接进了这个网, 分配 192.168.X.3。

腾讯云瓦工本地 p330
角色hub海外hub家用服务器
网络位置公网 EIP, 网卡上是内网地址真实公网 IP家宽 NAT 后, PPPoE
网卡virtio_net—Intel e1000e (其实还插了个82599ES, 但是这块卡不用来走这条路线)
XDP 模式skbskbskb
mimic filterlocal= 本机地址local= 本机地址remote= 对端地址

p330 侧

/etc/wireguard/wg0.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Interface]
Address = 192.168.X.3/24
ListenPort = 51820
PrivateKey = 不告诉你
MTU = 1380

[Peer]
PublicKey = 不告诉你
AllowedIPs = 192.168.X.0/24
Endpoint = 腾讯云EIP:51820
PersistentKeepalive = 25

/etc/mimic/eno1.conf

1
2
3
4
5
log.verbosity = info
link_type = eth
xdp_mode = skb
max_window = true
filter = remote=腾讯云EIP:51820

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:

1
2
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdpgeneric ...
    prog/xdp id 200 name ingress_handler tag 394bf6a8d35f24d3 jited

腾讯云侧

之前在腾讯云的 filter 写的是

1
filter = local=内网地址:51820

它匹配的是"本机地址 + 端口", 跟对端是谁无关 —— 所以加第二个 peer 时, 这条 filter 天然就覆盖了新连接, 一行都不用动。

mimic show -c eth0 也确实直接变成两条:

1
2
3
4
5
6
7
Connection 10.0.X.X:51820 => 瓦工IP:51820
  State: Established
  Peer MSS: 1332

Connection 10.0.X.X:51820 => 家宽公网IP:3102
  State: Established
  Peer MSS: 1424

WireGuard 那边暂时用 live 的方式加 peer, 不重启接口,家宽后也没有什么 Endpoint 好写:

1
# wg set wg0 peer <p330公钥> allowed-ips 192.168.X.3/32

瓦工侧

要让 p330 能访问瓦工, 得把瓦工上"腾讯云"这个 peer 的 AllowedIPs 从 /32 放宽:

1
AllowedIPs = 192.168.X.0/24   # 原来是 192.168.X.1/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 出发:

1
2
3
4
5
6
7
# ping -c 4 192.168.X.1          # 腾讯云
4 packets transmitted, 4 received, 0% packet loss
rtt min/avg/max/mdev = 17.366/17.830/18.312/0.334 ms

# ping -c 4 192.168.X.2          # 瓦工
4 packets transmitted, 4 received, 0% packet loss
rtt min/avg/max/mdev = 148.251/148.379/148.493/0.086 ms

p330→瓦工 的 148 ms ≈ p330→腾讯云 的 18 ms + 腾讯云→瓦工 的 130 ms, 和上次测的 130 ms 对得上。从瓦工 traceroute 也确认是绕腾讯云过去的:

1
2
3
# traceroute -n 192.168.X.3
 1  192.168.X.1  130.639 ms
 2  192.168.X.3  148.209 ms

mimic 效果

p330 的 mimic show -c eno1:

1
2
3
Connection 家宽内网地址:51820 => 腾讯云EIP:51820
  State: Established
  Peer MSS: 1424

在 p330 的 eno1 上抓包, 出口 TCP / 入口 UDP 的分裂现象和上次完全一致:

1
2
3
4
--- TCP, 17 个 ---
IP 家宽内网地址.51820 > 腾讯云EIP.51820: Flags [.], win 65535, length 128
--- UDP, 16 个 ---
IP 腾讯云EIP.51820 > 家宽内网地址.51820: UDP, length 128

win 65535 说明 max_window = true 也生效了。

吞吐

方向吞吐说明
p330 → 腾讯云88.0 Mbps跑的是家宽上行, 重传 79
腾讯云 → p3305.77 Mbps6 Mbps 出口跑满了, 重传 676

下行那 676 次重传和上次的现象一致 —— 6 Mbps 出口被打满时, mimic 伪造的 TCP 会大量重传 (上次 max_window 没开的时候是 1525)。


p330 改直连腾讯云, 另开一条到瓦工

2026-09-27 更新

上次 p330 是经 mimic 连腾讯云, 去瓦工靠腾讯云中转。这样有两个问题:

  1. RTT 白涨: p330→瓦工 148 ms = p330→腾讯云 18 ms + 腾讯云→瓦工 130 ms, 中间那一跳纯属绕路
  2. 去瓦工的流量得过腾讯云那 6 Mbps 出口, 直接被卡死

所以拆成两条独立隧道:

  • wg0 直连腾讯云, 不走 mimic
  • wg1 经 mimic 连瓦工

腾讯云的第二个接口

换个端口就完事, mimic 一行都不用改

/etc/wireguard/wg1.conf:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Interface]
Address = 192.168.X.1/32
ListenPort = 51821
PrivateKey = 不告诉你
MTU = 1420

[Peer]
# p330 (NAT 后, 不设 Endpoint, 靠对端保活)
PublicKey = 不告诉你
AllowedIPs = 192.168.X.3/32

nftables 补两行:

1
2
iifname "wg1" accept
udp dport 51821 accept

p330: 两条隧道共用一个 IP, 必须改成 /32

p330 两条隧道都用 192.168.X.3。这里有个必须改的地方: wg0 原来是 /24, 现在得改成 /32。

因为 /24 会在 p330 上生成一条 192.168.X.0/24 dev wg0 的子网路由, 两条隧道会抢整段, 去瓦工的流量会被塞进连腾讯云的那条。

改成 /32 之后, 每条隧道只按对端的 /32 主机路由转发:

1
2
3
4
# ip route get 192.168.X.1
192.168.X.1 dev wg0 src 192.168.X.3     # 直连腾讯云
# ip route get 192.168.X.2
192.168.X.2 dev wg1 src 192.168.X.3     # 经 mimic 到瓦工

两个接口扛同一个 /32 地址是没问题的, 因为源地址恒为 .3, 不存在选择歧义。

/etc/wireguard/wg0.conf (直连腾讯云):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Interface]
Address = 192.168.X.3/32
ListenPort = 51821
PrivateKey = 不告诉你
MTU = 1420

[Peer]
PublicKey = 不告诉你
AllowedIPs = 192.168.X.1/32
Endpoint = 腾讯云EIP:51821
PersistentKeepalive = 25

/etc/wireguard/wg1.conf (mimic 连瓦工):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Interface]
Address = 192.168.X.3/32
ListenPort = 51820
PrivateKey = 不告诉你
MTU = 1380

[Peer]
PublicKey = 不告诉你
AllowedIPs = 192.168.X.2/32
Endpoint = 瓦工IP:51820
PersistentKeepalive = 25

mimic 过滤器跟着改成指向瓦工:

1
filter = remote=瓦工IP:51820

瓦工

加一个新 peer:

1
2
3
[Peer]
PublicKey = p330 的公钥
AllowedIPs = 192.168.X.3/32

WireGuard 的 allowed-ips 是最长前缀优先: 去 .3 命中 /32 走 p330 直连, 去 .4 还是走 /24 经腾讯云。

加 peer 用热加载, 不重启接口 (当时瓦工↔腾讯云正在传数据):

1
# wg set wg0 peer <p330公钥> allowed-ips 192.168.X.3/32

同时写进 /etc/wireguard/wg0.conf, 保证重启后还在。

验证

路径方式RTT
p330 → 腾讯云直连, 明文 UDP13 ms
p330 → 瓦工mimic, 混淆成 TCP139 ms
(上次) p330 → 瓦工, 绕腾讯云148 ms

抓包确认两条隧道行为

1
2
3
4
5
--- 到腾讯云 :51821 (期望 UDP) ---
IP 家宽内网地址.51821 > 腾讯云EIP.51821: UDP, length 128          ← 明文 ✓

--- 到瓦工 :51820 (期望 TCP) ---
IP 家宽内网地址.51820 > 瓦工IP.51820: Flags [.], win 65535, length 128    ← 混淆 ✓

win 65535 说明 max_window 生效了。两条隧道都做了满包 DF 探测 + 真实 HTTP 请求 (200 / 301), 排除了 MTU 黑洞。


回看 MTU 问题

这次测下来的发现:

  1. 开销恒为 72 字节, 而且没有 padding

直接在腾讯云出口抓包, 量已知内层大小的包:

内层 IP外层 TCP IP
13921464
14001472

差值恒为 72。而且内层 1400 发出去的就是 1472, 不是 1480, 说明 WireGuard 并没有做 16 字节对齐 padding。

符合理论: WG 头 32 + TCP 头 20 + IP 头 20

  1. 只有 TCP 包有这个限制

逐字节探边界:

内层 IP外层 TCP IP结果
13921464通
13931465不通

外层卡在 1464。

可是同一条路径:

  • ICMP: 两个方向都能过 1500 (1504 才失败)
  • UDP: 从腾讯云打向瓦工, 载荷 1472 (IP 1500) 0% 丢包

也就是说 路径对 UDP/ICMP 是 1500, 对 mimic 的 TCP 却卡在 1464, 应该是腾讯云针对 TCP 的限制。

  1. 两个方向的上限还不一样

反方向 (瓦工→腾讯云) 再测:

内层 IP外层 TCP IP结果
14241496通
14401512不通

1512 > 1500, 这个失败就是路径 MTU 本身; 而 1496 能过。

所以:

  • 腾讯云 → 瓦工: 上限 1464
  • 瓦工 → 腾讯云: 上限 1496 (受路径 MTU 约束)

两个方向根本不是同一个机制。

(顺带一提, 中间点 1472 测到过一次 25% 丢包, 样本太小, 可能只是抖动, 没有深究。)

  1. 抓包

结论是: 1464 = 1424 + 20 + 20。而 1424 这个数在 mimic show 里出现过:

1
2
3
4
5
6
7
8
9
# 瓦工上
Connection 瓦工IP:51820 => 腾讯云EIP:51820
  Peer MSS: 1424          ← 瓦工认为腾讯云通告的
Connection 瓦工IP:51820 => 家宽公网IP:51820
  Peer MSS: 1452          ← 瓦工认为 p330 通告的

# 腾讯云上
Connection 腾讯云内网IP:51820 => 瓦工IP:51820
  Peer MSS: 1332          ← 腾讯云认为瓦工通告的

上次只能写"这个巧合很可疑"。这次直接把握手包抓下来了 —— 在腾讯云重启 mimic 触发一次新握手, 抓到的 SYN:

1
2
10.0.16.6.51820 > 220.185.230.26.37135: Flags [S], win 65535,
    options [mss 1460, nop,wscale 14,nop,nop,sackOK], length 0

mimic 通告的 MSS 是 1460 —— 1500 MTU 下的标准值, 本身完全正常。

可是瓦工那边收到的是 1424:

1
1460 − 1424 = 36 字节

中间有设备在握手路径上把 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 → 销毁重试

日志里就是这个循环:

1
2
3
4
Info  :: initializing connection
Warn  :: connection destroyed (invalid TCP state), retry in 10 seconds
Warn  :: connection destroyed (invalid TCP state), retry in 10 seconds
...

超时不会自愈 mimic 的 keepalive / stale 超时都以"对端无活动"为前提, 而腾讯云一直在发 SYN/RST —— 对 .4 来说这一直算"有对端活动", 超时永远不触发。死锁。

感觉最后是运气好: .4 的 NAT 出口端口正好换了 (37135 → 45733), 新五元组被 mimic 当成一条全新连接, 直接建起来, 把旧的那条晾在一边变成 Idle。

upd: 我傻逼了, reboot了腾讯云, 又断了, 可能只能使用 “叫妈妈重启家里云” 了

Licensed under CC BY-NC-SA 4.0
2026/9/27/23:45 CST