PSec有两种模式:transport和tunnel。Transport模式双方仍然使用各自的公网IP互联,只不过传送的数据会被自动加密,必须两端的IP固定(否则服务器端也要动态更新客户端IP),tunnel模式则是建立一个类似VPN的点对点通道,需要给通道分配内网IP,在公网IP的要求上则相对比较宽松(只需要客户端更新自己的IP),缺点是浪费20MTU,传输效率稍低。本文讲解如何配置IPSec tunnel连接,以及在其上配置一个GRE隧道。
配置IPSec
这里我们统一把固定IP的一侧叫做服务端,动态IP的一侧叫做客户端。需要准备两组IP地址:
- 服务端的公网IP
- 客户端当前的公网IP
- 服务端的隧道内网IP
- 客户端的隧道内网IP(如果你有多个客户端,在服务器那侧可以填写一个IP段;而对于每台客户端需要填写准确IP)
注:请不要把这里所述隧道内网IP段加入OSPF等动态路由协议的网段。如果需要跑动态路由协议,可以在GRE隧道上另配一组IP。
在建立完IPSec隧道以后,两台设备就可以使用这里规定的内网IP互相通信(即建立VPN)了。
服务端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# 禁止 IPSec 隧道内部流量被 NAT
# (仅 RouterOS 6.42 之前)
/ip firewall nat add action=return chain=srcnat comment=”IPSec Roadwarrior” src-address=<服务器隧道内网 IP 段> dst-address=<客户端隧道内网 IP> place-before=0
# 添加一个新的 policy group, 名字随便取,用默认那个 default 也行
/ip ipsec policy group add name=internal
# 添加一个新的 proposal,规定加密方式
/ip ipsec proposal add auth-algorithms=sha256 enc-algorithms=aes-128-cbc name=internal pfs-group=modp3072
# 添加一个通配符 peer
# 6.42 之前
/ip ipsec peer add dh-group=modp3072 enc-algorithm=aes-128 exchange-mode=ike2 generate-policy=port-strict hash-algorithm=sha256 policy-template-group=internal secret=<密码>
# 6.42 之后
/ip ipsec peer add dh-group=modp3072 enc-algorithm=aes-128 exchange-mode=ike2 generate-policy=port-strict hash-algorithm=sha256 policy-template-group=internal notrack-chain=prerouting secret=<密码>
# 禁用默认的 policy 模板
/ip ipsec policy set 0 disabled=yes
# 添加一个 policy 模板
/ip ipsec policy add dst-address=<客户端隧道内网 IP 段> group=internal proposal=internal protocol=gre src-address=<服务器隧道内网 IP> template=yes
# 如果服务器隧道内网 IP 地址在 /ip addr 里面没有的话,需要手工配置到一个 loopback 端口上
/interface bridge add name=lo
/ip addr add address=<服务器隧道内网 IP> interface=lo
|
客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# 禁止 IPSec 隧道内部流量被 NAT
# (仅 RouterOS 6.42 之前)
/ip firewall nat add action=return chain=srcnat comment=”IPSec Roadwarrior” src-address=<客户端隧道内网 IP> dst-address=<服务器隧道内网 IP> place-before=0
# 添加一个新的 policy group(其实默认的那个也行)
/ip ipsec policy group add name=internal
# 添加一个新的 proposal
/ip ipsec proposal add auth-algorithms=sha256 enc-algorithms=aes-128-cbc name=internal pfs-group=modp3072
# 添加一个新的 peer
# RouterOS 6.42 以前:
/ip ipsec peer add address=<服务器公网 IP> dh-group=modp3072 enc-algorithm=aes-128 exchange-mode=ike2 hash-algorithm=sha256 policy-template-group=internal secret=<密码>
# 6.42 以后(可以在这里直接绕过 NAT,不需要显式增加防火墙规则)
/ip ipsec peer add address=<服务器公网 IP> dh-group=modp3072 enc-algorithm=aes-128 exchange-mode=ike2 hash-algorithm=sha256 policy-template-group=internal notrack-chain=prerouting secret=<密码>
# 添加一个新的 policy
/ip ipsec policy add dst-address=<服务器的隧道内网 IP> proposal=internal protocol=gre sa-dst-address=<服务器的公网 IP> sa-src-address=<你的公网 IP> src-address=<你的隧道内网 IP> tunnel=yes
# 如果客户端隧道内网 IP 地址在 /ip addr 里面没有的话,需要手工配置到一个 loopback 端口上
/interface bridge add name=lo
/ip addr add address=<客户端隧道内网 IP> interface=lo
|
完成以上两部分设置以后,在任意一侧的IPSec Policies里应该可以看到一条连接,PH2 state为established,表示IPSec握手成功。
注:
- 如果你使用图形界面方式来设置的话,在添加policy时protocol请填入数字47(GRE协议号);
- 如果你在配置之前已有对该内网网段的NAT规则并且有设备尝试连接过该IP,NAT规则可能已被conntrack缓存;此时会出现IPSec Policy显示established但是GRE隧道不通的情况。清空conntrack缓存或者重启路由器即可解决。
IPSec调试
1
2
|
/system logging
add topics=ipsec,!debug action=memory
|
客户端动态更新IP
把以下脚本作为你PPPoE拨号端口对应PPP Profile的On Up触发脚本。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
:local WANip [/ip address get [find interface=”<你的 PPPoE interface 名字>”] address]
:global oldWANip
:set WANip [:pick “$WANip” 0 ([:len $WANip] – 3)]
if ($WANip != $oldWANip) do={
:log info “WAN IP changed, fixing IPSec”
# 如果有多个 IPSec 链接就多写几行
/ip ipsec policy set [find sa-dst-address=<服务器公网 IP>] sa-src-address=$WANip
:set oldWANip $WANip
}
|
建立GRE隧道
刚才的IPSec隧道只是点对点连接。如果我们要把点对点以外的流量也路由到隧道那头,就需要GRE协议的帮助。
因为已经建立了IPSec隧道,GRE隧道的配置就变得很简单:
服务端
1
|
/interface gre add local-address=<服务端隧道内网 IP> mtu=1382 name=gre-out1 remote-address=<客户端隧道内网 IP>
|
客户端
1
|
/interface gre add local-address=<客户端隧道内网 IP> mtu=1382 name=gre-out1 remote-address=<服务器端隧道内网 IP>
|
然后,你就可以把路由表里面的部分条目指向这个GRE隧道啦。
注:这边写死了MTU,你可以试试不填让路由器自动计算(提醒:RouterOS的MTU永远算不对)或者自己去算一个更优的值。