最新消息:点击查看大S的省钱秘笈

二级路由(旁路由) GRE tunnel over IPSec

湾区生活 Slyar 242浏览 0评论

最近几天AT&T Fiber有点抽风,晚上7-11点微信就没法用了,一直无法连接。发了个AT&T帖子然后找客服几天也无果,也不知道啥时候能修好,于是开始自己troubleshooting. 在电脑上装了个Mac版微信,也无法连接,这是个好事,证明Mac客户端跟手机客户端连接的是同一个服务端。又装了个Wireshark抓微信app的包,发现去101.32.104.41这个IP的包都不通, Google了一下这个IP发现属于腾讯新加坡数据中心,那基本没错了。新加坡和香港是微信海外的2个比较大的数据中心。

City: Singapore
ISP: Tencent cloud computing
Autonomous system number (ASN): 132203
Autonomous system organization: Tencent Building, Kejizhongyi Avenue

在正常和晚上受影响期间分别traceroute了一下这个IP,发现在晚上受影响的时间,路径上的192.205.37.70无法联通,又查了一下这个IP发现192.205.36.0/23属于AT&T Services, Inc. (AS7018),这就确认问题肯定是在AT&T了。

既然确定了问题那就开始搞tunnel了,本来一开始想的是搞一台有公网IP的VM然后在自己的边界路由器上搞一个GRE Tunnel就行了,但是UDM Pro居然不支持点到点的GRE Tunnel,真的是非常沙雕了。UDM Pro只支持site to site VPN但想要实现我们静态路由的目的我们还是需要一个GRE Tunnel在上面。考虑了一下之后决定用二级路由(旁路由)来实现。二级路由可以是任何支持VPN和GRE的路由器,比如OpenWRT,DD-WRT之类的,我家里有一台闲置的MikroTik路由器(RouterOS),正好可以拿来用。下面是方案:

家里的LAN网段是192.168.0.0/23。RouterOS的LAN口(ether5)插交换机,WAN口(ether1)插UDM Pro(Port#2),在UDM Pro上新建一个新网络10.0.20.1/24 VLAN 20,给Port#2加一个port profile VLAN 20,在RouterOS上给WAN口设静态IP 10.0.20.20/24,LAN口DHCP获取IP就可以了。(为了方便可以给RouterOS的Bridge管理口设一个静态IP比如192.168.1.88/23方便访问,不影响方案)。至此RouterOS应该可以访问Internet了,路径是0.0.0.0/0 -> ether1 -> 10.0.20.20 -> 10.0.20.1 (Gateway UDM Pro) -> AT&T Fiber modem -> Internet.

下一步就是建立IPSec连接,我们需要一个对端,这里可以用GCP, AWS, Azure或者是OCI(Oracle Cloud),你可以用这些服务商提供的IPSec服务(一般是免费的)也可以用Strongswan之类的软件自建IPSec服务器。这里假设我们已经得到了服务端的公网IP 152.67.254.129,内网网段10.0.0.0/16。得到了这些信息之后我们就可以在RouterOS上建立IPSec连接了。

有几个点需要注意。因为我们是用二级路由而不是边界路由做IPSec,所以这里就涉及到一个NAT内网穿透的过程,一般的公网IP IPSec用的是UDP 500端口,而这里我们需要启用NAT traversal来使用UDP 4500端口通信。我们这一端的源IP是二级路由WAN口的IP (10.0.20.20)而不是边界路由的WAN口IP

> ip ipsec profile print
1   name="myvpn3" hash-algorithm=sha1 enc-algorithm=aes-256,aes-128 dh-group=ecp384,modp2048,modp1024 lifetime=1d proposal-check=obey nat-traversal=yes dpd-interval=10s dpd-maximum-failures=5


> ip ipsec identity print
0    peer=myvpn3 auth-method=pre-shared-key secret="YOUR SHARED SECRET" generate-policy=no


> ip ipsec proposal print
1    name="myvpn3" auth-algorithms=sha256,sha1 enc-algorithms=aes-256-cbc,aes-256-ctr,3des lifetime=30m pfs-group=modp1024


> ip ipsec policy print
#      PEE TUN SRC-ADDRESS                                    DST-ADDRESS
1   A  myv yes 192.168.0.0/23                                 10.0.0.0/16


> ip ipsec peer print
0     name="myvpn3" address=152.67.254.129/32 local-address=10.0.20.20 profile=myvpn3 exchange-mode=main send-initial-contact=yes

完成设置之后就可以看到IPSec连接已经成功建立,此时我们应该可以ping通对端内网VM的内网IP (这里是10.0.0.83)

至此我们已经成功建立IPSec VPN连接完成了2个内网的互联,但因为IPSec没有interface的概念,想要完成静态路由转发流量,我们还需要分别在对端VM和RouterOS上建立GRE隧道。

# 启动GRE隧道模块
sudo modprobe ip_gre
# 增加一个GRE隧道接口gre1,192.168.1.88是RouterOS的内网IP,这个IP基于IPSec连接是可达的
ip tunnel add gre1 mode gre remote 192.168.1.88 local 10.0.0.83 ttl 255
# 给GRE隧道一个IP地址10.10.10.1
ip addr add 10.10.10.1/30 dev gre1
ip link set gre1 up
# 在RouterOS上建立隧道
> interface gre print
0  R name="gre-tunnel1" mtu=auto actual-mtu=1398 local-address=192.168.1.88 remote-address=10.0.0.83 dscp=inherit clamp-tcp-mss=yes dont-fragment=no allow-fast-path=yes
# 给GRE隧道一个IP地址10.10.10.2
> ip address print
#   ADDRESS            NETWORK         INTERFACE
0   192.168.1.88/23    192.168.0.0     bridge
1   10.0.20.20/24      10.0.20.0       ether1
2   10.10.10.2/32      10.10.10.1      gre-tunnel1

隧道建立完成后,下一步在RouterOS上建立静态路由,把去微信新加坡数据中心的流量转到GRE tunnel里

> ip route print
Flags: X - disabled, A - active, D - dynamic, C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme,
B - blackhole, U - unreachable, P - prohibit
#      DST-ADDRESS        PREF-SRC        GATEWAY            DISTANCE
0 A S  0.0.0.0/0                          10.0.20.1                 1
1 ADC  10.0.20.0/24       10.0.20.20      ether1                    0
2 ADC  10.10.10.1/32      10.10.10.2      gre-tunnel1               0
3 A S  101.32.0.0/16                      gre-tunnel1               1
4 ADC  192.168.0.0/23     192.168.1.88    bridge                    0

此时如果你从RouterOS ping 101.32.104.41发现是不通的,因为我们还缺少一个重要步骤叫做masquerade即IP地址伪装,与SNAT类似,用路由器发出接口的IP地址替换源IP。这里需要做2步,一步在RouterOS给GRE接口做,另一步在远程VM上做使得我们的数据包可以通过远程网络的默认网关到达Internet

# RouterOS firewall rule
> ip firewall nat print
0    chain=srcnat action=masquerade out-interface=gre-tunnel1

# 这个是在远程VM上
# ip route
default via 10.0.0.1 dev ens3 proto dhcp src 10.0.0.83 metric 100
10.0.0.0/24 dev ens3 proto kernel scope link src 10.0.0.83
10.10.10.0/30 dev gre1 proto kernel scope link src 10.10.10.1
169.254.0.0/16 dev ens3 proto dhcp scope link src 10.0.0.83 metric 1000

# iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE

最后一步就是在UDM Pro上再设置一个静态路由,把我们内网去往微信新加坡数据中心的流量转到我们的二级路由上。至此我们的整个方案就全部实施完毕了,内网设备使用微信的流量会自动通过GRE隧道,而其他网站的流量则依旧通过AT&T网络,最小程度减少对速度的影响,而且内网设备无需额外配置任何VPN。还有一些进阶设置比如在RouterOS上通过脚本监控通过AT&T网络到微信新加坡数据中心的可达性,启用GRE静态路由当AT&T网络不可达,移除静态路由当网络恢复,这样可以更进一步减少对网络速度的影响。完整的路径如下:

内网iPhone微信客户端(eg. 192.168.0.11) -> 内网Gateway (192.168.0.1) -> 边界路由静态路由match 101.32.0.0/16 目标下一跳 10.0.20.20 (RouterOS) -> RouterOS静态路由match 101.32.0.0/16 目标下一跳10.10.10.1 -> GRE Tunnel 10.10.10.2 -> IP地址伪装 -> 远程GRE Tunnel 10.10.10.1 -> IP地址伪装 -> 远程网络默认网关 10.0.0.1 -> Internet -> 微信新加坡数据中心

相关链接:
https://wiki.mikrotik.com/wiki/Manual:IP/Firewall/NAT
https://help.mikrotik.com/docs/display/ROS/IPsec
https://docs.sim-cloud.net/en/operations/vpn-configurations/ipsec-site-to-site/mikrotik-behind-nat.html
https://docs.oracle.com/en-us/iaas/Content/Network/Tasks/overviewIPsec.htm

转载请注明:Slyar Home » 二级路由(旁路由) GRE tunnel over IPSec

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址