RouterOS 多节点 VPN 出口方案公开版:L2TP/IPsec、IKEv2、WireGuard 接入,广州中转,香港默认出口,可切日本出口
这是一份公开版实施规范,不是凭据备份。
目标只有一个:让人或 AI 只读这一篇,就能在相同架构下完成部署、验证、切换和排障,并避开已经确认过的坑。
本文所有公网地址、端口、账号、PSK、密钥、节点名都必须替换为你自己的真实值;不要把真实值公开到网站。
1. 文档目标
本文描述的是一套三层结构的 VPN 出口网络:
- 广州 RouterOS 负责接入。
- 香港 RouterOS 作为默认互联网出口。
- 日本 Debian 作为可选出口,由香港侧开关切换。
需要同时满足以下要求:
- 支持 L2TP/IPsec、IKEv2/IPsec、WireGuard 三种接入方式。
- 客户端接入广州后,默认经广州转发到香港出网。
- 可以按协议分别把出口从香港切换到日本。
- 可以为少量目标地址做“广州直出”例外,不跟随默认香港出口。
- 后续 AI 执行同类任务时,只要读到这篇文档,就知道应该先做什么、哪里最容易错、错了看什么。
2. 适用场景
本文适用于以下场景:
- RouterOS v7。
- 至少两台 RouterOS 节点,其中广州节点负责 VPN 接入,香港节点负责默认出口。
- 可选第三个日本节点,系统为 Debian,作为 WireGuard 出口。
- 广州和香港之间同时具备公网与数据中心内网可达性。
- 需要把远程接入客户端的全流量导出到香港或日本。
- 需要明确记录实施顺序、验证步骤和排障决策,降低 AI 自行脑补设计的空间。
本文不直接覆盖以下场景:
- 纯站点到站点 IPsec。
- 证书版 IKEv2。
- ROS v6 老版本。
- 只做单节点本地拨号、不经过中转节点的简单 VPN。
3. 先给结论:这套方案里必须遵守的规则
这部分最重要,后续实施和排障都以它为准。
3.1 RouterOS v7 上,源地址策略路由优先用 routing rule,不要优先用 mangle mark-routing
如果你做的是“指定客户端、指定地址池、指定 LAN 主机走某条 VPN 出口”,在 RouterOS v7 上优先使用:
- routing table
- /ip route
- /routing rule
不要把 mangle mark-routing 当成默认方案。原因很简单:
- 它更容易引入局域网访问异常。
- 它更容易引入回程非对称。
- 在 L2TP/IPsec 这类隧道场景下,可能出现“小包能过,大流量极差,上传为 0,网页半残”的问题。
如果你已经遇到这些现象,先停掉 mangle PBR,再改成 routing rule,通常比继续给 mangle 打补丁更接近根因。
3.2 如果数据中心内网不转发 10.x / 172.x 之外的业务源地址,不要直接在 GZ 和 HK 之间裸跑客户端地址池
如果广州和香港之间的内网只愿意转发它自己认可的源/目的地址,而你的客户端地址池是独立的 10.255.x.x,那么最稳妥的做法不是强行让这些地址穿过内网,而是:
- 在 GZ 和 HK 之间先建立一条 WireGuard 传输隧道。
- 隧道外层用数据中心认可的内网地址通信。
- 客户端地址池作为隧道内层载荷传输。
3.3 L2TP 和 IKEv2 共存时,IKEv2 必须用独立命名的 IPsec 对象
不要为了 IKEv2 去乱改 RouterOS 的 default profile、default proposal、default peer。L2TP 的 use-ipsec=yes 会依赖默认 IKEv1 逻辑。正确做法是:
- L2TP 继续使用 RouterOS 默认的 L2TP/IPsec 机制。
- IKEv2 使用独立命名的 profile、proposal、peer、identity、mode-config、policy group。
3.4 每个出口点都必须有对应的 NAT
只要某个地址池可能从某个接口出互联网,就必须在那个出口接口上为该地址池准备 srcnat/masquerade。不能只在接入侧做 NAT。
3.5 MTU 与 MSS 的处理顺序不能反
正确顺序是:
- 先确认路由正确。
- 再确认 NAT 正确。
- 再确认回程正确。
- 最后再调 MTU/MSS。
如果路由本身是错的,单纯把 MSS 一路压到 1200 也救不回来。
3.6 RouterOS WireGuard peer 的 allowed-address 既是允许列表,也是回程路由线索
只要返回流量需要经过某个 peer,那个 peer 的 allowed-address 就必须覆盖需要回去的地址池。否则会出现握手有了、单向通、回包丢失这类问题。
4. 公开文档里必须保留的变量,而不是必须公开的秘密
公开版文档不应该包含真实凭据,但必须把实施所需的变量列全。后续 AI 或运维执行时,先收集这些变量,再替换到模板里。
| 变量 | 说明 |
|---|---|
| GZ_PUBLIC_IP | 广州节点公网地址 |
| GZ_PUBLIC_GW | 广州节点公网网关 |
| GZ_DC_IP | 广州节点数据中心内网地址 |
| GZ_DC_GW | 广州节点数据中心内网网关 |
| HK_PUBLIC_IP | 香港节点公网地址 |
| HK_PUBLIC_GW | 香港节点公网网关 |
| HK_DC_IP | 香港节点数据中心内网地址 |
| HK_DC_GW | 香港节点数据中心内网网关 |
| JP_PUBLIC_IP | 日本节点公网地址 |
| JP_PUBLIC_GW | 日本节点公网网关 |
| L2TP_POOL | L2TP 客户端地址池 |
| IKEV2_POOL | IKEv2 客户端地址池 |
| WG_LOCAL_POOL | 本地 WireGuard 接入地址池 |
| WG_GZ_HK_TRANSIT | GZ 和 HK 之间的 WireGuard 传输网段 |
| WG_HK_JP_TRANSIT | HK 和 JP 之间的 WireGuard 传输网段 |
| VPN_DNS | 下发给客户端的 DNS |
| DIRECT_VIA_GZ_LIST | 需要广州直出的目标地址列表 |
| FORCE_HK_LOCAL_SUBNET | 即使切到日本也必须继续从香港直出的网段 |
| SSH_PORT | 远程 SSH 端口 |
| WINBOX_PORT | Winbox 端口 |
如果这些变量没有收集完整,AI 不应该直接硬写配置,而应该先补采集。
5. 推荐的逻辑拓扑
远程客户端
├─ L2TP/IPsec
├─ IKEv2/IPsec
└─ WireGuard
│
▼
GZ RouterOS
接入、地址分配、策略路由汇聚
│
│ WireGuard 传输隧道(优先用 DC 内网地址做 endpoint)
▼
HK RouterOS
默认互联网出口
│
│ WireGuard 传输隧道
▼
JP Debian
可选互联网出口这套结构里,广州不是默认互联网出口,而是入口和中转层;香港是默认出口,日本是开关式备用出口。
6. 推荐地址规划
下面是一个可复用、且已经被验证过思路合理的规划方式。你可以保留网段结构,替换成你自己的值。
| 网段 | 用途 |
|---|---|
| 10.255.0.0/30 | GZ↔HK WireGuard 传输网段 |
| 10.255.10.0/24 | L2TP 地址池 |
| 10.255.20.0/30 | HK↔JP WireGuard 传输网段 |
| 10.255.30.0/24 | 本地 WireGuard 接入网段 |
| 10.255.40.0/24 | IKEv2 地址池 |
推荐原因:
- 地址池职责清楚。
- L2TP、IKEv2、本地 WireGuard 互不混淆。
- 回程路由、NAT 和 allowed-address 更好写。
7. MTU 设计原则
不要直接拿外层 PMTU 当内层隧道 MTU。要按承载层逐级扣头。
推荐起点如下:
- 本地 PPPoE 如果是 1450,那么本地到广州的 WireGuard 可以先从 1390 起步。
- GZ↔HK 如果跑在 1500 的数据中心内网上,WireGuard 可以先从 1400 起步。
- HK↔JP 如果跑在 1500 公网上,WireGuard 可以先从 1420 起步。
- L2TP/IPsec 不要一上来写 1450,先从 1400 起步更稳。
- 所有隧道出口都应启用 change-tcp-mss 或 clamp-to-pmtu。
如果业务已经通,但速度差、网页半开、测速上传异常,再做 MTU 微调;如果业务本身不通,先别碰 MTU。
8. 实施顺序
顺序不能乱。正确顺序如下:
- 先打通 GZ↔HK 传输层。
- 再打通 HK↔JP 传输层。
- 再配置 GZ 的 L2TP 服务。
- 再配置 GZ 的 IKEv2 服务。
- 再配置 GZ 的本地 WireGuard 接入。
- 再写 GZ 的策略路由表和 routing rule。
- 再写 HK 的默认出口 NAT 和日本开关。
- 再写 JP 的 NAT 和转发。
- 最后做例外路由、验证和测速。
9. 广州节点配置模板
以下是广州节点的最小可用模板,真实值必须替换。
9.1 GZ↔HK WireGuard 传输接口
/interface wireguard
add name=wg-hk listen-port=<GZ_HK_WG_PORT> mtu=1400 comment="gz-hk-transit"
/ip address
add address=<GZ_WG_GZ_HK_IP/CIDR> interface=wg-hk comment="gz-hk-transit"
/interface wireguard peers
add interface=wg-hk public-key="<HK_WG_PUBKEY>" \
endpoint-address=<HK_DC_IP> endpoint-port=<GZ_HK_WG_PORT> \
allowed-address=0.0.0.0/0,<WG_GZ_HK_TRANSIT>,<L2TP_POOL>,<IKEV2_POOL>,<WG_LOCAL_POOL> \
persistent-keepalive=25s comment="hk-peer"说明:
- GZ 这一侧需要把默认互联网流量塞进发往 HK 的 WireGuard 传输隧道,所以 allowed-address 要覆盖 0.0.0.0/0。
- endpoint-address 优先用 HK 的数据中心内网地址,而不是香港公网地址。
9.2 L2TP/IPsec 服务器
/ip pool
add name=pool-l2tp ranges=<L2TP_POOL_RANGE>
/ppp profile
add name=prof-l2tp local-address=<L2TP_GW_IP> remote-address=pool-l2tp \
dns-server=<VPN_DNS> change-tcp-mss=yes only-one=yes \
use-compression=no use-encryption=no
/ppp secret
add name=<L2TP_USERNAME> password="<L2TP_PASSWORD>" service=l2tp profile=prof-l2tp
/interface l2tp-server server
set enabled=yes use-ipsec=yes ipsec-secret="<L2TP_PSK>" \
authentication=mschap2 default-profile=prof-l2tp \
max-mtu=1400 max-mru=1400 one-session-per-host=yes9.3 IKEv2/IPsec 服务器
/ip pool
add name=pool-ikev2 ranges=<IKEV2_POOL_RANGE>
/ip ipsec profile
add name=prof-ikev2-gz enc-algorithm=aes-256,aes-128 hash-algorithm=sha256 \
dh-group=modp2048,modp1024
/ip ipsec proposal
add name=prop-ikev2-gz enc-algorithms=aes-256-cbc,aes-128-cbc \
auth-algorithms=sha256 pfs-group=none
/ip ipsec mode-config
add name=modeconf-ikev2 address-pool=pool-ikev2 address-prefix-length=32 \
split-include=0.0.0.0/0 static-dns=<VPN_DNS> system-dns=no
/ip ipsec policy group
add name=group-ikev2
/ip ipsec policy
add group=group-ikev2 template=yes proposal=prop-ikev2-gz \
src-address=0.0.0.0/0 dst-address=<IKEV2_POOL_CIDR>
/ip ipsec peer
add name=peer-ikev2 passive=yes exchange-mode=ike2 profile=prof-ikev2-gz
/ip ipsec identity
add peer=peer-ikev2 auth-method=pre-shared-key secret="<IKEV2_PSK>" \
generate-policy=port-strict mode-config=modeconf-ikev2 \
policy-template-group=group-ikev2这一步的关键不是命令本身,而是命名隔离:
- prof-ikev2-gz 不是 default。
- prop-ikev2-gz 不是 default。
- peer-ikev2 不是 default。
9.4 本地 WireGuard 接入接口
/interface wireguard
add name=wg-local listen-port=<WG_LOCAL_PORT> mtu=1390 comment="local-ingress"
/ip address
add address=<GZ_WG_LOCAL_IP/CIDR> interface=wg-local comment="local-ingress"
/interface wireguard peers
add interface=wg-local public-key="<LOCAL_PEER_PUBKEY>" \
allowed-address=<WG_LOCAL_PEER_IP/32> persistent-keepalive=25s \
comment="local-router-peer"9.5 GZ 的策略路由表与规则
/routing table
add fib name=to-hk-egress
/ip route
add dst-address=0.0.0.0/0 gateway=<GZ_PUBLIC_GW>
add dst-address=<HK_DC_SUBNET> gateway=<GZ_DC_GW> comment="to-hk-private-subnet"
add dst-address=<HK_DC_IP/32> gateway=<GZ_DC_GW> scope=10 comment="hk-private-recursive"
add dst-address=0.0.0.0/0 gateway=<HK_WG_TRANSIT_IP> routing-table=to-hk-egress target-scope=11 \
comment="default-via-hk"/routing rule
add src-address=<L2TP_POOL_CIDR> action=lookup-only-in-table table=to-hk-egress \
comment="l2tp-via-hk"
add src-address=<IKEV2_POOL_CIDR> action=lookup-only-in-table table=to-hk-egress \
comment="ikev2-via-hk"
add interface=wg-local action=lookup-only-in-table table=to-hk-egress \
comment="wg-local-via-hk"说明:
- 这部分是整套方案的核心。
- 这里故意用 routing rule,不用 mangle mark-routing。
- 如果你做的是“指定某台 LAN 主机走 VPN 出口”,也是同一个原则:给该主机写 src-address 的 routing rule,而不是先上 mangle。
9.6 广州直出例外路由
/ip route
add dst-address=<EXCEPTION_IP_1/32> gateway=<GZ_PUBLIC_GW> routing-table=to-hk-egress \
comment="force-gz-egress-1"
add dst-address=<EXCEPTION_IP_2/32> gateway=<GZ_PUBLIC_GW> routing-table=to-hk-egress \
comment="force-gz-egress-2"原理是:在 to-hk-egress 表里放比默认路由更具体的主机路由,让特定目的地址继续从广州本地公网出去。
9.7 广州直出 NAT
/ip firewall nat
add chain=srcnat action=masquerade out-interface=<GZ_PUBLIC_IF> src-address=<L2TP_POOL_CIDR> \
comment="l2tp-egress-via-gz-direct"
add chain=srcnat action=masquerade out-interface=<GZ_PUBLIC_IF> src-address=<IKEV2_POOL_CIDR> \
comment="ikev2-egress-via-gz-direct"
add chain=srcnat action=masquerade out-interface=<GZ_PUBLIC_IF> src-address=<WG_LOCAL_POOL_CIDR> \
comment="wg-local-egress-via-gz-direct"如果你不写这三条,那么命中广州直出例外路由时,客户端源地址不会被转换,出口将异常。
9.8 广州侧 MSS Clamping
/ip firewall mangle
add chain=forward action=change-mss new-mss=clamp-to-pmtu protocol=tcp tcp-flags=syn \
out-interface=wg-hk comment="clamp-mss-out-wg-hk"
add chain=forward action=change-mss new-mss=clamp-to-pmtu protocol=tcp tcp-flags=syn \
out-interface=wg-local comment="clamp-mss-out-wg-local"10. 香港节点配置模板
10.1 HK↔GZ WireGuard 传输接口
/interface wireguard
add name=wg-gz listen-port=<GZ_HK_WG_PORT> mtu=1400 comment="hk-gz-transit"
/ip address
add address=<HK_WG_GZ_HK_IP/CIDR> interface=wg-gz comment="hk-gz-transit"
/interface wireguard peers
add interface=wg-gz public-key="<GZ_WG_PUBKEY>" \
endpoint-address=<GZ_DC_IP> endpoint-port=<GZ_HK_WG_PORT> \
allowed-address=<WG_GZ_HK_TRANSIT>,<L2TP_POOL>,<IKEV2_POOL>,<WG_LOCAL_POOL> \
persistent-keepalive=25s comment="gz-peer"说明:
- 香港侧主要负责回程,不必默认把全部互联网流量送回广州,所以这里通常不需要 0.0.0.0/0。
- 但必须包含所有客户端地址池,否则回包找不到路。
10.2 HK↔JP WireGuard 传输接口
/interface wireguard
add name=wg-jp listen-port=<HK_JP_WG_PORT> mtu=1420 comment="hk-jp-egress"
/ip address
add address=<HK_WG_HK_JP_IP/CIDR> interface=wg-jp comment="hk-jp-egress"
/interface wireguard peers
add interface=wg-jp public-key="<JP_WG_PUBKEY>" \
endpoint-address=<JP_PUBLIC_IP> endpoint-port=<HK_JP_WG_PORT> \
allowed-address=0.0.0.0/0,<WG_HK_JP_TRANSIT> \
persistent-keepalive=25s comment="jp-peer"这里需要 0.0.0.0/0,因为当“日本开关”启用时,香港要把默认互联网流量送去日本。
10.3 香港默认出口、回程路由与日本开关
/routing table
add fib name=to-jp-egress
/ip route
add dst-address=0.0.0.0/0 gateway=<HK_PUBLIC_GW>
add dst-address=<GZ_DC_SUBNET> gateway=<HK_DC_GW> comment="to-gz-private-subnet"
add dst-address=<GZ_DC_IP/32> gateway=<HK_DC_GW> scope=10 comment="gz-private-recursive"
add dst-address=<L2TP_POOL_CIDR> gateway=<GZ_WG_TRANSIT_IP> target-scope=11 comment="l2tp-pool-via-gz"
add dst-address=<IKEV2_POOL_CIDR> gateway=<GZ_WG_TRANSIT_IP> target-scope=11 comment="ikev2-pool-via-gz"
add dst-address=<WG_LOCAL_POOL_CIDR> gateway=<GZ_WG_TRANSIT_IP> target-scope=11 comment="wg-local-pool-via-gz"
add dst-address=0.0.0.0/0 gateway=<JP_WG_TRANSIT_IP> routing-table=to-jp-egress comment="default-via-jp"
add dst-address=<FORCE_HK_LOCAL_SUBNET> gateway=<HK_PUBLIC_IF> routing-table=to-jp-egress \
comment="force-hk-egress-subnet"/routing rule
add src-address=<L2TP_POOL_CIDR> action=lookup-only-in-table table=to-jp-egress \
comment="switch-l2tp-to-jp" disabled=yes
add src-address=<IKEV2_POOL_CIDR> action=lookup-only-in-table table=to-jp-egress \
comment="switch-ikev2-to-jp" disabled=yes
add src-address=<WG_LOCAL_POOL_CIDR> action=lookup-only-in-table table=to-jp-egress \
comment="switch-wg-local-to-jp" disabled=yes默认禁用意味着默认走香港;启用后才走日本。
10.4 香港默认出口 NAT
/ip firewall nat
add chain=srcnat action=masquerade out-interface=<HK_PUBLIC_IF> src-address=<L2TP_POOL_CIDR> \
comment="l2tp-egress-via-hk"
add chain=srcnat action=masquerade out-interface=<HK_PUBLIC_IF> src-address=<IKEV2_POOL_CIDR> \
comment="ikev2-egress-via-hk"
add chain=srcnat action=masquerade out-interface=<HK_PUBLIC_IF> src-address=<WG_LOCAL_POOL_CIDR> \
comment="wg-local-egress-via-hk"10.5 香港侧 MSS Clamping
/ip firewall mangle
add chain=forward action=change-mss new-mss=clamp-to-pmtu protocol=tcp tcp-flags=syn \
out-interface=wg-gz comment="clamp-mss-out-wg-gz"
add chain=forward action=change-mss new-mss=clamp-to-pmtu protocol=tcp tcp-flags=syn \
out-interface=wg-jp comment="clamp-mss-out-wg-jp"11. 日本 Debian 配置模板
11.1 系统要求
- 开启 net.ipv4.ip_forward=1。
- 安装 WireGuard。
- 出口网卡记为 eth0,实际环境按真实网卡名替换。
11.2 WireGuard 配置模板
文件路径可以使用 /etc/wireguard/wg-hk.conf。
[Interface]
Address = <JP_WG_HK_JP_IP/CIDR>
ListenPort = <HK_JP_WG_PORT>
PrivateKey = <JP_WG_PRIVKEY>
MTU = 1420
PostUp = iptables -A FORWARD -i wg-hk -j ACCEPT
PostUp = iptables -A FORWARD -o wg-hk -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -s <L2TP_POOL_CIDR> -o eth0 -j MASQUERADE
PostUp = iptables -t nat -A POSTROUTING -s <IKEV2_POOL_CIDR> -o eth0 -j MASQUERADE
PostUp = iptables -t nat -A POSTROUTING -s <WG_LOCAL_POOL_CIDR> -o eth0 -j MASQUERADE
PostUp = iptables -t mangle -A FORWARD -o wg-hk -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PreDown = iptables -D FORWARD -i wg-hk -j ACCEPT
PreDown = iptables -D FORWARD -o wg-hk -j ACCEPT
PreDown = iptables -t nat -D POSTROUTING -s <L2TP_POOL_CIDR> -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -s <IKEV2_POOL_CIDR> -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -s <WG_LOCAL_POOL_CIDR> -o eth0 -j MASQUERADE
PreDown = iptables -t mangle -D FORWARD -o wg-hk -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
[Peer]
PublicKey = <HK_WG_PUBKEY>
AllowedIPs = <HK_WG_TRANSIT_IP/32>,<L2TP_POOL_CIDR>,<IKEV2_POOL_CIDR>,<WG_LOCAL_POOL_CIDR>
PersistentKeepalive = 25说明:
- 日本节点只负责把来自香港的客户端地址池 NAT 出去。
- 它不需要宣称自己拥有整个互联网的回程,只需要把这些客户端网段接住即可。
12. 本地 RouterOS 通过 WireGuard 接入广州的模板
如果你有一台本地 RouterOS,想把它的部分或全部流量送到广州,再转香港/日本,可以按下列方式接入。
/interface wireguard
add name=wg-gz listen-port=<WG_LOCAL_PORT> mtu=1390 comment="wg-to-gz"
/ip address
add address=<LOCAL_WG_IP/CIDR> interface=wg-gz comment="wg-to-gz"
/interface wireguard peers
add interface=wg-gz public-key="<GZ_WG_LOCAL_PUBKEY>" \
endpoint-address=<GZ_PUBLIC_IP> endpoint-port=<WG_LOCAL_PORT> \
allowed-address=0.0.0.0/0 persistent-keepalive=25s comment="gz-server-peer"12.1 如果是全局 LAN 走广州
/routing table
add fib name=to-gz-egress
/ip route
add dst-address=0.0.0.0/0 gateway=<GZ_WG_LOCAL_IP> routing-table=to-gz-egress
/routing rule
add src-address=<LOCAL_LAN_SUBNET> action=lookup-only-in-table table=to-gz-egress \
comment="lan-via-gz"12.2 如果只是指定某台 LAN 主机走广州
/routing table
add fib name=to-gz-egress
/ip route
add dst-address=0.0.0.0/0 gateway=<GZ_WG_LOCAL_IP> routing-table=to-gz-egress
/routing rule
add src-address=<LAN_HOST_IP/32> action=lookup-only-in-table table=to-gz-egress \
comment="host-via-gz"这里再次强调:
- 优先用 routing rule。
- 不要默认用 mangle mark-routing。
13. 日本出口开关的标准操作
在香港节点执行。
13.1 切 L2TP 到日本
/routing rule enable [find where comment="switch-l2tp-to-jp"]13.2 切 IKEv2 到日本
/routing rule enable [find where comment="switch-ikev2-to-jp"]13.3 切本地 WireGuard 到日本
/routing rule enable [find where comment="switch-wg-local-to-jp"]13.4 关闭日本开关
/routing rule disable [find where comment~"switch.*to-jp"]验证标准只有一个:客户端看到的出口公网 IP 必须符合预期。
14. AI 或运维执行时的标准验证顺序
不要上来就测速。正确验证顺序如下。
14.1 先看隧道握手
RouterOS:
/interface wireguard peers print
/ip ipsec active-peers print
/ip ipsec installed-sa printLinux:
wg show14.2 再看路由
广州:
/ip route print where active
/routing rule print
/ping address=8.8.8.8 src-address=<L2TP_GW_IP> count=3
/ping address=8.8.8.8 src-address=<IKEV2_TEST_IP> count=3香港:
/ip route print where active
/routing rule print14.3 再看 NAT 命中
/ip firewall nat print statsLinux:
iptables -t nat -L POSTROUTING -n -v14.4 再看客户端出口 IP
curl -s ifconfig.me如果要看更完整的 AS 信息,使用:
curl -sL -A 'Mozilla/5.0' 'https://bgp.he.net' | grep 'visiting from'不要再用 HTTP 版本去请求 bgp.he.net,否则容易 403。
14.5 最后才做应用层验证
- 打开网页。
- 播放视频。
- 跑上下行测速。
- 对比切换前后出口 IP 是否符合预期。
15. 标准排障决策表
这一节是给 AI 用的,也是给人用的。遇到问题,先对号入座,再查对应项。
| 现象 | 最可能原因 | 优先检查 |
|---|---|---|
| L2TP 或 IKEv2 能连上,但完全不能上网 | GZ 路由规则没命中,HK 回程路由缺失,或 HK NAT 漏写 | GZ routing rule、HK route、HK NAT |
| GZ 和 HK 的内网地址互 ping 正常,但客户端地址池过不去 | 数据中心内网不转发客户端地址池 | GZ↔HK 必须用 WireGuard 传输层封装 |
| WireGuard 握手有,但业务单向通 | peer 的 allowed-address 不完整 | 双端 peer 的 allowed-address |
| 加完 IKEv2 以后 L2TP 断了 | 改坏了 default IPsec 配置 | IKEv2 是否用了独立命名对象 |
| 网页半开、图片不全、测速上传为 0 | 不是单纯 MSS 问题,更可能是 RouterOS v7 mangle PBR 不稳定 | 是否使用了 mark-routing;先改 routing rule |
| 把 MSS 压很小还是不通 | 根因不在 MSS | 回到路由、回程、NAT |
| RouterOS SSH 执行 WireGuard peer 命令时报 expected end of command | 公钥里的 / 被当成命令路径分隔符 | 用 Here-String 经 stdin 发送命令 |
| Linux L2TP 已拨上,但 DNS 不通 | ppp0 的 DNS 没被 systemd-resolved 接管 | resolvectl dns ppp0 |
| 切到日本后香港自身公网段访问异常 | to-jp-egress 表里没保留香港本地直出例外 | FORCE_HK_LOCAL_SUBNET 的更具体路由 |
| 客户端连上后访问 VPN 服务器公网地址异常 | 默认路由把服务器地址也送进隧道,形成回环 | 先加服务器公网地址的直连路由 |
16. 已验证的典型坑
16.1 不要把“外层 PMTU 1450”直接理解成“L2TP MTU 应该设 1450”
外层 PMTU 只说明最外层 IP 包能承载多大,不代表 L2TP/IPsec 内层接口也能安全吃满这个值。L2TP、PPP、ESP、UDP、NAT-T 都会继续吃头部。
16.2 不要把 FastTrack、QUIC、rp-filter 当成第一嫌疑人
如果你看到的是“路由级别不稳定”,先回到策略路由实现方式本身。很多时候问题根本不在 QUIC 或 FastTrack,而在 PBR 选型。
16.3 不要假设 SSH 自动化里 Base64 是普通字符串
RouterOS 在命令行里对特殊字符解析很敏感,尤其是 WireGuard 公钥里的斜杠。自动化时最好直接通过 stdin 管道喂整段命令。
16.4 不要漏掉每个出口点的 NAT
GZ 负责直出例外时需要 NAT,HK 作为默认出口需要 NAT,JP 作为可选出口同样需要 NAT。缺哪个,哪个方向就会出问题。
17. 自动化执行时的补充约束
如果后续让 AI 直接按这篇文章实施,请额外遵守下面几条:
- 先盘点变量,再写配置,不要先写后问。
- 先建传输隧道,再建接入服务,不要倒序。
- 变更 IKEv2 时,不要动 L2TP 默认 IPsec 对象。
- 做策略路由时,优先用 routing rule,不要默认上 mangle mark-routing。
- 做例外路由时,要同时考虑路由与 NAT,不能只写路由。
- 测速前先确认出口 IP 正确,否则测速结果没有意义。
- 如果某一步现象和本文的排障表冲突,先检查是不是基础变量拿错了。
18. 如果你的任务不是远程接入,而是“本地某台 LAN 主机走 VPN 出口”
这属于同类问题,只是接入源从地址池变成单一主机。处理原则不变:
- 为这台主机建立独立 routing table。
- 用 routing rule 按 src-address=<LAN_HOST/32> 查表。
- 如有必要,在该表中为本地网关、局域网、特定公网目标写更具体例外路由。
- 不要把 mangle mark-routing 当默认实现。
如果你已经见到这些现象:
- 本地路由器 192.168.x.1 无法访问。
- 外部从原公网入口访问该主机时回包异常。
- 网页卡、图片不全、测速上传为 0。
优先怀疑策略路由实现方式,而不是先把问题归咎于 MSS。
19. 公开发布时的脱敏要求
如果你要把这篇文档放到网站上,至少做到下面几点:
- 所有公网 IP 改为占位符或文档保留地址。
- 所有账号、密码、PSK、私钥、公钥全部去掉或替换为
。 - 所有自定义端口如果没有公开必要,也改为占位符。
- 所有截图打码 IP、用户名、peer 名、SPI、时间戳、接口名、序列号。
- 所有看起来像管理入口的域名不要放在正文里。
公开文档应该公开的是架构、顺序、判断逻辑和坑,不是资产清单。
20. 一句话总结
这套方案的核心不是“把 VPN 配起来”,而是明确把问题拆成四层来做:
- 传输层先打通。
- 策略路由用 routing rule 固化。
- 每个出口点把 NAT 补齐。
- MTU/MSS 最后再调。
只要顺序不乱,GZ 负责接入、HK 负责默认出口、JP 负责可选出口的这套结构是可以稳定复用的;反过来,如果一开始就用 mangle PBR 去硬扛复杂隧道,大概率会再次踩回同一批坑。