IPsec 配置备忘 Part9 - RouterOS

这篇来填一个在 Part1 的时候挖的坑,简单介绍一下怎么在 RouterOS 和 strongSwan 之间配置一个 Site-to-Site 的 IKEv2 VPN。如果你还没有动手实际配置过 strongSwan,我强烈建议你先读完至少 Part1~5 和 Part7,并且自己动手配置一个能用的 strongSwan 服务端。这样至少能保证你会配置 strongSwan,否则同时学习 RouterOS 和 strongSwan 两种配置方法会让人云里雾里。

网络结构

RouterOS 做路由器,用 DHCP 给内网设备分配192.168.50.0/24段中的 IP 地址。并且用 IPsec 的 Tunnel 模式将所有来自此 IP 段的数据转发至服务器22.22.22.22。路由器本身的 IP 并不重要。

Network topology

阅读基本 RouterOS 命令

在本文中我主要使用 RouterOS 命令来表示具体的配置,但是实际情况下调试 WebUI 会更方便。这里提供一张简图解释怎么阅读 RouterOS 的命令:
Command explanation

证书生成

我这里只贴 certtool 的 template 文件,具体的生成指令请参考 Part2。注意 RouterOS 似乎还不支持 Ed25519 证书,所以需要使用 ECDSA 或者是 RSA 证书。

server.tmpl
1
2
3
4
cn = "随意填, 我们使用 DNS SAN 作为 ID"
dns_name = "server.dns.name"
activation_date = "2020-12-01 00:00:00 UTC+0"
expiration_date = "2022-01-01 00:00:00 UTC+0"
routeros.tmpl
1
2
3
4
cn = "同样随意填"
dns_name = "routeros.server.dns.name"
activation_date = "2020-12-01 00:00:00 UTC+0"
expiration_date = "2022-01-01 00:00:00 UTC+0"

strongSwan 配置

由于这是一个 Site-to-Site 连接,所以不需要 Virtual IP 了。配置基于 Part2 中的hosta.conf,同样也是有变化的地方做了注释

server.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
connections {
# 修改连接名不影响功能
conn_routeros {
version = 2
# 使用实际的服务器地址
local_addrs = 22.22.22.22
# 不指定 RouterOS 的地址,因为家宽地址不固定
remote_addrs = %any
# RouterOS 在一阶段握手时不支持 GCM Mode
proposals = aes256-sha256-ecp256
local {
# 使用证书中的 SAN
id = server.dns.name
auth = pubkey
}
remote {
# 使用证书中的 SAN
id = routeros.server.dns.name
auth = pubkey
# (可选) 指定 CA 证书的 DN,以确保对方出示的证书是我们签发的
ca_id = CN=CA_COMMON_NAME
}
children {
child_sa {
# 接受任意目的地流量
local_ts = 0.0.0.0/0
# 客户端 IP 段,需要与 RouterOS DHCP 设定一致
remote_ts = 192.168.50.0/24
mode = tunnel
# RouterOS 支持 GCM 作为实际数据的加密方式
esp_proposals = aes256gcm128-sha256-ecp256
}
}
}
}

RouterOS DHCP 设置

这里假设读者已经会在 RouterOS 中设置 VLAN。所以只是简单的把我的 LAN 配置列出来,方便读者调试。假设使用 ether8,bridge 名称为 LAN,使用 VLAN=50,子网 IP 段是 192.168.50.100-192.168.50.200。也可以参考我以前写的一篇《访客网络配置备忘》。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 将 ether8 加入网桥
/interface bridge port add bridge=LAN interface=ether8 pvid=50 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-tagged
# 在网桥上新建一个 VLAN 接口
/interface vlan add vlan-id=50 interface=LAN name=LAN.ipsec_test
# 编辑网桥的 VLAN 表
/interface bridge vlan add bridge=LAN vlan-ids=50 tagged=LAN untagged=ether8 comment=VLAN_ipsec_test
# 分配网关 IP
/ip address add address=192.168.50.1/24 interface=LAN.ipsec_test
# 添加 DHCP IP 池
/ip pool add name=dhcp_ipsec_test ranges=192.168.50.100-192.168.50.200
# 设置 DHCP 服务器
/ip dhcp-server network add address=192.168.50.0/24 gateway=192.168.50.1
/ip dhcp-server add name=dhcp_ipsec_test interface=LAN.ipsec_test address-pool=dhcp_ipsec_test

注意我们没有设置任何 NAT 规则,现在将一台电脑连接到ether8上,应该能自动获取到 IP 但是上不了网。如果能上网说明你的 NAT 规则设置得太宽了,你在之后需要参考 NAT and Fasttrack bypass 设置额外的规则。

RouterOS IPsec 术语对照表

RouterOS 使用了自己的一套术语来描述 IPsec 相关的配置,我尝试了一下把 RouterOS 中的术语和 strongSwan 的配置文件内容一一对应起来:

RouterOS strongSwan Note
Peer {local,remote}_addrs
Profile IKE_SA parameters No AES GCM
Identities local/remote 身份认证块
Policy {local,remote}_ts 分为普通的 policy 和 policy template
Proposal CHILD_SA parameters 支持 AES GCM
ModeConfig Address Pool, DNS, etc. 暂时用不到。
Group 似乎用来把多个 policy template 合成一组,暂时不清楚是做什么用的。
Active Peer 已建立的 IKE_SA
Installed SA 已建立的 CHILD_SA
Key 暂时不清楚是做什么用的

导入证书

需要导入三个文件,先 scp 进 RouterOS 再/certificate import file-name=xxx.pem即可,WebUI也行。导入后确认 CA 证书显示为T,客户端证书显示为KT

  • 客户端私钥
  • 客户端证书
  • CA 证书
1
2
3
4
5
[admin@RouterOS] > /certificate print            
Flags: K - private-key, L - crl, C - smart-card-key, A - authority, I - issued, R - revoked, E - expired, T - trusted
# NAME COMMON-NAME SUBJECT-ALT-NAME
0 K T routeros.pem_0 routeros DNS:routeros.server.dns.name
1 T ca-cert.pem_0 ca

IPsec 设定

先设置 Profile,Proposal,Peer,Identities

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 指定 IKE_SA 的 ciphersuite
/ip ipsec profile add name=secure_ikesa hash-algorithm=sha256 enc-algorithm=aes-256 dh-group=ecp256 proposal-check=strict
# 指定 CHILD_SA 的 ciphersuite
/ip ipsec proposal add name=secure_childsa auth-algorithms=sha256 enc-algorithms=aes-256-gcm pfs-group=ecp256
# 指定服务器地址和要使用的 Profile
/ip ipsec peer add name=routeros_ipsec address=22.22.22.22 profile=secure_ikesa exchange-mode=ike2
# 配置身份验证,certificate 使用导入的客户端证书
# my-id 和 remote-id 使用 FQDN(i.e. DNS SAN) 并和证书中的值保持一致
/ip ipsec identity add \
peer=routeros_ipsec \
auth-method=digital-signature \
certificate=routeros.pem_0 \
my-id=fqdn:routeros.server.dns.name \
remote-id=fqdn:server.dns.name

这样设定完以后应该在 Active Peers 里看到这个 Peer 处于established状态了。然后再设置 Policy:

1
2
3
4
5
6
7
8
# 这里的 {src,dst}-address 类似 {local,remote}_ts
/ip ipsec policy add peer=routeros_ipsec \
tunnel=yes \
src-address=192.168.50.0/24 \
dst-address=0.0.0.0/0 \
action=encrypt \
level=require \
proposal=secure_childsa

取决于你的防火墙配置,你可能需要显式放行所有将被 IPsec 加密的 forward 流量:

1
/ip firewall filter add chain=forward ipsec-policy=out,ipsec action=accept

最后在服务器上设置 masquerade 规则,应该就能上网了。你应当检查你的外部 IP 是不是确实变成了你的服务器的 IP。

其他资料