WireGuard
WireGuard 是一种现代 VPN 解决方案,提供跨平台的快速、安全加密,并具备详细的配置选项,包括私钥/公钥、VRF 路由和 peer 管理,用于在设备之间建立加密隧道。
WireGuard
WireGuard 是一种简单、快速且现代的 VPN,采用最先进的加密技术。它的目标是比 IPsec 更快、更简单、更精简,并且比 OpenVPN 性能高得多。WireGuard 是一种通用 VPN,既面向嵌入式接口,也面向超级计算机,适用于多种不同的场景。它最初为 Linux 内核发布,现在已跨平台(Windows、macOS、BSD、iOS、Android)并可广泛部署。
WireGuard 上下文中的 vrf 参数
vrf 参数不适用于 WireGuard 接口本身(例如 wg0、wg1),而是适用于用于传输加密数据包的 UDP socket。
WireGuard 的运行中有两个不同的层:
- WireGuard 接口 —— 这是虚拟网络设备,明文(未加密)数据包流经它。这些数据包被加密后通过 UDP socket 发送出去,或者从 UDP socket 进来时被解密。
- UDP sockets —— 它们处理加密流量:从网络接收加密数据包并将加密数据包发送出去。
vrf 参数与 UDP socket 层(情况 2)相关。它指定 socket 应使用**哪个路由表(VRF)**来决定加密数据包的发送或接收方式。
这可确保加密流量遵循正确的路由路径并使用正确的源 IP,防止数据包因其他原因从错误的接口或路由发出的问题。
示例
假设接口
eth1属于 VRFfoo。
如果你希望 WireGuard 通过eth1发送和接收加密数据包,请使用vrf=foo配置 WireGuard。
WireGuard 接口(wg0)本身所处的 VRF 与内部 UDP socket 所使用的vrf参数指定的 VRF 不同,这是正常的。
导入和导出 WireGuard
可以通过多种方式完成配置。下面是一个简单的 WireGuard 导入文件示例:export
通过二维码或文件在客户端设备上导入时,必须指定最低限度的参数。如果客户端地址字段留空,则在生成二维码时会添加默认 IP 地址 192.168.177.2/24。
示例:
interface: wireguard1
public-key: v/oIzPyFm1FPHrqhytZgsKjU7mUToQHLrW+Tb5e601M=
private-key: KMwxqe/iXAU8Jn9dd1o5pPdHep2blGxNWm9I944/I24=
allowed-address: 192.168.88.3/24
client-address: 192.168.88.3/32
client-endpoint: example.com:13231
使用 /interface/wireguard/wg-import file= 导入时,如果 WireGuard 导入文件以 # 开头,你可能会遇到 Could not parse 错误。
请使用如下示例中的简洁格式:
[Interface]
Address =192.168.88.3/24
ListenPort = 13533
PrivateKey = UBLqJEFZZf9wszZSUF2BPWa9dsMX99RbEcxlNfxWffk=
可以使用 config-string 参数导入配置:
/interface/wireguard/wg-import config-string="
[Interface]
Address =192.168.88.3/24
ListenPort = 13533
PrivateKey = UBLqJEFZZf9wszZSUF2BPWa9dsMX99RbEcxlNfxWffk=
[Peer]
PublicKey = EoF7HlFu3fbOnuYbyGqLMJkPZgQk9n3WwONZuJZ6qWc=
Endpoint = 199.168.100.10:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25"
当你遇到回复流量的源地址错误的问题时,使用 NAT 将数据包源地址转换为你的 loopback 接口是一种常见的变通方法。此方法有助于确保数据包通过网络回传时源地址是一致的且正确的。
通过 WireGuard peer 导出(配置文件或二维码)提供给客户端的 "AllowedIPs" 配置无法更改,它被设置为 "0.0.0.0/0, ::/0"。如果你需要修改远端的这些值,必须通过用于 WireGuard 连接的远程 peer 软件来完成。从 7.21 版本开始已添加支持。
应用示例
站点到站点 WireGuard 隧道
考虑下面所示的设置。两个远程办公室路由器连接到互联网,办公室工作站位于 NAT 之后。每个办公室都有自己的本地子网,Office1 为 10.1.202.0/24,Office2 为 10.1.101.0/24。两个远程办公室都需要到路由器后面本地网络的安全隧道。

WireGuard 接口配置
首先,在两个站点上配置 WireGuard 接口,以允许自动生成私钥和公钥。两台路由器的命令相同:
/interface/wireguard
add listen-port=13231 name=wireguard1
现在打印接口详情时,应该可以看到私钥和公钥,以便进行交换。
警告
远端设备从不需要私钥 —— 这正是它被称为私钥的原因。 Office1
/interface/wireguard/print
Flags: X - disabled; R - running
0 R name="wireguard1" mtu=1420 listen-port=13231 private-key="yKt9NJ4e5qlaSgh48WnPCDCEkDmq+VsBTt/DDEBWfEo="
public-key="u7gYAg5tkioJDcm3hyS7pm79eADKPs/ZUGON6/fF3iI="
Office2
/interface/wireguard/print
Flags: X - disabled; R - running
0 R name="wireguard1" mtu=1420 listen-port=13231 private-key="KMwxqe/iXAU8Jn9dd1o5pPdHep2blGxNWm9I944/I24="
public-key="v/oIzPyFm1FPHrqhytZgsKjU7mUToQHLrW+Tb5e601M="
Peer 配置
Peer 配置定义了谁可以使用 WireGuard 接口,以及可以通过它发送什么样的流量。要标识远程 peer,必须将其公钥与所创建的 WireGuard 接口一起指定。
Office1
/interface/wireguard/peers
add allowed-address=10.1.101.0/24,10.255.255.2/32 endpoint-address=192.168.80.1 endpoint-port=13231 interface=wireguard1 \
public-key="v/oIzPyFm1FPHrqhytZgsKjU7mUToQHLrW+Tb5e601M="
Office2
/interface/wireguard/peers
add allowed-address=10.1.202.0/24,10.255.255.1/32 endpoint-address=192.168.90.1 endpoint-port=13231 interface=wireguard1 \
public-key="u7gYAg5tkioJDcm3hyS7pm79eADKPs/ZUGON6/fF3iI="
IP 和路由配置
最后,必须配置 IP 和路由信息,以允许流量通过隧道发送。
Office1
/ip/address
add address=10.255.255.1/30 interface=wireguard1
/ip/route
add dst-address=10.1.101.0/24 gateway=wireguard1
Office2
/ip/address
add address=10.255.255.2/30 interface=wireguard1
/ip/route
add dst-address=10.1.202.0/24 gateway=wireguard1
防火墙注意事项
默认的 RouterOS 防火墙会阻止隧道正常建立。两个站点上都必须在任何 drop 规则之前,在 "input" 链中接受该流量。
Office1
/ip/firewall/filter
add action=accept chain=input dst-port=13231 protocol=udp src-address=192.168.80.1
Office2
/ip/firewall/filter
add action=accept chain=input dst-port=13231 protocol=udp src-address=192.168.90.1
"forward" 链也可以限制子网之间的通信,因此此类流量也应在任何 drop 规则之前被接受。
Office1
/ip/firewall/filter
add action=accept chain=forward dst-address=10.1.202.0/24 src-address=10.1.101.0/24
add action=accept chain=forward dst-address=10.1.101.0/24 src-address=10.1.202.0/24
Office2
/ip/firewall/filter
add action=accept chain=forward dst-address=10.1.101.0/24 src-address=10.1.202.0/24
add action=accept chain=forward dst-address=10.1.202.0/24 src-address=10.1.101.0/24
RoadWarrior WireGuard 隧道
RouterOS 配置
添加一个新的 WireGuard 接口并为其分配一个 IP 地址。
/interface/wireguard
add listen-port=13231 name=wireguard1
/ip/address
add address=192.168.100.1/24 interface=wireguard1
添加新的 WireGuard 接口会自动生成一对私钥和公钥。在你的远程设备上配置公钥。要获取公钥值,请打印接口详情。
[admin@home] > /interface/wireguard/print
Flags: X - disabled; R - running
0 R name="wireguard1" mtu=1420 listen-port=13231 private-key="cBPD6JNvbEQr73gJ7NmwepSrSPK3np381AWGvBk/QkU="
public-key="VmGMh+cwPdb8//NOhuf1i1VIThypkMQrKAO9Y55ghG8="
接下来的步骤中,获取远程设备的公钥。拿到后,通过指定远程设备的公钥以及将允许通过 WireGuard 隧道的地址,添加一个新的 peer。
/interface/wireguard/peers
add allowed-address=192.168.100.2/32 interface=wireguard1 public-key="<paste public key from remote device here>"
防火墙注意事项
如果你配置了默认或严格的防火墙,则需要允许远程设备与你的设备建立 WireGuard 连接。
/ip/firewall/filter
add action=accept chain=input comment="allow WireGuard" dst-port=13231 protocol=udp place-before=1
要允许远程设备连接到 RouterOS 服务(例如请求 DNS),请在 input 链中允许 WireGuard 子网。
/ip/firewall/filter
add action=accept chain=input comment="allow WireGuard traffic" src-address=192.168.100.0/24 place-before=1
或者直接将 WireGuard 接口添加到 "LAN" 接口列表。
/interface/list/member
add interface=wireguard1 list=LAN
iOS 配置
从 App Store 下载 WireGuard 应用程序。打开它并从零开始创建一个新配置。

首先,为你的连接指定一个 "Name" 并选择生成密钥对。生成的公钥是 RouterOS 侧 peer 配置所必需的。

在 "Addresses" 字段中指定一个与服务器侧配置的子网相同的 IP 地址。此地址用于通信。在本例中,RouterOS 侧使用 192.168.100.1/24。你可以在此处使用 192.168.100.2。
如有必要,配置 DNS 服务器。如果 RouterOS 侧的 IP/DNS 部分下将 allow-remote-requests 设置为 yes,你可以在此处指定远程 WireGuard IP 地址。

选择 "Add peer" 以显示更多参数。
"Public key" 值是 RouterOS 侧 WireGuard 接口上生成的公钥值。
"Endpoint" 是 iOS 设备可以通过互联网与之通信的 RouterOS 设备的 IP 或 DNS 加端口号。
"Allowed IPs" 设置为 0.0.0.0/0,以允许所有流量通过 WireGuard 隧道发送。

Depending on your configuration, you may need to add a NAT rule
chain=dstnat action=dst-nat to-ports=port protocol=udp in-interface=interface dst-port=port
Windows 10 配置
从 WireGuard 下载 WireGuard 安装程序并以管理员身份运行。

按 <kbd>Control</kbd>+<kbd>N</kbd> 添加一个新的空隧道。为接口添加一个名称 —— 公钥应会自动生成。将其复制到 RouterOS peer 配置中。
将其添加到服务器配置中。完整配置应如下所示(在 [Interface] 部分保留你自动生成的 PrivateKey):
[Interface]
PrivateKey = your_autogenerated_private_key=
Address = 192.168.100.2/24
DNS = 192.168.100.1
[Peer]
PublicKey = your_MikroTik_public_KEY=
AllowedIPs = 0.0.0.0/0
Endpoint = example.com:13231
保存并激活
多 WAN 设置
对于 WireGuard,不存在服务器-客户端关系。两端都可以作为 endpoint,如果它们的配置中定义了 endpoint,两端都会彼此发送 UDP 握手消息。你可以在 peer 设置中启用 "responder" 选项来模拟服务器-客户端行为,此时 "server" peer 仅回复来自 "client" peer 的握手消息,自身不发送握手消息。
由于这种隧道建立行为,来自 WireGuard 隧道不同 endpoint 的握手消息会被视为两个独立的连接。
在到 "client" peer 存在多条路径的设置中,你需要考虑到这一点,因为这可能导致 "server" 通过不同于入站路由的其他路由回复 "client"。
下面是一个配置示例,它解决了此行为并确保 "server" 使用入站路由回复 "client"。
配置示例
本示例不包含 WireGuard 接口配置,因为它适用于 RoadWarrior 和 Site to Site 两种设置,以及具有两条 WAN 连接的场景,例如 PCC 设置。
要使这些规则按预期工作,你需要在 WireGuard peer 设置中启用 "responder" 选项,因为由于路由未被标记,"server" 可能会通过错误的接口发送握手消息。
/ip/firewall/mangle
add action=add-src-to-address-list chain=prerouting address-list=WAN2_WireGuard_clients address-list-timeout=1m dst-port=13231 in-interface=ether2 protocol=udp comment="add source IP address of WAN2 incoming WireGuard traffic to address list"
add action=mark-connection chain=output dst-address-list=WAN2_WireGuard_clients dst-port=13231 new-connection-mark=wan2 protocol=udp comment="mark WireGuard connection to the client peer by checking destination address from the address list"
add action=mark-routing chain=output connection-mark=wan2 dst-port=13231 new-routing-mark=wan2 protocol=udp comment="ensure that WireGuard traffic uses routing table associated with the WAN2 incoming interface"
add action=add-src-to-address-list chain=prerouting address-list=WAN3_WireGuard_clients address-list-timeout=1m dst-port=13231 in-interface=ether3 protocol=udp comment="add source IP address of WAN3 incoming WireGuard traffic to address list"
add action=mark-connection chain=output dst-address-list=WAN3_WireGuard_clients dst-port=13231 new-connection-mark=wan3 protocol=udp comment="mark WireGuard connection to the client peer by checking destination address from the address list"
add action=mark-routing chain=output connection-mark=wan3 dst-port=13231 new-routing-mark=wan3 protocol=udp comment="ensure that WireGuard traffic uses routing table associated with the WAN3 incoming interface"
/ip/firewall/nat
add action=masquerade chain=srcnat log=yes out-interface=ether2 comment="ensure that packet has source IP of WAN2 interface"
add action=masquerade chain=srcnat log=yes out-interface=ether3 comment="ensure that packet has source IP of WAN3 interface"
第一条 mangle 规则通过匹配入站 WireGuard 握手的目标端口来捕获源 IP 地址,并将其添加到列表中,该列表稍后用于标记出站的 WireGuard 握手。超时可确保同一源 IP 地址稍后可以通过不同的 WAN 接口建立 WireGuard 隧道。
第二条 mangle 规则标记用于路由标记的连接,并确保在 IP 地址从 address list 中消失且隧道建立后,标记仍保留在连接上。
第三条 mangle 规则强制数据包对第二个 WAN 接口使用正确的路由表。
最后一条 NAT 规则确保数据包使用正确的源 IP 发送,因为它不会被 mangle 规则调整。如果没有此规则,数据包可能会根据具体设置而具有不同的源 IP。
这些规则为 WAN3 重复了一遍,以确保 WAN3 接口也可用于 WireGuard。
这组规则确保 WireGuard 隧道在接收到入站握手的接口上建立。
2FA 设置
在 RouterOS v7 中,HotSpot 服务可以绑定到 WireGuard 接口。这允许管理员将 WireGuard 的高性能加密与 HotSpot 的强制门户功能结合起来,通过本地数据库、User Manager 或 RADIUS 支持额外的用户级认证。OTP 功能进一步增强了安全性。
配置示例
确保你的设备上已配置 WireGuard 接口:
/interface/wireguard> print
Flags: X - DISABLED; R - RUNNING
0 R name="wg1" mtu=1420 listen-port=49422
public-key="MikroTikMikroTikMikroTik="
在 WireGuard 接口上设置 HotSpot:
/ip/hotspot> setup
Select interface to run HotSpot on
hotspot interface: wg1
or
/ip/hotspot/add interface=wg1
*Supported from 7.22
HotSpot 设置完成后,一旦 WireGuard peer 连接,就需要额外登录门户才能继续。可以使用常规的 HotSpot 用户名/密码授权。为了更好的安全性,请使用 /ip/hotspot/user 的 otp-password 或 /user-manager/user 的 totp-password 字段。添加一个带有 totp-secret 的用户:
/ip/hotspot/user/add name=peer1 totp-secret=HVR4CFHAFOWFGGFAGSA5JVTIMMPG6GMT
你可以找到多个开源的 totp 生成工具,它们可以为你提供合适的密钥以及将其导入到你的 "authenticator" 应用所需的选项。
设置完成后,在你的设备上启动 WireGuard。经 WireGuard/HotSpot 服务器成功授权后,会出现 HotSpot 登录页面,你必须输入 HotSpot 用户名以及来自 authenticator 应用的 TOTP 6 位密码(每 30 秒变化一次)。
你应该为 HotSpot 使用 HTTPS 登录页面,并确保 WireGuard peer 能够验证登录页面的证书。