«

RouterOS 7 + Ubuntu VPS:基于 WireGuard 与动态 DNS 列表的策略分流

myluzh 发布于 阅读:132 RouterOS


0x00 前言

前置条件

本文的 DNS 域名匹配转发(match-subdomain=yes)与动态列表延时(address-list-extra-time)依赖 RouterOS 7 的新特性。请确保你的 ROS 版本至少在 v7.10 及以上,否则 /ip/dns/static 相关的配置将无法执行。

介绍

本文使用一台 HK VPS Ubuntu 与家里的 RouterOS 建立 WireGuard 隧道,为后续基于域名解析结果的策略分流做准备。
WireGuard 隧道网段规划如下:

角色 地址
隧道网段 10.252.252.0/30
香港 Ubuntu VPS 10.252.252.1/30
家里 RouterOS 10.252.252.2/30
网络地址 10.252.252.0
广播地址 10.252.252.3
flowchart TD
    classDef l3 fill:#f9f9f9,stroke:#333,stroke-width:1px;
    classDef intf fill:#e6f3ff,stroke:#0066cc,stroke-width:1px;

    Subnet["LAN Subnet (172.17.0.0/16)"]:::l3

    subgraph SiteA ["Site A: On-Premises (RouterOS)"]
        ROS_WG["Interface: wireguard2<br/>IP: 10.252.252.2/30<br/>Peer Endpoint: 119.28.68.138<br/>AllowedIPs: 0.0.0.0/0"]:::intf
    end

    subgraph SiteB ["Site B: Cloud Node (Ubuntu VPS)"]
        VPS_WG["Interface: wg0<br/>IP: 10.252.252.1/30<br/>ListenPort: 51820<br/>AllowedIPs: 10.252.252.2/32, 172.17.0.0/16"]:::intf
    end

    Subnet --> ROS_WG
    ROS_WG <-->|"WireGuard UDP Tunnel (Port 51820)"| VPS_WG

最终目标是:由家里的 RouterOS 负责 DNS 解析并将指定国外域名解析出的 IP 自动加入地址列表,再通过策略路由将这些目标流量转发到香港VPS 出口,实现基于域名的分流。

0x01 安装 & 配置 WireGuard 互通

Ubuntu配置

1、开启Ubuntu IPv4 转发

root@ubuntu-vps:~$ echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard.conf
root@ubuntu-vps:~$ sudo sysctl --system

2、Ubuntu 安装 WireGuard

root@ubuntu-vps:~$ sudo apt update
root@ubuntu-vps:~$ sudo apt install -y wireguard

3、 生成 VPS 密钥

# WireGuard 私钥很敏感,所以生成 key 前常用 umask 077,就是只有 root 能读写。
root@ubuntu-vps:~$ sudo -i
root@ubuntu-vps:~$ umask 077
root@ubuntu-vps:~$ wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key

#  记下输出的 server_public_key,后面 RouterOS 要用
root@ubuntu-vps:~$ cat /etc/wireguard/server_public.key  
WzYftiIiuilxHtGHvGKe3PvO5I+XNdorKN6SxXVfD0g=

4、创建Ubuntu wireguard 配置文件

root@ubuntu-vps:~$ vi /etc/wireguard/wg0.conf
# 先填这些,确保wg能起来,后面再补上peer配置。
[Interface]
Address = 10.252.252.1/30
ListenPort = 51820
# PrivateKey 填 server_private.key 的内容 cat /etc/wireguard/server_private.key
PrivateKey =  QH7mP2xR9vK4nB8jF5cT1dL6wY0hS3gUeiNaA7oD0EM= 

# 允许 VPS 通过 wg0 转发流量
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT

5、启动 WireGuard
记得去云厂商安全组放行,去 VPS 控制台放行:UDP 51820 入站

root@ubuntu-vps:~$ systemctl enable --now wg-quick@wg0
root@ubuntu-vps:~$ wg show
interface: wg0
 public key: WzYftiIiuilxHtGHvGKe3PvO5I+XNdorKN6SxXVfD0g=
 private key: (hidden)
 listening port: 51820

7、最终配置
然后需要在对端创建wg,获取对端公钥,最终配置如下:
AllowedIPs 172.17.0.0/16 是我家里的网段。

root@ubuntu-vps:~$ cat /etc/wireguard/wg0.conf
[Interface]
Address = 10.252.252.1/30
ListenPort = 51820
PrivateKey = QH7mP2xR9vK4nB8jF5cT1dL6wY0hS3gUeiNaA7oD0EM=

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT

[Peer]
PublicKey = XvnO1bNLgGGjBqRaKN9w03U2N9v0okLvKT9Cb1HB6g0=
AllowedIPs = 10.252.252.2/32, 172.17.0.0/16

8、配置完成后重启

root@ubuntu-vps:~$ sudo systemctl restart wg-quick@wg0
root@ubuntu-vps:~$ wg show
interface: wg0
  public key: WzYftiIiuilxHtGHvGKe3PvO5I+XNdorKN6SxXVfD0g=
  private key: (hidden)
  listening port: 51820

peer: XvnO1bNLgGGjBqRaKN9w03U2N9v0okLvKT9Cb1HB6g0=
  allowed ips: 10.252.252.2/32, 172.17.0.0/16

RouterOS配置

1、wg与peer配置
RouterOS 端的 listen-port 可以不固定,因为这里由家里的 RouterOS 主动连接 VPS;但 peer 里的endpoint-port 必须填写 VPS WireGuard 的监听端口,也就是 51820。endpoint-address 为对端ip。

[admin@HOME2-ROS] /interface/wireguard> export 
/interface wireguard
add comment=wg-ubuntu listen-port=48722 mtu=1420 name=wireguard2
/interface wireguard peers
add allowed-address=10.252.252.1/32 client-allowed-address=::/0 comment=ubuntu-vps endpoint-address=119.28.68.138 endpoint-port=51820 interface=wireguard2 name=\
    peer6 persistent-keepalive=5s public-key="WzYftiIiuilxHtGHvGKe3PvO5I+XNdorKN6SxXVfD0g="

2、ip配置

[admin@HOME2-ROS] /ip/address> export 
/ip address
add address=10.252.252.2/30 interface=wireguard2 network=10.252.252.0

测试

1、ros侧

# 看 handshake 确认状态:
[admin@HOME2-ROS] /interface/wireguard>   /interface/wireguard/peers/print detail where name="peer6" 
Flags: X - disabled; D - dynamic 
 2    ;;; ubuntu-vps
      interface=wireguard2 name="peer6" public-key="WzYftiIiuilxHtGHvGKe3PvO5I+XNdorKN6SxXVfD0g=" endpoint-address=119.28.68.138 endpoint-port=51820 
      current-endpoint-address=119.28.68.138 current-endpoint-port=51820 allowed-address=10.252.252.1/32 persistent-keepalive=5s client-endpoint="" 
      client-allowed-address=::/0 rx=2056 tx=7.0KiB last-handshake=26s 
# ping测
[admin@HOME2-ROS] /interface/wireguard>  /ping 10.252.252.1 src-address=10.252.252.2
  SEQ HOST                                     SIZE TTL TIME       STATUS                                                                                          
    0 10.252.252.1                               56  64 31ms278us 
    1 10.252.252.1                               56  64 31ms296us 

2、vps侧

root@ubuntu-vps:~$ ping -c 4 10.252.252.2
PING 10.252.252.2 (10.252.252.2) 56(84) bytes of data.
64 bytes from 10.252.252.2: icmp_seq=1 ttl=64 time=31.1 ms
64 bytes from 10.252.252.2: icmp_seq=2 ttl=64 time=31.5 ms

到此,wg互通已经实现。

0x02 根据域名分流

机制简述:DNS FWD 与 Address-List 联动

依托于 ROS v7 的 DNS 静态转发(type=FWD)特性,实现了“应用层域名”到“网络层路由”的自动映射。其工作流如下:

flowchart LR
    classDef host fill:#fff,stroke:#333,stroke-width:1px;
    classDef process fill:#f2f2f2,stroke:#666,stroke-width:1px;
    classDef state fill:#fff2cc,stroke:#d6b656,stroke-width:1px;
    classDef action fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px;

    subgraph CP ["Control Plane: DNS Policy Injection"]
        C_Req["1. Client DNS"]:::host --> DNS_FWD["2. ROS Static"]:::process
        DNS_FWD -->|"FWD to VPS"| DNS_Up["3. VPS AdGuard"]:::process
        DNS_Up -->|"Return IP"| DNS_Rsp["4. ROS Cache"]:::process
        DNS_Rsp -.->|"Dynamic Inject"| AddrList[("5. Address-List")]:::state
    end

    subgraph DP ["Data Plane: Traffic Forwarding"]
        P_Req["6. Client Payload"]:::host --> Mangle["7. ROS Mangle"]:::action
        Mangle -->|"mark=to_hk"| FIB["8. ROS FIB"]:::process
        FIB -->|"Route to 10.x"| WG_Tx["9. WG Tunnel"]:::process
        WG_Tx -->|"SNAT"| SNAT["10. VPS POSTROUTING"]:::action
        SNAT --> Egress["11. WAN Egress"]:::host
    end

    %% 跨层级关联
    AddrList -.->|"Provide Dst-IP Match"| Mangle

Ubuntu 配置

设置DNS转发

root@ubuntu-vps:~$ docker run -d --name dnsproxy --restart unless-stopped \
    -p 10.252.252.1:53:53/udp \
    -p 10.252.252.1:53:53/tcp \
    adguard/dnsproxy \
    --upstream https://dns.google/dns-query \
    --listen 0.0.0.0

Status: Downloaded newer image for adguard/dnsproxy:latest
bc995d1c5086a174cbd000c3293a014de858c7d8e21795741b1c93ff09b437e9

# 测试
root@ubuntu-vps:~$ dig @10.252.252.1 google.com

设置NAT

开启srcnat,允许转发。
检查:sysctl net.ipv4.ip_forward应为:net.ipv4.ip_forward = 1
注意:iptables 规则重启后不会自动保留,需要写入 wg0.conf 的 PostUp/PostDown。

# 把内网来源 NAT 成 VPS 出口地址:
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o eth0 -j MASQUERADE
# 可选:WireGuard 点对点网段也 NAT:
iptables -t nat -A POSTROUTING -s 10.252.252.0/30 -o eth0 -j MASQUERADE
# 允许内网经 wg0 转发到 eth0:
iptables -A FORWARD -i wg0 -o eth0 -s 172.17.0.0/16 -j ACCEPT
# 允许公网回包从 eth0 回 wg0:
iptables -A FORWARD -i eth0 -o wg0 -d 172.17.0.0/16 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

验证命令,在 VPS 上看 NAT 是否命中:

iptables -t nat -vnL POSTROUTING
iptables -vnL FORWARD

路由状态

root@ubuntu-vps:~$ ip route
default via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.14 metric 100
10.0.0.0/22 dev eth0 proto kernel scope link src 10.0.0.14 metric 100
10.0.0.1 dev eth0 proto dhcp scope link src 10.0.0.14 metric 100
10.8.0.0/24 dev tun0 proto kernel scope link src 10.8.0.1
10.88.0.0/24 dev docker0 proto kernel scope link src 10.88.0.1
10.252.252.0/30 dev wg0 proto kernel scope link src 10.252.252.1
172.17.0.0/16 dev wg0 scope link # 有回程路由
183.60.82.98 via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.14 metric 100
183.60.83.19 via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.14 metric 100

RouterOS 配置

修改peers

由于 RouterOS 直接把公网目标也丢进这个 WireGuard peer,需要修改peer,allowed-address=0.0.0.0/0

/interface/wireguard/peers/set [find name="peer6"] allowed-address=0.0.0.0/0

设置DNS转发

下一步 RouterOS 里就可以这样写:
address-list-extra-time:就是是额外时间; DNS 记录 TTL + address-list-extra-time(额外时间)=加入 address-list 动态条目有效时间。它只影响这种配置生成的 address-list存在时长,这个时间不应该太短,也不能太长。
max-concurrent-queries:最大并发查询数,路由器通过 UDP 协议同时处理的 DNS 查询请求的最大数量,对于普通家庭使用,512-1024 足够;对于大型网络或有大量智能家居设备的环境,建议设置为 2048 或更高。
max-concurrent-tcp-sessions:最大并发 TCP 会话数。现代 DNS 查询(尤其是涉及大体积解析记录或加密 DNS 时)会用到 TCP。512 是一个非常稳健的数值,足以应对绝大多数高频场景。
cache-size:DNS 缓存大小我这边是 131072 (128MiB)。根据你的内存调整,大缓存可提升二次访问速度。

/ip/dns/set allow-remote-requests=yes servers=223.5.5.5,223.6.6.6 address-list-extra-time=45m max-concurrent-queries=2048  max-concurrent-tcp-sessions=512 cache-size=131072

指定域名走 HK VPS DNS:

# 有多少域名就写多少条
/ip/dns/static/add address-list=to_hk_domains forward-to=10.252.252.1 match-subdomain=yes name=youtube.com type=FWD
/ip/dns/static/add address-list=to_hk_domains forward-to=10.252.252.1 match-subdomain=yes name=google.com type=FWD
...

测试:
这里不推荐 RouterOS 测试解析,因为只在 RouterOS 本机查询不一定能验证客户端分流。关键是客户端 DNS 必须指向 RouterOS,并由 RouterOS 递归/转发解析,address-list 才会自动生成。

# 首先客户端dns服务器确保已经是到ros上面
PS C:\Users\myluzh> nslookup google.com
服务器:  UnKnown
Address:  172.17.20.1

非权威应答:
名称:    google.com
Addresses:  2404:6800:4005:826::200e
          142.250.199.238
# 查看ros dns cache 看看记录有没有
[admin@HOME2-ROS] /ip/dns/cache> print
[admin@HOME2-ROS] /ip/dns/cache/all> print

[admin@HOME2-ROS] /ip/firewall/address-list> print
;;; created for youtube.com.
 10 D to_hk_domains  142.250.197.110  2026-05-06 18:25:34

创建专用路由表

源地址是 172.17.0.0/16,目标 IP 在 address-list=to_hk_domains 里,就改走 routing-table=to_hk。下一跳为 10.252.252.1,也就是对端 WireGuard 接口地址。

/routing/table/add name=to_hk fib
# 给这个路由表添加默认路由,下一跳是 HK VPS 的 WireGuard 地址:
/ip/route/add dst-address=0.0.0.0/0 gateway=10.252.252.1 routing-table=to_hk
# 用 mangle 标记需要走 HK VPS 的流量:
/ip/firewall/mangle/add chain=prerouting src-address=172.17.0.0/16 dst-address-list=to_hk_domains action=mark-routing new-routing-mark=to_hk passthrough=no comment="domain to HK VPS"

验证

Windows 上建议用 TCP/HTTPS 验证,不只看 tracert
另外 dst-address-list=to_hk_domains 只匹配已经进 address-list 的目标 IP。域名解析出来的新 IP 如果没进这个列表,就不会走 HK VPS。

0x03 进阶:封装 WireGuard UDP 流量

如果担心 WireGuard UDP 特征明显,或者遇到 UDP 限速/阻断,可以在不改动 DNS 分流和策略路由逻辑的前提下,通过一台 PVE 内的 Debian 旁路节点配合VPS 上的 udp2raw,将 WireGuard UDP 封装成 faketcp 流量。
详见:《使用 udp2raw 封装 WireGuard UDP 流量》

ubuntu routeros ros wireguard


正文到此结束
版权声明:若无特殊注明,本文皆为 Myluzh Blog 原创,转载请保留文章出处。
文章内容:https://itho.cn/ros/593.html
文章标题:《RouterOS 7 + Ubuntu VPS:基于 WireGuard 与动态 DNS 列表的策略分流