分类目录归档:VyOS/EdgeOS

如何设置分支机构互连 (2) GRE over VPN

简介

Policy-based VPN有很大的局限性,尤其是无法支持路由。而常用的基于路由的IPSec VPN所用到的VTi接口,要求两端WAN口都是固定IP,需要专线,这对大多数中小企业来说网络使用成本太高。

我们这里介绍如何配置GRE over IPSec, 通过GRE隧道,就可以使用各种路由协议灵活配置你的网络。

下图是本文用到示范网络。左端是EdgeRouter,右端是VyOS。

预先准备

路由设备

实现本文介绍的功能,你需要一台EdgeRouter和安装好VyOS的软路由。在参考本文开始配置以前,我们假定大家已经按照介绍VyOS一文完成了VyOS的初始化配置。使用EdgeOS的用户,可以使用系统自带的wizard完成初始配置。

设置动态域名

考虑到大多数客户的宽带接入都是动态IP地址, 因此需要通过域名来获取当前使用的IP地址。我们假定左边EdgeOS的域名是edgeos.ddns.com,右边的VyOS的域名是vyos.ddns.com

如何配置动态域名,请参见本站另一篇帖子EdgeRouter/VyOS配置DDNS动态域名

基于规则的IPSec VPN

GRE隧道两端各用一个固定IP作为端口外围地址。

你可以使用路由器上任何接口IP地址,但是有一个问题就是,如果那个接口离线,相应的GRE接口也会进入离线状态。因此使用永远在线的loopback接口就有优势了。

配置loopback地址

下面我们为EdgeOS端loopback端口配置一个IP地址,10.255.0.254/32。

configure
set interfaces loopback lo address 10.255.0.254/32

同样,再到VyOS配置相应的loopback地址,10.255.1.254/32。

configure
set interfaces loopback lo address 10.255.1.254/32

配置IPSec隧道

我们首先要配置一条承载GRE的IPSec隧道,具体配置方法我们已经在如何设置分支机构互连(一)IPSec VPN一文中有了详细解释,这里就不再赘述。请注意替换原文中local prefix和remote prefix分别为两端的loopback地址。

完成后,可以从EdgeOS端使用以下命令测试隧道是否通畅。

sudo ping 10.255.1.254 -I 10.255.0.254

如果隧道还没建立起来,IPSec进程在监控到隧道流量后,会自动启动连接,连接过程中丢失几个包是正常现象。

GRE接口

GRE隧道配置有5个必配要素:

  • 隧道名称,以tun起头,后面接从0到255的数字。
  • 隧道本地外部地址 local-ip
  • 隧道对端外部地址 remote-ip
  • 隧道内部地址 address
  • 最大传输单元 mtu,这个是包括IP包头的,和MSS不一样。

由于GRE是点到点隧道。因此隧道内两端各只有一个IP地址,因此CIDR必须是30。下面是EdgeOS侧GRE隧道配置的参考命令:

set interfaces tunnel tun0 address 10.254.0.1/30
set interfaces tunnel tun0 description 'EdgeOS ... (ipsec) ... VyOS'
set interfaces tunnel tun0 encapsulation gre
set interfaces tunnel tun0 local-ip 10.255.0.254
set interfaces tunnel tun0 mtu 1390
set interfaces tunnel tun0 multicast disable
set interfaces tunnel tun0 remote-ip 10.255.1.254

同样,我们在VyOS也配置相应的GRE隧道:

set interfaces tunnel tun0 address 10.254.0.2/30
set interfaces tunnel tun0 description 'VyOS ... (ipsec) ... EdgeOS'
set interfaces tunnel tun0 encapsulation gre
set interfaces tunnel tun0 local-ip 10.255.1.254
set interfaces tunnel tun0 mtu 1390
set interfaces tunnel tun0 multicast disable
set interfaces tunnel tun0 remote-ip 10.255.0.254

防火墙策略

由于我们相当与在WAN口对接了GRE隧道(IPSec流量来自于WAN口),因此还需要对应地配置一条防火墙策略,允许WAN口接入GRE隧道。

EdgeOS的auto-firewall-nat-exclude并不包括这一条规则,需要参考如下命令添加:

set firewall name WAN_LOCAL rule 210 action accept
set firewall name WAN_LOCAL rule 210 description 'ipsec'
set firewall name WAN_LOCAL rule 210 ipsec match-ipsec
set firewall name WAN_LOCAL rule 210 log disable
set firewall name WAN_LOCAL rule 210 protocol all

VyOS端,我们之前已经做过这个配置,不必重复了。

路由

要让流量通过GRE隧道转发,还需要配置相应的路由。下面我们就用静态路由作为参考。

EdgeOS端

set protocols static route 10.1.0.0/24 next-hop 10.254.0.2 description 'right side via GRE over IPSec'
set protocols static route 10.1.0.0/24 next-hop 10.254.0.2 distance 100
commit;save;exit

VyOS端

set protocols static route 10.0.0.0/24 next-hop 10.254.0.1 description 'right side via GRE over IPSec'
set protocols static route 10.0.0.0/24 next-hop 10.254.0.1 distance 100
commit;save;exit

翻回墙内听音乐

简介

在美久居,有一项非常不方便的地方,就是无法使用QQ音乐,网易云音乐来听中文歌。大多数歌曲都会显示无法播放。

这些应用的服务器端,会根据你的IP地址来判断你的位置。如果发现你在境外,就会拒绝你的播放请求。

解决这个问题有很多方法,最快的方法是使用VPN软件。然而软件VPN有两个问题,一是所有流量发送到国内不方便,而且还要人为开启连接;二是类似Sonos这样的离线播放器无法使用。

我们这里介绍通过配置Ubiquiti的EdgeRouter来实现全家在线听歌,非常便利。Ubiquiti这个品牌国内不太响亮,他在网络界算是比较特立独行,以互联网直销为主,主打性价比和稳定性,是市值百亿美元上市公司。他家的Edgerouter-X,被国内网友称为弱电箱之王,京东售价不到400元。

这里介绍如何设置家里路由器,方便访问墙内的音乐网站服务。同时我们还利用家里的路由器,作为移动VPN接入点,这样即使出门在外也能随时随地听歌。

下面是这个方案的示意图。这里有4个元素,手机,家里的路由器EdgeOS,中国的虚拟路由器VyOS,以及墙内的服务器,包括DNS服务器(114.114.114.114)以及音乐服务器(music.qq.com等)。

这个方法的原理比较简单,只需要实现几个步骤:

  • 建立VPN隧道,连接墙内VyoS和家里的EdgeRouter;
  • 智能引流,区分回国流量和其他互联网流量;
  • 定向流量转发,只有访问音乐网站的流量走隧道回墙内;
  • 手机通过IPSec VPN与本地路由器(USA)建立连接,所有的流量都通过隧道(蓝色)到达本地路由器,在那里,流量根据目的(域名)进行分流:访问墙内音乐网站的流量通过另外一条VPN隧道(红色)流向远端路由器(China),在那里解密出隧道,再通过互联网(绿色)访问相应的网站;而其他流量都从本地路由器直接转发到互联网。

本地路由器在上述方案中扮演了核心角色。其中一个重要的功能是智能分流,也就是根据域名来确定流量的走向。大家可以参考下面的功能概要图。

  1. 从手机通过IPSec隧道发送过来的流量(esp1) 经过WAN口防火墙转发到IPSec功能模块(红色);解密后的流量(蓝色)再次经过DNAT替换原来的DNS查询包目标地址为路由器内loopback接口地址(10.255.0.254),通过防火墙后发送到DNSMASQ模块(绿色);
  2. 家里设备流量通过局域网直接使用DNSMASQ作为DNS代理;
  3. DNSMASQ模块发现域名与预先设置的分流域名匹配,随之向墙内的上游DNS服务器(114.114.114.114)发出查询请求(紫色);
  4. 路由转发引擎根据路由表将该查询请求(紫色)转发到IPSec加密模块;加密过的流量通过WAN口发送到墙内的远端路由器。

介绍完原理,下面我们来看看具体如何配置。


预先准备

路由设备

实现本文介绍的功能,你需要在家里使用一台EdgeRouter,国内要有一台安装好VyOS的软路由(EdgeRouter也可以)。

配置拨号VPN以及回国IPSec隧道


DNSMASQ智能分流

内部DNS服务器

我们先给loopback接口设置地址:

configure
set interfaces loopback lo address 10.255.0.254/32

然后是修改/config/ipsec.d/ipsec.conf,把loopback地址设置为下发的客户端DNS服务器地址

...
#rightdns=8.8.8.8,8.8.4.4
rightdns=10.255.0.254
...

LAN口启用DNS转发服务

要让DNSMASQ起作用,前提是主机需要使用EdgeRouter的DNS服务。因此在配置EdgeRouter的DHCP服务器时,下发的DNS配置必须指向路由器,而不是公网DNS,如114.114.114.114或者8.8.8.8。

set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 dns-server 10.255.0.254

重定向DNS请求

某些Linux客户端,不一定会使用下发的DNS,因此,需要将所有的DNS请求都重定向到loopback接口。我们知道,DNS的协议非常简单,使用UDP的端口53,查询也就一个包,因此我们可以配置如下目标地址转换来实现重定向。

set service nat rule 1000 destination port 53
set service nat rule 1000 source address 10.255.255.0/24
set service nat rule 1000 inbound-interface eth0
set service nat rule 1000 inside-address address 10.255.0.254
set service nat rule 1000 inside-address port 53
set service nat rule 1000 log disable
set service nat rule 1000 protocol udp
set service nat rule 1000 type destination

防火墙地址集

我们需要建立一个防火墙地址集,用于收藏远端DNS服务器解析出来的IP地址。

set firewall group address-group MUSIC

启用DNSMASQ

第一步是启用DNSMASQ;然后,确保DNSMASQ会监听loopback接口上收到的DNS请求;

set service dhcp-server use-dnsmasq enable

set service dns forwarding cache-size 1500
set service dns forwarding except-interface=eth0
set service dns forwarding name-server 8.8.8.8
set service dns forwarding name-server 8.8.4.4

set service dns forwarding options listen-address=10.255.0.254

注意上文中,我们启用了一条options配置,设置list-address为loopback接口IP,这一条很关键,否则DNSMASQ不会响应来自IPSec隧道的请求。

域名分析

上述智能分流要用到的一个重要数据是相关的域名列表。我们知道,一个应用往往会用到多个域名。光dropbox,就会用到十多个不同的域名。dropbox比较有良心,官网直接列出自己使用的域名,但大多数商家没有这样做,因此我们需要自己有办法来分析哪些域名会被用到。

分析域名的一个最有用的工具就是tcpdump。我们知道DNS请求有一个特定的端口号:53,因此我们只要去截获匹配端口号53以及相应主机的IP,就可以捕获所有的相关DNS请求。参考EdgeOS命令如下:

sudo tcpdump -n -i switch0 port 53 and host 10.1.8.106

下面是捕获的截屏

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on switch0, link-type EN10MB (Ethernet), capture size 262144 bytes
06:46:53.276711 IP 10.1.8.106.52757 > 10.1.8.254.53: 3794+ A? google.com. (28)
06:46:53.277244 IP 10.1.8.254.53 > 10.1.8.106.52757: 3794 1/0/0 A 216.58.194.206 (44)

我们可以看到主机10.1.8.106向路由器发送了一条域名解析申请,域名是”google.com“,以及相应的回复。

我们可以用这个办法,在打开相关应用时,监控DNS请求,再把相应的域名添加到DNSMASQ的域名清单里。

第三方dnsmasq配置文件

如果你需要处理的域名很多,或者想用第三方收集的配置文件,将文件中的server/ipset一行行地添加到配置里,将是一件很繁琐的事情。

经过分析,我们发现在EdgeOS里,所有配置为service dns forwarding options 后面的文本,都会原样不动地转换为/etc/dnsmasq.conf里的对应一行。因此,我们可以调用dnsmasq的conf-file功能,以简化配置。

具体操作时,你可以将相应的配置文件,保存在/config目录下,例如保存为/config/dnsmasq/dnsmasq-china-muisc.conf;然后添加以下配置。

set service dns forwarding options conf-file=/config/dnsmasq/dnsmasq-china-muisc.conf.conf

下面是dnsmasq-china-muisc.conf的示范文件,

ipset=/ximalaya.com/xmcdn.com/163.com/126.net/163yun.com/MUSIC
server=/ximalaya.com/xmcdn.com/163.com/126.net/163yun.com/114.114.114.114
server=/kugou.com/kuwo.cn/114.114.114.114
ipset=/hicloud.com/huawei.com/MUSIC
server=/hicloud.com/huawei.com/114.114.114.114
ipset=/kugou.com/kuwo.cn/MUSIC
server=/y.qq.com/music.qq.com/114.114.114.114
ipset=/y.qq.com/music.qq.com/MUSIC
server=/music.tcdn.qq.com/114.114.114.114
ipset=/music.tcdn.qq.com/MUSIC
server=/taobao.com/114.114.114.114
server=/alicdn.com/alimama.com/alibabadns.com/tbcache.com/114.114.114.114
server=/alibabacorp.com/114.114.114.114
ipset=/taobao.com/MUSIC
ipset=/alicdn.com/alimama.com/alibabadns.com/tbcache.com/MUSIC
ipset=/alibabacorp.com/MUSIC
server=/sonos.com/114.114.114.114
ipset=/sonos.com/MUSIC
server=/sonoschina.com/114.114.114.114
ipset=/sonoschina.com/MUSIC

路由

DNS路由

为了使用国内的域名服务器来解析音乐网站,需要配置一条静态路由,让访问墙内DNS服务器(114.114.114.114)的流量都走GRE over IPSec隧道,转发到远端路由器。

set protocols static interface-route 114.114.114.114/32 next-hop-interface tun0 distance 100

策略路由

DNSMASQ已经把墙内音乐网站的IP地址收录到地址集MUSIC里。我们使用下面的策略路由规则,让所有访问墙内音乐网站的流量走GRE隧道tun0。

set protocols static table 50 interface-route 0.0.0.0/0 next-hop-interface tun0 distance 100

set firewall modify PBR rule 2410 action modify
set firewall modify PBR rule 2410 destination group address-group MUSIC
set firewall modify PBR rule 2410 modify table 50
set firewall modify PBR rule 2410 protocol all

set interfaces eth0 firewall in modify PBR

NAT

当转发的流量通过隧道到达墙内一端后,其源地址还是这边内网的地址,因此返回的流量就需要在墙内路由器上配置相关的路由,否则会因为那边查找不到相应的路由而被丢弃。有个简单的方法可以规避配置这个路由,就是在GRE隧道出口启用masqurade做出口地址转换。这样,进入隧道的流量的源地址包都是隧道口地址,而对端是自然知道返回路由的。

set service nat rule 5100 'nat for GRE tunnel tun0'
set service nat rule 5100 outbound-interface tun0
set service nat rule 5100 type masquerade

commit;save;exit

验证

你可以使用以下命令来验证配置是否正确:

  • show ip route
  • show ip route table 50
  • show firewall modify PBR statistics
  • sudo ipset -L MUSIC
  • sudo tcpdump -n -i eth0 port 53
  • sudo tcpdump -n -i tun0 port 53

在EdgeOS/VyOS上启用DNSMASQ

简介

DNSMASQ是英国程序员Simon Kelley开发的一件多功能DHCP服务器/DNS代理工具软件。墙内的IT极客们都非常熟悉它,因为它是逃离DNS污染的必用工具。

我们这里就重点介绍以下DNS转发和地址收集功能。在DNSMASQ配置文件里,你常常可以见到类似以下两行的配置:

server=/creekside.network/1.1.1.1
ipset=/creeksidenet.com/MY_ADDR_GRP

第一项配置,”server=/creekside.network/1.1.1.1″是告诉DNSMASQ,如果遇到以”creekside.network”为后缀的域名,都转发到IP地址是1.1.1.1的DNS服务器上进行解析;

第二项配置,”ipset=/creekside.network/MY_IP_ADDR_GRP“,指示DNSMASQ,把以“creeksidenet.com“为后缀的域名解析结果,都放到名为MY_ADDR_GRP的ipset集合里。

这两项功能对于企业很有用处。比如你在公司内网安装了一个文件服务器,为了方便访问,你可以给它设置一个内部用的域名,比如file.mycompany,在路由器里添加相应的DNSMASQ设置,就可以通过这个域名来访问你内部的资源。

EdgeOS

EdgeOS已经内置了DNSMASQ功能,你可以通过以下配置来启用它。

configure
set service dhcp-server use-dnsmasq enable
set service dns forwarding cache-size 1500
set service dns forwarding name-server 8.8.8.8
set service dns forwarding name-server 8.8.4.4
set service dns forwarding except-interface pppoe0
commit;save;exit

上述配置里,首先启用DNSMASQ(缺省不启用),然后设置DNS缓存大小,以及缺省使用的上游DNS域名服务器。

最后一行是除了pppoe0端口以外,其他端口都启用DNSMASQ。另外与之相斥的配置方法是设置listen-on来指定启用的端口,未指定的端口不启用。比如以下配置就是在eth1和tun0两个端口上启用DNSMASQ。

configure
set service dns forwarding listen-on eth1
set service dns forwarding listen-on tun0
commit;save;exit

另外一个非常好用的配置是options,凡是在options里配置的内容,都会被复制到/etc/dnsmasq.conf文件里。这样我们就可以启用DNSMASQ手册里的所有功能。其典型的配置语法如下:

configure
set service dns forwarding options "conf-file=/config/dnsmasq/dnsmasq-xxxlist-ipset.conf"
commit;save;exit

这个设置指示DNSMASQ从/config/dnsmasq/dnsmasq-xxxlist-ipset.conf装载配置选项。

USG

USG装载的是比较旧版本的EdgeOS,虽然也内置了DNSMASQ功能,但是由于它是用Unifi控制器管理的,有一个限制。系统缺省配置except-interface选项,而且无法删除。这个配置是和listen-on相斥的,如果我们按照官网UniFi – USG Advanced Configuration一文中添加了这一条配置,会造成commit失败,让USG不停地重启。

我们可以配置一条options选项来规避这个问题。

configure
set interfaces loopback lo address 10.255.255.254/32
set service dns forwarding options "listen-address=10.255.255.254"
commit;save;exit

一旦启用这一条,except-interface就失效了。因此在DHCP配置DNS选项时,都把DNS指向10.255.255.254这个地址。

VyOS

不知道VyOS开发团队是如何考虑的,VyOS 1.2版本以后就没有再预装DNSMASQ了,改成PowerDNS,不支持ipset选项。

经过一番摸索,我们找到解决方法,在这里介绍给大家。

从Debian安装DNSMASQ

我们知道,VyOS 1.2.5版本是在Debian Jessie上开发的,理论上我们从Debian官方源安装的软件是可以直接拿来用的。

要从官方源安装软件,需要配置/etc/apt/sources.list文件,不幸的是,VyOS开发团队为了防止我们安装软件,搞乱系统,把soureces.list清空了。不过这难不倒我们。下面的shell命令可以完成DNSMASQ的安装。

echo "deb http://deb.debian.org/debian/ jessie main contrib non-free
deb-src http://deb.debian.org/debian/ jessie main contrib non-free" | sudo tee /etc/apt/sources.list
sudo apt update && sudo apt install dnsmasq -y

好像已经大功告成了,但是事情没有那么简单。如果你重启VyOS,你会发现新安装的DNSMASQ以及相应的缺省配置文件 /etc/dnsmasq.conf 统统不见了。这是因为VyOS开发团队为了保护系统,使用了Overlay文件系统,用户对路由器系统的任何改变都无法永久保存,这样保证了系统的稳健性。

固化DNSMASQ

我们知道,/config目录是会永久保存的,即使系统升级,这个目录也不会被触及。因此,我们可以将dnsmasq程序保存到这个目录里。

sudo mkdir -p /config/dnsmasq/bin
sudo cp /usr/sbin/dnsmasq /config/dnsmasq/bin/

然后,我们可以创建一个基础的配置文件,

echo "log-facility=/var/log/dnsmasq.log
except-interface=eth0
cache-size=15000
server=1.1.1.1	# statically configured
server=8.8.4.4	# statically configured" | sudo tee /config/dnsmasq/dnsmasq.conf

为了在系统重启时自动启动dnsmasq,我们可以修改/config/scripts/vyos-postconfig-bootup.script脚本。

echo "/config/dnsmasq/bin/dnsmasq --conf-file=/config/dnsmasq/dnsmasq.conf" | \
    sudo tee -a /config/scripts/vyos-postconfig-bootup.script

启用DNSMASQ

同理,如果要让终端使用DNSMASQ,而不是系统缺省内置的PowerDNS,我们需要做以下设置。

首先,给loopback接口配置一个IP地址,并在相应的DHCP设置中把DNS指向loopback接口地址。

configure
set interfaces loopback lo address 10.255.255.254/32
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/24 dns-server 10.255.255.254
commit;save;exit

在dnsmasq配置文件中添加以下设置。

echo "listen-address=10.255.255.254" | sudo tee -a  /config/dnsmasq/dnsmasq.conf

ipset

ipset是防火墙里常用的工具。它可以收集IP地址,用于各种防火墙策略。在EdgeOS/VyOS里,每个address-group实际上就对应相应的ipset集合。

如果你想要在dnsmasq.conf里使用一个MY_ADDR_GRP的ipset,可以在配置里做如下操作。

configure
set firewall group address-group MY_ADDR_GRP
commit;save;exit

终端里常用的ipset命令有:

  • 显示ipset内容,sudo ipset list MY_ADDR_GRP
  • 查找某个IP,sudo ipset test MY_ADDR_GRP 8.8.8.8

在EdgeOS/VyOS上启用IKEv2 拨号VPN

简介

我们在上一篇文章《如何快速在CentOS7上部署VPN服务器》介绍了在CentOS 7上部署IKEv2服务器的方法。这种最常见的部署方式还是有几个缺点,

  • 所有配置都是基于各个模块的对应配置文件,分散在不同的目录下,让备份和复制变得很麻烦;
  • 很多基础的网络功能模块都需要单独安装;
  • 手动配置出错导致系统崩溃的几率比较大。

这里我们介绍在EdgeOS/VyOS下,如何部署IKEv2 Roadwarrior VPN的方案。EdgeOS/VyOS集成了非常丰富的网络功能,配置可以脚本化,非常便于部署。然而,EdgeOS/VyOS内置的命令行并不直接支持IKEv2 Roadwarrior VPN,我们需要增加一些自己制作的配置文件。这些配置文件都统一保存在/config/ipsec.d目录下,在系统升级的时候不会丢失,也便于备份。

大家需要注意的是,低端的EdgeRouter路由器,会因为内存和处理性能的限制,无法同时支持较多的IPSec连接。基于x86的VyOS平台则完全没有这个限制。

预先准备

实现本文介绍的功能,你需要一台EdgeRouter或者安装好VyOS的软路由。

在参考本文开始配置以前,我们假定大家已经按照介绍VyOS一文完成了VyOS的初始化配置。使用EdgeOS的用户,可以使用系统自带的wizard完成初始配置。

你还需要有一个公网地址,以便客户端可以用来连接。我们并不需要静态地址,动态地址也可以,只要设置好相应的动态域名即可。具体方法请参考EdgeRouter配置DDNS动态域名一文。

签发证书

服务器密钥

我们先使用专门的RSA密钥工具生成服务器用证书密钥。如果你已经根据如何在EdgeRouter上配置站点到站点IPSec VPN隧道配置过基于RSA的隧道,可以跳过这一小节。我们把生成的RFC3110格式的公钥保存到/config/ipsec.d/rsa-keys/下,后续配置站点到站点的IPSec还会用到。

generate vpn rsa-key > localhost.pub
sudo mv ./localhost.pub /config/ipsec.d/rsa-keys/

然后,我们进入root模式,并创建工作目录。

sudo -i
mkdir -p /config/ipsec.d/{cacerts,certs,private}

再把现有的localhost.key复制到密钥目录。

sudo cp /config/ipsec.d/rsa-keys/localhost.key /config/ipsec.d/private/server-key.pem

EdgeOS

接下来,我们调用PKI命令创建一个自签发的CA证书。下面参考命令中,”CN=Creekside EdgeOS CA”是证书颁发机构名称,你可以根据自己的情况修改。

pki --gen --type rsa --outform pem > /config/ipsec.d/private/ca-key.pem 

pki --self --ca --type rsa --lifetime 3650 \
  --in /config/ipsec.d/private/ca-key.pem \
  --dn "CN=Creekside EdgeOS CA" \
  --outform pem > /config/ipsec.d/cacerts/ca-cert.pem

随后,我们使用刚才签发的CA证书,再为本机签发VPN服务器证书和密钥。请注意替换相应的服务器域名信息(范例中的”vpn.creekside.network”)。

pki --pub --in /config/ipsec.d/private/server-key.pem | \
  pki --issue --cacert /config/ipsec.d/cacerts/ca-cert.pem \
  --cakey /config/ipsec.d/private/ca-key.pem \
  --dn "CN=vpn.creekside.network" \
  --san="vpn.creekside.network" \
  --flag serverAuth --flag clientAuth --flag ikeIntermediate \
  --outform pem --digest sha256 > /config/ipsec.d/certs/server-cert.pem

VyOS

VyOS没有PKI这么好用的工具。好在系统内置了openssl,我们同样可以生成PKI用的证书文件。

我们调用openssl命令创建一个自签发的CA证书。下面参考命令中,在subj选项里,C=国家,O=组织,CN=证书颁发机构名称,这三项你可以根据自己的情况修改。

openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
    -keyout /config/ipsec.d/private/ca-key.pem \
    -out /config/ipsec.d/cacerts/ca-cert.pem \
    -addext "keyUsage=Certificate Sign, CRL Sign" \
    -subj "/C=US/O=CreekSide Networks/CN=Creekside VyOS CA"

随后,我们使用服务器密钥生成服务器证书申请文件。

openssl req -new -nodes \
  -key /config/ipsec.d/private/server-key.pem \
  -out /config/ipsec.d/certs/server.csr \
  -subj /CN="vpn.creekside.network"

在签发证书前,还要创建一个用于签发的extension文件,以便包括关键的SAN以及其他参数。 [alt_names]下,可以设置多个域名,分别以DNS.1, DNS.2 …列出。

echo "authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth,clientAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = vpn.creekside.network" > /config/ipsec.d/vpn-server.ext

最后,我们使用刚才生成的CA证书,签发VPN服务器证书。

openssl x509 -req -days 3650 -CAcreateserial \
  -in /config/ipsec.d/certs/server.csr \
  -CA /config/ipsec.d/cacerts/ca-cert.pem \
  -CAkey /config/ipsec.d/private/ca-key.pem  \
  -out /config/ipsec.d/certs/server-cert.pem \
  -extfile /config/ipsec.d/vpn-server.ext

配置IPSec连接参数

连接配置

使用下面命令创建/config/ipsec.d/ipsec.conf定制化配置文件。

echo "
# customized roadwarrior configuration by Creekside Networks LLC
config setup
    uniqueids=never

ca rootca
    cacert=/config/ipsec.d/cacerts/ca-cert.pem

conn winlx
    ike=aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024!
    esp=aes256-sha1,aes128-sha1,3des-sha1!
    keyexchange=ikev2
    compress=no
    type=tunnel
    fragmentation=yes
    forceencaps=yes
    dpddelay=300s
    dpdtimeout=30s
    dpdaction=clear
    forceencaps=yes
    ikelifetime=4h
    lifetime=2h
    eap_identity=%identity
    auto=add
    rekey=no
    left=%any
    leftcert=/config/ipsec.d/certs/server-cert.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightid=%any
    rightauth=eap-mschapv2
    rightsourceip=10.255.255.1/24
    rightdns=8.8.8.8,8.8.4.4
    rightsendcert=never

conn apple
    also=winlx
    [email protected]
" > /config/ipsec.d/ipsec.conf

说明

  • 考虑到EdgeRouter硬件加速的限制,我们只配置了有限的PN加密认证算法;如果是基于x86的VyOS平台,可以在去除IKE/ESP算法后面的”!”号,系统会自动加载所有算法;
  • 苹果产品系列,remote id(等同于上述的leftid)是必填。因此我们这里将VPN服务器的域名作为remote id。你也可以用任何字符串,只要客户端设置时与此匹配就好。

密钥及用户账户

我们使用以下命令创建用户认证文件: /config/ipsec.d/ipsec.secrets。

echo "
# roadwarrior user accounts 

 : RSA /config/ipsec.d/private/server-key.pem

bob  : EAP bobpasswd
alice : EAP alicepasswd
"  > /config/ipsec.d/ipsec.secrets

exit

如果你可以参考最后两行行用户账户的格式 (用户名 :EAP 密码),添加更多的用户。用户名可以是任意字符串,你也可以使用邮箱作为用户名。在用户名和密码之间,使用” :EAP “来分割。

最后,别忘了使用exit命令退出root模式。

设置防火墙

WAN口规则

接下来,我们进入配置状态,配置相应的防火墙策略

configure

set firewall name WAN_LOCAL rule 200 action 'accept'
set firewall name WAN_LOCAL rule 200 description 'ipsec ike'
set firewall name WAN_LOCAL rule 200 destination port '500,4500'
set firewall name WAN_LOCAL rule 200 log 'disable'
set firewall name WAN_LOCAL rule 200 protocol 'udp'

set firewall name WAN_LOCAL rule 201 action 'accept'
set firewall name WAN_LOCAL rule 201 description 'ipsec esp'
set firewall name WAN_LOCAL rule 201 log 'disable'
set firewall name WAN_LOCAL rule 201 protocol 'esp'

set firewall name WAN_LOCAL rule 210 action 'accept'
set firewall name WAN_LOCAL rule 210 description 'ipsec traffic'
set firewall name WAN_LOCAL rule 210 log 'disable'
set firewall name WAN_LOCAL rule 210 protocol 'all'
set firewall name WAN_LOCAL rule 210 ipsec match-ipsec

set firewall name WAN_IN rule 210 action 'accept'
set firewall name WAN_IN rule 210 description 'ipsec traffic'
set firewall name WAN_IN rule 210 log 'disable'
set firewall name WAN_IN rule 210 protocol 'all'
set firewall name WAN_IN rule 210 ipsec match-ipsec

commit;save;exit

由于从IPSec隧道出来的数据包被视作来自WAN口,因此,需要在WAN口的IN和LOCAL两个规则集上都配置相应的规则允许数据包接入。

TCP MSS

由于esp的带来的额外负担(overhead)大约在90字节左右,考虑到PPPoE下局域网IP包最大长度被限制在1500-8=1492字节,因此TCP MSS值最大为1500-8-90-40=1362字节。考虑到可能会有GRE over IPSec,保守一点,我们可以设置为1300字节。

VyOS

configure
set firewall options interface eth0 adjust-mss 1300
commit;save;exit

EdgeOS

configure
set firewall options mss-clamp interface-type all
set firewall options mss-clamp 1300
commit;save;exit

配置NAT-exclude

因为是定制化VPN,所以需要专门配置NAT-exclude,把发送给VPN客户端的流量排除在正常WAN的NAT之外,否则,NAT过的流量,无法进入IPSec隧道返回。由于NAT规则是顺序执行的,这条配置需要排在WAN口masquerade规则的前面。

EdgeOS

configure
edit service nat rule 5010
set description "exclude roadwarrior ipsec"
set destination address 10.255.255.0/24
set exclude
set log disable
set outbound-interface eth0
set protocol all
set type masquerade
commit;save;exit

VyOS

configure
edit nat source rule 10
set description "exclude roadwarrior ipsec"
set destination address 10.255.255.0/24
set exclude
set log disable
set outbound-interface eth0
set protocol all
set translation address masquerade
commit;save;exit

启用VPN配置

最后我们把刚才定制过的VPN文件添加到配置里。

configure
set vpn ipsec include-ipsec-conf /config/ipsec.d/ipsec.conf
set vpn ipsec include-ipsec-secrets /config/ipsec.d/ipsec.secrets
commit;save;exit

配置客户端

我们需要把自签发的证书(/config/ipsec.d/cacerts/ca-cert.pem)拷贝出来,安装在客户端上。具体配置步骤,请参考如何设置IPSec VPN客户端一文。需要注意的是,Windows不能识别后缀为pem的证书文件,请下载后重命名为ca-cert.cer。

验证

以下命令可以用于验证和调试:

  • openssl x509 -text -in <证书文件>,用于查看证书内容
  • sudo ipsec statusall,查看ipsec状态
  • sudo ipsec listcerts,显示服务器证书信息
  • sudo ipsec restart, 重启Strongswan,当你改变了上述定制文件,需要用这个命令
  • sudo swanctl –log,显示strongswan日志,对于诊断用户端连接问题非常有用。

如何理解EdgeOS/VyOS防火墙

防火墙基础

防火墙是建立在网络会话的基础上,对网络流量进行访问控制的重要工具。

通常一个会话,可以由5个元素来确定,即源地址和端口,目的地址和端口,以及协议类型,这常常成为五元组。防火墙规则通常就会基于这五大元素展开。

根据防火墙的会话跟踪机制,进入防火墙的包又可以分为四类。

  • 新建New:在已有的会话中找不到匹配的会话,并且TCP包的SYN位ON。
  • 已建立Established:属于已有的会话。
  • 相关Related:这个包不属于任何已有的会话,但是和现有会话有关,例如ftp的数据连接是依附于控制连接的。
  • 非法Invalid:凡是不属于以上三类的包都属于非法包。

下面我们就三种不同的应用场景介绍在VyOS上防火墙的配置与使用。

场景一:内网访问互联网

我们先看看相应的流量走向图。

内网的流量(绿色)首先经过DNAT,一般访问外网的流量无需DNAT,然后进入LAN口eth1的防火墙IN规则。如果没有配置规则,缺省都是accept,就是允许任何流量进入。经过内部路由后,流量再经过WAN口OUT规则过滤(缺省accept),再经过SNAT(masquerate)把源地址切换成WAN口外网地址,最后发送出去。

返程流量(蓝色),正好走反过来的路线。WAN口IN方向,缺省规则是丢弃,因为我们不允许外来未知流量进入,并且要丢弃非法状态的流量包。

因此,要让回程的流量正常通过,我们需要在WAN口防火墙IN的规则集里,配置一条允许已经建立连接和相关连接的规则。

下面是对应的防火墙配置:

configure
set firewall name WAN_IN default-action 'drop'

set firewall name WAN_IN rule 10 action 'accept'
set firewall name WAN_IN rule 10 description 'Allow established/related'
set firewall name WAN_IN rule 10 state established 'enable'
set firewall name WAN_IN rule 10 state related 'enable'

set firewall name WAN_IN rule 20 action 'drop'
set firewall name WAN_IN rule 20 description 'Drop invalid state'
set firewall name WAN_IN rule 20 state invalid 'enable'

set interfaces ethernet eth0 firewall in name 'WAN_IN'
commit;save;exit

场景二:端口转发

内网有一个http服务器,IP地址是10.0.0.100/24,开放公网访问。我们知道http/https用的端口是80/433。

我们还是可以参考场景一的示意图,只不过流量走向正好反过来。要让外网发起的访问内部网站的流量通过,我们需要配置一条防火墙规则,允许符合条件(目的地址和端口,协议)的流量通过。注意执行顺序防火墙排在DNAT之后,所以目的地址应当是转换过的内网地址。

返程不需要设置规则,因为WAN口OUT的缺省规则是accept,允许外向流量。

下面是参考配置。

configure
set firewall name WAN_IN rule 100 action 'accept'
set firewall name WAN_IN rule 100 destination port 80,443
set firewall name WAN_IN rule 100 destination address 10.0.0.100
set firewall name WAN_IN rule 100 protocol tcp
set firewall name WAN_IN rule 100 log disable
set firewall name WAN_IN rule 100 description "allow web access"
commit;save;exit

场景三:IPSec VPN

IPSec的流量是终结在路由器内部的,如下图:

IPSec分成IKE协商阶段,会用到两个固定的端口,500/udp和4500/udp。隧道建立后,流量会封装在ESP包里。流量从隧道出来,也是被视作来源于WAN口,还需要在LOCAL和IN规则集里各配置一条对应的规则,这里要用到匹配IPSec流量的关键字 ipsec match-ipsec。对应的规则如下:

configure
set firewall name WAN_LOCAL default-action 'drop'

set firewall name WAN_LOCAL rule 200 action 'accept'
set firewall name WAN_LOCAL rule 200 description 'ipsec ike'
set firewall name WAN_LOCAL rule 200 destination port '500'
set firewall name WAN_LOCAL rule 200 log 'disable'
set firewall name WAN_LOCAL rule 200 protocol 'udp'

set firewall name WAN_LOCAL rule 210 action 'accept'
set firewall name WAN_LOCAL rule 210 description 'ipsec esp'
set firewall name WAN_LOCAL rule 210 log 'disable'
set firewall name WAN_LOCAL rule 210 protocol 'esp'

set firewall name WAN_LOCAL rule 220 action 'accept'
set firewall name WAN_LOCAL rule 220 description 'ipsec nat-t'
set firewall name WAN_LOCAL rule 220 destination port '4500'
set firewall name WAN_LOCAL rule 220 log 'disable'
set firewall name WAN_LOCAL rule 220 protocol 'udp'

set firewall name WAN_LOCAL rule 230 action 'accept'
set firewall name WAN_LOCAL rule 230 destination address 10.0.0.0/24
set firewall name WAN_LOCAL rule 230 source address 10.1.0.0/24
set firewall name WAN_LOCAL rule 230 ipsec match-ipsec
set firewall name WAN_LOCAL rule 230 log 'disable'
set firewall name WAN_LOCAL rule 230 protocol 'all'

set firewall name WAN_IN rule 200 action 'accept'
set firewall name WAN_IN rule 200 destination address 10.0.0.0/24
set firewall name WAN_IN rule 200 source address 10.1.0.0/24
set firewall name WAN_IN rule 200 ipsec match-ipsec
set firewall name WAN_IN rule 200 log 'disable'
set firewall name WAN_IN rule 200 protocol 'all'

set interfaces ethernet eth0 firewall local name 'WAN_LOCAL'
commit;save;exit

从应用的视角谈NAT

简介

前段时间,有朋友让我介绍以下在VyOS下如何配置端口转发NAT。我查了一下资料,发现市面上介绍NAT的文章都过于学术化,甚至有些晦涩难懂。有鉴于此,本文试图从应用的视角来介绍常见的NAT及在VyOS上的配置。

从技术的角度来区分,我们常用的NAT可以分为源地址转换SNAT和目标地址转换DNAT两种类型。VyOS/EdgeOS上,两种NAT与接口和防火墙的关系可以参考下图。

下面我们就介绍NAT的各种应用场景以及配置方法。

NAT应用

SNAT

顾名思义,SNAT主要应用于从内网访问外网的场景。我们知道,一般运营商只给宽带接入分配一个IP地址。流量从WAN口出去,就必须转换为外网IP地址,否则远端服务器的回传流量无法路由回本地。

在出口为静态地址,例如192.0.0.1时,可以使用SNAT。VyOS的配置如下:

configure
set nat source rule 100 outbound-interface eth0
set nat source rule 100 translation address 192.0.0.1
commit;save;exit

Masquerade是SNAT的一种实现形式,主要应用于出口是动态地址的场景。

configure
set nat source rule 100 outbound-interface pppoe0
set nat source rule 100 translation address 'masquerade'
commit;save;exit

在某些特殊场景下,我们希望排除NAT,例如IPSec是按照两端地址进行匹配的,如果相应的流量NAT后,就源地址就会变化,导致流量无法进入隧道,这时候就需要使用下面的配置对相应的流量排除。注意,和防火墙策略一样,NAT策略是按照规格序号从小到大先后执行的,因此,需要把排除策略放到前面。

configure
set nat source rule 10 destination address '10.0.0.0/24'
set nat source rule 10 'exclude'
set nat source rule 10 outbound-interface 'eth0'
set nat source rule 10 source address '192.168.0.0/24'
commit;save;exit

端口转发

有些时候,我们会在家里部署NAS,视频监控等应用。当我们出门在外,希望能访问家里的DNS或者查看监控视频,这时候就需要用到DNAT,因为回访的流量是从外到内,目标地址是家里路由器的外网地址,进入到内网,需要转化成指定的内网设备地址。这就是我们常说的端口转发,是DNAT最常见的应用场景。

配置端口转发时,需要指定相关的协议(tcp/udp/tcp_udp)以及相应的端口号。常用的端口号可以参见Wikipedia。端口转发只适用于TCP或者UDP协议。

下面的配置将协议为TCP或者UDP,并且端口为52800或者52810的流量转发到192.168.0.100主机上。

configure
set nat destination rule 100 description 'demo dnat application'
set nat destination rule 100 inbound-interface pppoe0
set nat destination rule 100 protocol tcp_udp
set nat destination rule 100 port 52800,52810
set nat destination rule 100 translation address 192.168.0.100
commit;save;exit

1:1 NAT

在商业应用中,如果你有两个或以上的静态IP地址,你可以将其中一个IP匹配到某个服务器或者第二级路由器上。这时候就会用到1:1NAT,也就是一个外网IP对应一个内网IP,也被称作双向NAT。由于1:1NAT不受限于协议,所有流量都会被转发到内网IP,相应的该内网IP的出口流量也都使用指定的外网IP。

下面的范例中,把WAN口eth1的一个IP地址(192.0.2.30),转化为内网eth0上另一个IP地址(192.168.1.10)。

configure
set nat destination rule 2000 description '1-to-1 NAT example'
set nat destination rule 2000 destination address '192.0.2.30'
set nat destination rule 2000 inbound-interface 'eth1'
set nat destination rule 2000 translation address '192.168.1.10'
set nat source rule 2000 description '1-to-1 NAT example'
set nat source rule 2000 outbound-interface 'eth1'
set nat source rule 2000 source address '192.168.1.10'
set nat source rule 2000 translation address '192.0.2.30'
commit;save;exit

Hairping NAT

假定我们在内网运行了一个web服务器,我们可以通过DNAT开启外网访问。如果我们也要从内网访问,如果使用同样的URL,而DNS解析出来的目标地址是我们的外网地址,导致内网无法访问。这时候,就可以使用Hairping NAT来解决这个问题。

Hairping NAT的工作原理是在内网接口eth1配置地址转换,将所有来自eth1,并且是访问本地的特定端口的流量(原目标地址根据DNS解析为本地WAN口IP),转换目标地址为服务器的内网IP。

同时还要配置一个返程策略,让返回流量的源地址变换为外网IP,这样,从客户端看起来,就好像直接访问了该外网IP。

首先,我们配置一个常规的端口转发:

configure
set nat destination rule 100 description 'Regular destination NAT from external'
set nat destination rule 100 destination port 80
set nat destination rule 100 inbound-interface 'pppoe0'
set nat destination rule 100 protocol 'tcp'
set nat destination rule 100 translation address '192.168.0.100'

接下来我们配置Hairping NAT 的DNAT部分,让内网来的流量重新定位到服务器的内网IP。

set nat destination rule 110 description 'NAT Reflection: INSIDE'
set nat destination rule 110 destination port '80'
set nat destination rule 110 inbound-interface 'eth1'
set nat destination rule 110 protocol 'tcp'
set nat destination rule 110 translation address '192.168.0.100'

最后,我们再为Hairping NAT配置相应的返程策略。

set nat source rule 110 description 'NAT Reflection: INSIDE'
set nat source rule 110 destination address '192.168.0.0/24'
set nat source rule 110 outbound-interface 'eth1'
set nat source rule 110 protocol 'tcp'
set nat source rule 110 source address '192.168.0.0/24'
set nat source rule 110 translation address 'masquerade'

防火墙策略

由于WAN口的缺省防火墙策略是drop,也就是拒绝未经许可的流量。因此对于所有的DNAT,还需要配置相匹配的防火墙策略。防火墙的策略配置,请参考如何理解EdgeOS/VyOS防火墙一文。

介绍VyOS

前言

国内同学熟悉VyOS应该不算太多。在软路由里,如果把某快比做当年的D-Link,那和VyOS相对应的应该就是Cisco了。

VyOS源自当年开源的Vyatta OS,后者被收购后,网上开发者在原来Vayatta的基础上继续开发,形成了今天的VyOS。EdgeRouter上搭载的EdgeOS也是源自Vyatta OS,因此二者非常类似,但是在一些扩展功能上,有一些区别。

因此,VyOS和EdgeRouter可以说是绝配,EdgeRouter以高稳定,高性能,低价格(千兆转发的EdgeRouter-X售价不到400元人民币) 的硬件而著称;VyOS就非常适合虚拟化的场合。

安装VyOS

VyOS可以安装在软路由机器上,也可以安装在VMWare虚拟化平台上,在主流的VPS市场,例如AWS,Azure,GCP,都可以找到相应的安装源。

我们也提供了一个自己编译好基于最新的equuleus版本,有兴趣的朋友可以在这里下载VyOS-1.2.6.iso光盘映像。接下来要用一个Windows下的工具软件Rufus将光盘映像写入到可启动的U盘上,你可以从官网下载,也可以使用提供的下载。写盘的时候,选择MBR分区,支持BIOS或EFI启动即可。第一次刻写会提示你是否升级到最新的Syslinux引导模块,点击确认升级即可开始刻录。

启动后,显示器会进入命令行界面,使用vyos作为用户名和密码登录。登录后,我们需要将系统安装在本地硬盘上,输入命令“install image”可以启动安装程序。

[email protected]:~$ install image
Welcome to the VyOS install program.  This script
will walk you through the process of installing the
VyOS image to a local hard drive.
Would you like to continue? (Yes/No) [Yes]: 
Probing drives: OK
Looking for pre-existing RAID groups...none found.
The VyOS image will require a minimum 2000MB root.
Would you like me to try to partition a drive automatically
or would you rather partition it manually with parted?  If
you have already setup your partitions, you may skip this step

Partition (Auto/Parted/Skip) [Auto]: 

I found the following drives on your system:
 sda	4294MB


Install the image on? [sda]:

This will destroy all data on /dev/sda.
Continue? (Yes/No) [No]: Yes

Looking for config files from previous installations on sda1...
How big of a root partition should I create? (2000MB - 4294MB) [4294]MB: 

Creating filesystem on /dev/sda1: |
OK
Done!
Mounting /dev/sda1...
What would you like to name this image? [1.2.5]: OK.  This image will be named: 1.2.5
Copying squashfs image...
Copying kernel and initrd images...
Done!
I found the following configuration files:
    /opt/vyatta/etc/config/config.boot
    /opt/vyatta/etc/config.boot.default
Which one should I copy to sda? [/opt/vyatta/etc/config/config.boot]: 

Copying /opt/vyatta/etc/config/config.boot to sda.
Enter password for administrator account
Enter password for user 'vyos':
Retype password for user 'vyos':
I need to install the GRUB boot loader.
I found the following drives on your system:
 sda	4294MB


Which drive should GRUB modify the boot partition on? [sda]:

Setting up grub: OK
Done!
[email protected]:~$ 

一路回答Yes, 最后输入你为VyOS新设置的密码。完成安装后,一定要输入”reboot”命令重启系统,否则你的设置无法保存到新建立的硬盘分区。

第一次配置

重启后,我们登录系统进行第一次配置。我们需要完成以下任务:

  • 配置WAN口并添加缺省路由
  • 设置系统DNS服务器
  • 启用SSH
  • 设置WAN口防火墙策略
  • 配置本地局域网

配置WAN口

DHCP

使用DHCP获取IP地址时,系统会自动获取缺省路由和DNS服务器设置,因此我们只需要启用DHCP模式就好。

configure
set interfaces ethernet eth0 address dhcp

静态地址

使用静态地址时,需要设置缺省路由以及系统DNS服务器:

configure
set interfaces ethernet eth0 address 192.168.1.100/24
set system name-server '8.8.8.8'
set protocols static route 0.0.0.0/0 next-hop 192.168.1.254 distance 1

PPPOE

PPPOE模式下,需要设置相应接口的MTU,一般是1492个字节。

configure
set interfaces pppoe pppoe0 authentication password '123456'
set interfaces pppoe pppoe0 authentication user '051212345678'
set interfaces pppoe pppoe0 description 'China Unioncom'
set interfaces pppoe pppoe0 mtu '1492'
set interfaces pppoe pppoe0 source-interface 'eth0'

启用SSH

set service ssh port '22'

配置WAN口防火墙策略

除了本地出口流量外,我们只允许从互联网端ping和ssh访问路由器。

set firewall all-ping 'enable'
set firewall name WAN_IN default-action 'drop'
set firewall name WAN_IN rule 10 action 'accept'
set firewall name WAN_IN rule 10 description 'Allow established/related'
set firewall name WAN_IN rule 10 state established 'enable'
set firewall name WAN_IN rule 10 state related 'enable'
set firewall name WAN_IN rule 20 action 'drop'
set firewall name WAN_IN rule 20 description 'Drop invalid state'
set firewall name WAN_IN rule 20 state invalid 'enable'
set firewall name WAN_LOCAL default-action 'drop'
set firewall name WAN_LOCAL rule 10 action 'accept'
set firewall name WAN_LOCAL rule 10 description 'Allow established/related'
set firewall name WAN_LOCAL rule 10 state established 'enable'
set firewall name WAN_LOCAL rule 10 state related 'enable'
set firewall name WAN_LOCAL rule 20 action 'drop'
set firewall name WAN_LOCAL rule 20 description 'Drop invalid state'
set firewall name WAN_LOCAL rule 20 state invalid 'enable'
set firewall name WAN_LOCAL rule 30 action 'accept'
set firewall name WAN_LOCAL rule 30 description 'Ping from internet'
set firewall name WAN_LOCAL rule 30 icmp type-name 'echo-request'
set firewall name WAN_LOCAL rule 30 log 'disable'
set firewall name WAN_LOCAL rule 30 protocol 'icmp'
set firewall name WAN_LOCAL rule 40 action 'accept'
set firewall name WAN_LOCAL rule 40 description 'allow remote management'
set firewall name WAN_LOCAL rule 40 destination port '22'
set firewall name WAN_LOCAL rule 40 protocol 'tcp'

然后我们将防火墙策略绑定在WAN口上。

set interfaces ethernet eth0 firewall in name 'WAN_IN'
set interfaces ethernet eth0 firewall local name 'WAN_LOCAL'

配置本地局域网

除了设置相应端口的静态地址外,我们还启用了相应的DHCP服务。

set interfaces ethernet eth1 address 192.168.3.254/24
set service dhcp-server shared-network-name LAN subnet 192.168.3.0/24 default-route 192.168.3.254
set service dhcp-server shared-network-name LAN subnet 192.168.3.0/24 range 0 start 192.168.3.5
set service dhcp-server shared-network-name LAN subnet 192.168.3.0/24 range 0 stop 192.168.3.200
set service dhcp-server shared-network-name LAN subnet 192.168.3.0/24 dns-server 192.168.3.254

DNS代理服务

设置系统上游DNS服务器。

set system name-server 1.1.1.1
set system name-server 8.8.4.4

配置DNS代理,使用系统上游DNS服务器,监听LAN口地址。

set service dns forwarding system
set service dns forwarding listen-address 192.168.3.254
set service dns forwarding allow-from 192.168.3.0/24

出口NAT

set nat source rule 1000 outbound-interface eth0
set nat source rule 1000 translation address 'masquerade'

commit;save;exit

小贴士

有些时候,我们想参考现有的配置,你可以使用以下命令将配置转化为命令。

show configuration commands

升级系统:

add system image <url>

显示目前LAN口DHCP地址租用清单:

show dhcp server leases

配置编辑命令

  • edit:进入子项目编辑状态,例如edit interfaces ethernet eth1
  • copy:复制子项目,例如 copy rule 10 to rule 100
  • rename: 给子项目重命名,例如 rename rule 10 to rule 100

如何设置分支机构互连 (1) IPSec VPN

简介

站点到站点的VPN应用是IPSec最常见的使用场景。通过VPN隧道,企业内部多个站点可以无缝连接,内部应用可以通过虚拟网络互联互通。

本篇介绍如何在Ubiquiti EdgeRouter与VyOS之间建立点对点IPSec隧道,实现两个分支机构的互访。

下图是一个简单的测试模型。左边的站点(EdgeOS)的笔记本用户,需要通过VPN访问右边站点(VyOS)的服务器。左右两边内网网段分别是10.0.0.0/24和10.1.0.0/24。

预先准备

路由设备

实现本文介绍的功能,你需要一台EdgeRouter和安装好VyOS的软路由。在参考本文开始配置以前,我们假定大家已经按照介绍VyOS一文完成了VyOS的初始化配置。使用EdgeOS的用户,可以使用系统自带的wizard完成初始配置。

设置动态域名

考虑到大多数客户的宽带接入都是动态IP地址, 因此需要通过域名来获取当前使用的IP地址。我们假定左边EdgeOS的域名是edgeos.ddns.com,右边的VyOS的域名是vyos.ddns.com

如何配置动态域名,请参见本站另一篇帖子EdgeRouter/VyOS配置DDNS动态域名

RSA密钥

许多同学都有过用预共享密钥设置VPN隧道的经验。的确,预共享密钥使用起来非常方便,但是他有一个很大的缺点,WAN口必须是静态地址,而能提供静态地址的企业专线成本非常高,所以现实生活中大多数企业还是使用性价比高的共享宽带。

共享宽带带来的一个缺点是,只能得到一个动态地址。运营商大多数每24-48小时,就要更换一次公网地址。

在这个情况下,使用RSA签名进行IKE认证就非常有用了。RSA算法配合两端的ID就可以完成认证。下面我们先生成密钥。

EdgeOS/VyOS自带生成RSA密钥的模块。在shell下执行以下命令,

[email protected]:~$ generate vpn rsa-key
Generating 2048 bit rsa-key to /config/ipsec.d/rsa-keys/localhost.key
.........+++++
...........................+++++

Your new local RSA key has been generated
The public portion of the key is:

0sAwEAAe7k2zE85tw4T7BGQGjkGEcIB3K7PnktckNx/JskpkhAjcU3TE7Q9xj6MtjWw794XKNFk2cnGmLCD9tkNPK30vITi3quJQxVNfuTJy3rFT6uJfPxyNsnCr+D483UNYdJThtsac8zenBoqQVMS5O50Db7/6UFdKF6QsoAMd9aRyROFZ+3RBiPe3uDMMwCaFEW28EFKN3Ye47LTCk1r1V/cXIUsMa9uVkgy9b5Axp+FnYwDl84m2mbViE+/sm7WPRGpuR15nFVwZHlk8Fj+USXMmjdteqOzq0Q19I4ma7v15LLdKlhhboxJiwjO/OqRzKsW4zt+5GcvbCagF6PzM942ok=

这个命令会在生成PEM格式的2048bit RSA密钥,存放在/config/ipsec.d/rsa-keys/localhost.key文件里。同时会生成RFC3110格式的公钥。

我们需要在配置里保存新生成的密钥和公钥,你需要将刚才生成的公钥粘贴替换到下面的命令里。

configure

set vpn rsa-keys local-key file /config/ipsec.d/rsa-keys/localhost.key
set vpn rsa-keys rsa-key-name local-pub rsa-key 0sAwEAAe7k2zE85tw4T7BGQGjkGEcIB3K7PnktckNx/JskpkhAjcU3TE7Q9xj6MtjWw794XKNFk2cnGmLCD9tkNPK30vITi3quJQxVNfuTJy3rFT6uJfPxyNsnCr+D483UNYdJThtsac8zenBoqQVMS5O50Db7/6UFdKF6QsoAMd9aRyROFZ+3RBiPe3uDMMwCaFEW28EFKN3Ye47LTCk1r1V/cXIUsMa9uVkgy9b5Axp+FnYwDl84m2mbViE+/sm7WPRGpuR15nFVwZHlk8Fj+USXMmjdteqOzq0Q19I4ma7v15LLdKlhhboxJiwjO/OqRzKsW4zt+5GcvbCagF6PzM942ok=

同样,在右端VyOS侧执行同样的命令。

[email protected]:~$ generate vpn rsa-key
Generating rsa-key to /config/ipsec.d/rsa-keys/localhost.key
Generating RSA private key, 2192 bit long modulus (2 primes)
.+++++
.........................+++++
e is 65537 (0x010001)

Your new local RSA key has been generated
The public portion of the key is:

0sAwEAAd3MOCvSY2WnMCz9uVOLO34o+Cmhwlld+ldz0iP+x4jdCiD/676r5C4hfc9m8VDWfaFy/Ya6r4cprfM6XuPymRH+VgRPXoHafBdLY+1y6//HES/f2QUGqRfxjIbDn6fzDBqLHSPIB8eryYA6YFj0cgZMlG7EJGmkk/yEP5nziGJUHHKyGu+yAXdEsHoHar4Fp13hdzzdXFiqQ6hNg4LP3q8cTOiXVd1Ba3UuAwH+9tiLxUmPOBkYQXBxcBrlYu9tkU9kGB0vOj6crMnCt73qUO9aOrLSK8qEoi/4JnHLA9HHNna9fcTlCrn7fXRANzq0CYHfoyoosUhRIBnzeqUzGcDvCZ3diMxm8pmKI3vWD8RdUqs=

并且把两端的公钥都保存到VyOS配置里。

configure

set vpn rsa-keys local-key file /config/ipsec.d/rsa-keys/localhost.key
set vpn rsa-keys rsa-key-name local-pub rsa-key 0sAwEAAd3MOCvSY2WnMCz9uVOLO34o+Cmhwlld+ldz0iP+x4jdCiD/676r5C4hfc9m8VDWfaFy/Ya6r4cprfM6XuPymRH+VgRPXoHafBdLY+1y6//HES/f2QUGqRfxjIbDn6fzDBqLHSPIB8eryYA6YFj0cgZMlG7EJGmkk/yEP5nziGJUHHKyGu+yAXdEsHoHar4Fp13hdzzdXFiqQ6hNg4LP3q8cTOiXVd1Ba3UuAwH+9tiLxUmPOBkYQXBxcBrlYu9tkU9kGB0vOj6crMnCt73qUO9aOrLSK8qEoi/4JnHLA9HHNna9fcTlCrn7fXRANzq0CYHfoyoosUhRIBnzeqUzGcDvCZ3diMxm8pmKI3vWD8RdUqs=
set vpn rsa-keys rsa-key-name edgeos-pub rsa-key 0sAwEAAe7k2zE85tw4T7BGQGjkGEcIB3K7PnktckNx/JskpkhAjcU3TE7Q9xj6MtjWw794XKNFk2cnGmLCD9tkNPK30vITi3quJQxVNfuTJy3rFT6uJfPxyNsnCr+D483UNYdJThtsac8zenBoqQVMS5O50Db7/6UFdKF6QsoAMd9aRyROFZ+3RBiPe3uDMMwCaFEW28EFKN3Ye47LTCk1r1V/cXIUsMa9uVkgy9b5Axp+FnYwDl84m2mbViE+/sm7WPRGpuR15nFVwZHlk8Fj+USXMmjdteqOzq0Q19I4ma7v15LLdKlhhboxJiwjO/OqRzKsW4zt+5GcvbCagF6PzM942ok=

回到左边的EdgeOS,我们再把VyOS的公钥保存到配置里。

set vpn rsa-keys rsa-key-name vyos-pub rsa-key 0sAwEAAd3MOCvSY2WnMCz9uVOLO34o+Cmhwlld+ldz0iP+x4jdCiD/676r5C4hfc9m8VDWfaFy/Ya6r4cprfM6XuPymRH+VgRPXoHafBdLY+1y6//HES/f2QUGqRfxjIbDn6fzDBqLHSPIB8eryYA6YFj0cgZMlG7EJGmkk/yEP5nziGJUHHKyGu+yAXdEsHoHar4Fp13hdzzdXFiqQ6hNg4LP3q8cTOiXVd1Ba3UuAwH+9tiLxUmPOBkYQXBxcBrlYu9tkU9kGB0vOj6crMnCt73qUO9aOrLSK8qEoi/4JnHLA9HHNna9fcTlCrn7fXRANzq0CYHfoyoosUhRIBnzeqUzGcDvCZ3diMxm8pmKI3vWD8RdUqs=

Policy-based IPSec VPN

通常IPSec是通过匹配预设置的隧道两端的网段来确定哪些流量走隧道的。本例中,假定笔记本电脑需要访问远端服务器,那么相应的流量包里,对应的源地址和目标地址分别是10.0.0.100和10.1.0.200,而隧道两端的网段设置是10.0.0.0/24和10.1.0.200/24,于是流量就会走隧道。

这种匹配方式类似于防火墙的规则,因此我们也称之为基于规则的IPSec VPN。下面我们就开始配置。

EdgeOS端

set vpn ipsec auto-update 30
set vpn ipsec auto-firewall-nat-exclude enable
set vpn ipsec esp-group ESP_GRP compression disable
set vpn ipsec esp-group ESP_GRP lifetime 3600
set vpn ipsec esp-group ESP_GRP mode tunnel
set vpn ipsec esp-group ESP_GRP pfs enable
set vpn ipsec esp-group ESP_GRP proposal 1 encryption aes256
set vpn ipsec esp-group ESP_GRP proposal 1 hash sha1
set vpn ipsec ike-group IKE_V1 dead-peer-detection action restart
set vpn ipsec ike-group IKE_V1 dead-peer-detection interval 30
set vpn ipsec ike-group IKE_V1 dead-peer-detection timeout 120
set vpn ipsec ike-group IKE_V1 ikev2-reauth no
set vpn ipsec ike-group IKE_V1 key-exchange ikev1
set vpn ipsec ike-group IKE_V1 lifetime 28800
set vpn ipsec ike-group IKE_V1 proposal 1 dh-group 2
set vpn ipsec ike-group IKE_V1 proposal 1 encryption aes256
set vpn ipsec ike-group IKE_V1 proposal 1 hash sha1
set vpn ipsec ike-group IKE_V2 dead-peer-detection action restart
set vpn ipsec ike-group IKE_V2 dead-peer-detection interval 30
set vpn ipsec ike-group IKE_V2 dead-peer-detection timeout 120
set vpn ipsec ike-group IKE_V2 ikev2-reauth no
set vpn ipsec ike-group IKE_V2 key-exchange ikev2
set vpn ipsec ike-group IKE_V2 lifetime 28800
set vpn ipsec ike-group IKE_V2 proposal 1 dh-group 2
set vpn ipsec ike-group IKE_V2 proposal 1 encryption aes256
set vpn ipsec ike-group IKE_V2 proposal 1 hash sha1
set vpn ipsec ipsec-interfaces interface eth0
set vpn ipsec nat-traversal enable
edit vpn ipsec site-to-site peer vyos.ddns.com
set authentication id edgeos.ddns.com
set authentication mode rsa
set authentication remote-id vyos.ddns.com
set authentication rsa-key-name vyos-pub
set connection-type initiate
set description 'ipsec tunnel edgeos ... vyos'
set ike-group IKE_V2
set ikev2-reauth inherit
set local-address any
set tunnel 0 allow-nat-networks disable
set tunnel 0 allow-public-networks disable
set tunnel 0 esp-group ESP_GRP
set tunnel 0 local prefix 10.0.0.0/24
set tunnel 0 remote prefix 10.1.0.0/24

设置说明

  • auto-update:让IPSec daemon定时去检查DDNS是否有更新,时间单位是秒;
  • auto-firwall-nat-exclude:启用后系统会自动配置相应的防火墙和NAT策略;
  • dead-peer-detection:自动检测并重置死连接;
  • ipsec-interface:设置成你所要使用的WAN口;
  • connection-type initiate:在EdgeOS里,Initiate对应的连接类型是”route”,隧道流量会自动触发连接;
  • peer vyos.ddns.com:要用对端域名
  • authentication id:本地域名或者你设置的本地名称
  • authentication remote-id: 对端域名或者你设置的对端名称
  • authentication rsa-key-name:对端公钥
  • local prefix: 是要开放给对端访问的本地内网网段;
  • remote prefxi:需要访问的远端内网网段。

由于IPSec对流量进行加密,相应的esp包会被占用大约100字节,因此需要调整TCP MSS设定。

set firewall options mss-clamp interface-type all 
set firewall options mss-clamp mss 1300

commit;save;exit

VyOS端

防火墙

VyOS和EdgeOS略有不同。VyOS没有内置auto-firewall-nat-exclude命令,因此需要单独先配置防火墙策略。

set firewall name WAN_LOCAL rule 200 action 'accept'
set firewall name WAN_LOCAL rule 200 description 'ipsec ike'
set firewall name WAN_LOCAL rule 200 destination port '500,4500'
set firewall name WAN_LOCAL rule 200 log 'disable'
set firewall name WAN_LOCAL rule 200 protocol 'udp'
set firewall name WAN_LOCAL rule 201 action 'accept'
set firewall name WAN_LOCAL rule 201 description 'ipsec esp'
set firewall name WAN_LOCAL rule 201 log 'disable'
set firewall name WAN_LOCAL rule 201 protocol 'esp'
set firewall name WAN_LOCAL rule 210 action 'accept'
set firewall name WAN_LOCAL rule 210 description 'ipsec traffic'
set firewall name WAN_LOCAL rule 210 log 'disable'
set firewall name WAN_LOCAL rule 210 protocol 'all'
set firewall name WAN_LOCAL rule 210 ipsec match-ipsec
set firewall name WAN_IN rule 210 action 'accept'
set firewall name WAN_IN rule 210 description 'ipsec traffic'
set firewall name WAN_IN rule 210 log 'disable'
set firewall name WAN_IN rule 210 protocol 'all'
set firewall name WAN_IN rule 210 ipsec match-ipsec

NAT

我们需要配置地址转换规则,把隧道流量排除在出口NAT之外。

set nat source rule 10 description 'exclude ipsec'
set nat source rule 10 destination address '10.0.0.0/24'
set nat source rule 10 source address '10.1.0.0/24'
set nat source rule 10 exclude
set nat source rule 10 outbound-interface 'eth0'
set nat source rule 10 protocol 'all'
set nat source rule 10 translation address 'masquerade'

IPSec

然后是配置VPN。

set vpn ipsec auto-update 30
set vpn ipsec esp-group ESP_GRP compression disable
set vpn ipsec esp-group ESP_GRP lifetime 3600
set vpn ipsec esp-group ESP_GRP mode tunnel
set vpn ipsec esp-group ESP_GRP pfs enable
set vpn ipsec esp-group ESP_GRP proposal 1 encryption aes256
set vpn ipsec esp-group ESP_GRP proposal 1 hash sha1
set vpn ipsec ike-group IKE_V1 dead-peer-detection action restart
set vpn ipsec ike-group IKE_V1 dead-peer-detection interval 30
set vpn ipsec ike-group IKE_V1 dead-peer-detection timeout 120
set vpn ipsec ike-group IKE_V1 ikev2-reauth no
set vpn ipsec ike-group IKE_V1 key-exchange ikev1
set vpn ipsec ike-group IKE_V1 lifetime 28800
set vpn ipsec ike-group IKE_V1 proposal 1 dh-group 2
set vpn ipsec ike-group IKE_V1 proposal 1 encryption aes256
set vpn ipsec ike-group IKE_V1 proposal 1 hash sha1
set vpn ipsec ike-group IKE_V2 dead-peer-detection action restart
set vpn ipsec ike-group IKE_V2 dead-peer-detection interval 30
set vpn ipsec ike-group IKE_V2 dead-peer-detection timeout 120
set vpn ipsec ike-group IKE_V2 ikev2-reauth no
set vpn ipsec ike-group IKE_V2 key-exchange ikev2
set vpn ipsec ike-group IKE_V2 lifetime 28800
set vpn ipsec ike-group IKE_V2 proposal 1 dh-group 2
set vpn ipsec ike-group IKE_V2 proposal 1 encryption aes256
set vpn ipsec ike-group IKE_V2 proposal 1 hash sha1
set vpn ipsec ipsec-interfaces interface eth0
set vpn ipsec nat-traversal enable
edit vpn ipsec site-to-site peer edgeos.ddns.com
set authentication id vyos.ddns.com
set authentication mode rsa
set authentication remote-id edgos.ddns.com
set authentication rsa-key-name edgeos-pub
set connection-type respond
set description 'ipsec tunnel vyos ... edgeos'
set ike-group IKE_V2
set ikev2-reauth inherit
set local-address any
set tunnel 0 allow-nat-networks disable
set tunnel 0 allow-public-networks disable
set tunnel 0 esp-group ESP_GRP
set tunnel 0 local prefix 10.1.0.0/24
set tunnel 0 remote prefix 10.0.0.0/24

设置说明

  • connection-type initiate:在VyOS里,respond对应的连接类型是”route”,隧道流量会自动触发连接,与EdgeOS实现不同;

与 EdgeOS一样,我们需要配置TCP MSS。因为IPSec流量通过WAN口,这里对应的接口就是eth0,如果你使用pppoe,相应的端口应该是pppoe0。

set firewall options interface eth0 adjust-mss '1300'

commit;save;exit

测试与诊断

我们这里介绍几个常用的命令:

  • 查看连接状态: sudo ipsec statusall
[email protected]:~$ sudo ipsec statusall
Status of IKE charon daemon (strongSwan 5.7.2, Linux 4.19.118-amd64-vyos, x86_64):
  uptime: 20 hours, since Sep 17 20:00:02 2020
  malloc: sbrk 3211264, mmap 0, used 1447440, free 1763824
  worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 4
  loaded plugins: charon test-vectors ldap pkcs11 tpm aes rc2 sha2 sha1 md5 mgf1 rdrand random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl gcrypt af-alg fips-prf gmp curve25519 agent chapoly xcbc cmac hmac ctr ccm gcm curl attr kernel-netlink resolve socket-default connmark stroke vici updown eap-identity eap-aka eap-md5 eap-gtc eap-mschapv2 eap-radius eap-tls eap-ttls eap-tnc xauth-generic xauth-eap xauth-pam tnc-tnccs dhcp lookip error-notify certexpire led addrblock counters
Listening IP addresses:
  192.0.0.1
Connections:
peer-edgeos.ddns.com-tunnel-0:  %any...edgeos.ddns.com  IKEv2, dpddelay=30s
peer-edgeos.ddns.com-tunnel-0:   local:  [vyos.ddns.com] uses public key authentication
peer-edgeos.ddns.com-tunnel-0:    cert:  "vyos.ddns.com"
peer-edgeos.ddns.com-tunnel-0:   remote: [edgeos.ddns.com] uses public key authentication
peer-edgeos.ddns.com-tunnel-0:    cert:  "edgeos.ddns.com"
peer-edgeos.ddns.com-tunnel-0:   child:  10.1.0.0/24 === 10.0.0.0/24 TUNNEL, dpdaction=restart
Routed Connections:
peer-edgeos.ddns.com-tunnel-0{2}:  ROUTED, TUNNEL, reqid 2
peer-edgeos.ddns.com-tunnel-0{2}:   10.1.0.0/24 === 10.0.0.0/24
Security Associations (1 up, 0 connecting):
peer-edgeos.ddns.com-tunnel-0[165]: ESTABLISHED 4 hours ago, 10.1.8.50[vyos.ddns.com]...35.220.139.62[edgeos.ddns.com]
peer-edgeos.ddns.com-tunnel-0[165]: IKEv2 SPIs: 4156b61c9b60c765_i* fdec6e13d63f6640_r, rekeying in 2 hours
peer-edgeos.ddns.com-tunnel-0[165]: IKE proposal: AES_CBC_256/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
peer-edgeos.ddns.com-tunnel-0{30}:  INSTALLED, TUNNEL, reqid 2, ESP in UDP SPIs: c99726b9_i ccf4d342_o
peer-edgeos.ddns.com-tunnel-0{30}:  AES_CBC_256/HMAC_SHA1_96/MODP_2048, 1596 bytes_i (19 pkts, 44s ago), 1596 bytes_o (19 pkts, 44s ago), rekeying in 23 minutes
peer-edgeos.ddns.com-tunnel-0{30}:   10.1.0.0/24 === 10.0.0.0/24
  • 重启IPSec进程: sudo ipsec restart

如果查看IPsec状态时,“Routed Connections:“下面没有显示相应的隧道信息,就需要执行这个命令重启进程。一般第一次配置完,常常会发生这种情况。

  • 强制连接: sudo ipsec up <peer>
  • 在线查看ipsec日志: sudo swanctl –log

EdgeRouter/VyOS配置DDNS动态域名

Cloudflare

市场上有很多动态域名提供商,其中最值得推荐的是Cloudflare。只要你把注册的域名转到Cloudflare下管理,动态域名本身并不收费,而且一个账户可以管理上千个子域名,没有额外费用,也不需要你实名注册,并且亲测中国境内可用。

EdgeOS/VyOS

EdgeRouter最新版本的固件本身直接支持Cloudflare APIv4,参考以下配置命令。

configure
edit service dns dynamic interface pppoe0 service custom-cloudflare
set host-name www.yoursite.com
set login your_cloudflare_email
set password your_cloudflare_global_API_key
set protocol cloudflare
set options "zone=yoursite.com"
commit;save;exit

USG

UBNT的另外一条产品线,USG系列,其装载的OS版本很老,因此无法直接支持Cloudflare DDNS。网上有很多帖子提到手动更新ddclient软件,但是一旦固件更新,就必须重新配置,非常麻烦。这里我们介绍使用shell script的方法,来定时更新域名。原始脚本参考自Tras2在Github上的帖子

首先在/config/scripts/目录下,创建一个新的script文件cloudflare-update.sh,填入以下内容,并根据你的Cloudflare账户更改文件起头的设置参数。

#!/bin/bash

# A bash script to update a Cloudflare DNS A record with the external IP of the source machine
# Used to provide DDNS service for my home
# Needs the DNS record pre-creating on Cloudflare

# Cloudflare zone is the zone which holds the record
zone="yourdomain.com"
# dnsrecord is the A record which will be updated
dnsrecord="www.yourdomain.com"
# Cloudflare authentication details, keep these private
cloudflare_auth_email="[email protected]"
cloudflare_auth_key="your_cloudflare_global_API_key"

log_file="/var/log/cloudflare.log"

# LOGGER
log() {
    if [ "$1" ]; then
        echo -e "[$(date)] - $1" >> $log_file
    fi
}

# Get the current external IP address
ip=$(curl -s -X GET https://checkip.amazonaws.com)

echo "Current IP is $ip"

if host $dnsrecord 8.8.8.8 | grep "has address" | grep "$ip"; then
  echo "$dnsrecord is currently set to $ip; no changes needed"
  exit
fi

# if here, the dns record needs updating

# get the zone id for the requested zone
zoneid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone&status=active" \
  -H "X-Auth-Email: $cloudflare_auth_email" \
  -H "X-Auth-Key: $cloudflare_auth_key" \
  -H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id')

echo "Zoneid for $zone is $zoneid"

# get the dns record id
dnsrecordid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?type=A&name=$dnsrecord" \
  -H "X-Auth-Email: $cloudflare_auth_email" \
  -H "X-Auth-Key: $cloudflare_auth_key" \
  -H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id')

echo "DNSrecordid for $dnsrecord is $dnsrecordid"

# update the record
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$dnsrecordid" \
  -H "X-Auth-Email: $cloudflare_auth_email" \
  -H "X-Auth-Key: $cloudflare_auth_key" \
  -H "Content-Type: application/json" \
  --data "{\"type\":\"A\",\"name\":\"$dnsrecord\",\"content\":\"$ip\",\"ttl\":1,\"proxied\":false}")

if [[ $update == *"\"success\":false"* ]]; then
    message="API UPDATE FAILED. DUMPING RESULTS:\n$update"
    log "$message"
    echo -e "$message"
    exit 1 
else
    message="IP changed to: $ip"
    log "$message"
    echo "$message"
fi

以上脚本通过查询特定网站(https://checkip.amazonaws.com)以获取外网IP。如果使用多个WAN口,这个方法就不适用了,可以通过调用EdgeOS运行命令接口来获取端口IP地址:

ip=$(/opt/vyatta/bin/vyatta-op-cmd-wrapper show interfaces | grep pppoe0 | awk '{print $2}')

记住要将新创建的文件改成可执行模式,然后进行测试:

sudo chmod +x /config/scripts/cloudflare-update.sh
sudo /config/scripts/cloudflare-update.sh

测试成功后,我们需要通过网关配置文件来设置定时任务。具体网关配置文件的设置方法请参见UBNT的官网链接。参考的配置文件如下:

{
    "system": {
        "task-scheduler": {
            "task": {
                "update-cloudflar-dns": {
                    "executable": {
                        "arguments": "",
                        "path": "/config/scripts/cloudflare-update.sh"
                    },
                    "interval": "1m"
                }
            }
        }
    }
}

这种方法可以保证设置不会受到固件升级的影响,并且每次USG从云端更新配置时,会自动将更新任务下发到USG。

NoIP

NoIP也是网友常用的DDNS供应商,相对Cloudflare,其最大的好处是使用官方域名,完全免费。EdgeOS和USG也都内置对NoIP的支持,可以使用WebUI或者Unifi控制器直接配置。参考命令行配置如下:

configure
edit service dns dynamic interface pppoe0 
set service noip host-name yourhost.ddns.net
set service noip login yourloginID
set service noip password yourloginpasswd
set service noip server dynupdate.no-ip.com
set web checkip.dyndns.com
commit;save;exit

NoIP的免费DDNS域名服务,供应商会要求域名必须每30天至少更新一次。而EdgeOS的设计在WAN口IP不变化的情况下,不主动更新DDNS记录。因此有必要配置一个定时任务来实现每天更新一次域名。这里我们调用EdgeOS内置的运行命令接口/opt/vyatta/bin/vyatta-op-cmd-wrapper,有兴趣的朋友可以参见官网介绍

configure
edit system task-scheduler task update_noip_pppoe0 
set executable arguments 'update dns dynamic interface pppoe0'
set executable path /opt/vyatta/bin/vyatta-op-cmd-wrapper
set interval 1d
commit;save;exit

公云PubYun

公云是国内老牌DDNS提供商,这里就不赘述了,直接上干货。

configure
set service dns dynamic interface pppoe0 service custom-pubyun host-name yourdomain.f3322.net
set service dns dynamic interface pppoe0 service custom-pubyun login yourlogin
set service dns dynamic interface pppoe0 service custom-pubyun options ssl=no
set service dns dynamic interface pppoe0 service custom-pubyun password yourpasswd
set service dns dynamic interface pppoe0 service custom-pubyun protocol dyndns2
set service dns dynamic interface pppoe0 service custom-pubyun server www.pubyun.com
commit;save;exit

阿里云DDNS

阿里云的DDNS服务最近很流行。EdgeOS和VyOS都没有内置支持,我们参考网上其他的网友Jarvis脚本,做了一个参考实现。

先下载脚本文件updatealiddns.sh,然后用编辑器修改脚本开头的三个参数:

  • aliddns_ak,你的阿里云DDNS账户Access Key ID
  • aliddns_sk,你的阿里云DDNS账户Access Key Secrets
  • aliddns_domain,阿里云域名后缀

上传修改后的脚本文件到/config/scripts目录下,并使用以下命令更改文件属性为可执行。

sudo chmod +x /config/scripts/update-aliddns.sh

接下来,我们配置一个系统任务,每分钟执行一次这个脚本。

configure
set system task-scheduler task update-aliyun-ddns executable arguments 'myhostname'
set system task-scheduler task update-aliyun-ddns executable path '/config/scripts/update-aliddns.sh'
set system task-scheduler task update-aliyun-ddns interval '1m'
commit;save;exit

上述配置中,myhostname是你的二级域名。请根据实际情况修改。