在动态寻址端点上构建 OpenVPN 站点到站点隧道
花了整整一年时间,历经无数心血,它终于成功了!
引言
2015年,在经历了25年的北海石油行业生涯后,我住在我被称为“银色之城”的地方,并在福蒂斯油田和贝里尔油田的石油钻井平台上工作。我把家人从苏格兰多变的气候中迁移出来,前往卡塔尔炙热的、沙尘飞扬的环境,并在Al-Shaheen油田工作。
在本文中,我们将探讨我如何实现OpenVPN隧道,以便访问我在苏格兰的家庭网络,从而能够访问我的CCTV系统和NAS设备,并让智能电视等设备认为它们仍然位于苏格兰。但为什么要这么做呢?网络限制不能阻碍我妻子观看她最喜欢的《英国烘焙大赛》!
到达目的地并非一帆风顺,经历了许多反复试验和大量的文章阅读,才得以理清思路并将其整合在一起。
挑战
在苏格兰,我使用的是BT Infinity连接,其稳定速度约为65Mb/s下载/18Mb/s上传。我更换了BT提供的HomeHub路由器,因为它太糟糕了,而且DHCP地址分配设备数量有限。它最多支持20个设备,这在我们家庭根本不够用!过了一段时间,我家的网络开始变得有些复杂,需要进行一次大修。您可以在我的CCTV文章中看到“之前”的样子:https://codeproject.org.cn/Articles/768867/Ive-Got-My-Eye-On-You-A-Journey-Into-Home-CCTV,但我们稍后会讨论硬件。英国端的主要挑战在于BT连接是动态IP,并且经常变化。
在卡塔尔,我使用的是FTTH连接,带宽为100Mb/s(如果需要且有钱,可以升级到1Gb/s!),这也是动态IP。第二个问题是有一个无法更换的Q-Tel光纤网关,所有流量都必须通过它。卡塔尔的另一个巨大挑战是建筑本身,都是实心混凝土墙。墙内的现有电缆管道时好时坏,有些堵塞,而且它们并不通往你想要的地方!WiFi穿透力很差,所以需要大量的扩展器才能覆盖到所有地方。
硬件
苏格兰端
我完全重建了家里的网络,并将其打包进了一个网络机柜。网络还被分成了几个不同的子网,用于主网络、CCTV和WiFi。它包括:
- Ubiquiti Edgerouter Pro
- Ubiquiti EdgeSwitch 24
- Ubiquiti ToughSwitch(用于CCTV子网)
- Ubiquiti UniFi AC AP
- BT OpenReach Modem
这是机柜的样子
卡塔尔端
这一端要简单得多,它只包括:
- Ubiquiti EdgeRouter POE
- Q-Tel光纤网关
- LinkSys AC2600路由器
- 一堆WiFi扩展器和电力线适配器
Q-Tel光纤网关
EdgeRouter POE
我们的最终目标是实现以下设置
配置时间
我们不会深入到每一个配置部分。Ubiquiti路由器有一些基本的向导,可以帮助它们启动和运行,作为带有默认防火墙规则等的路由器。本文重点关注隧道的建立和卡塔尔端必要的路由,以确定网络上的设备应将流量发送到何处。
EdgeRouter Pro中的基本设置向导屏幕
远程访问配置
在离开英国之前,我必须确保能够访问我的路由器。为此,第一件事是在防火墙规则中开放远程GUI端口。使用GUI,只需在WAN_LOCAL
规则集中为端口443
添加一条规则,并允许TCP和UDP流量。
EdgeRouter Pro上的防火墙规则配置
动态DNS
我还需要设置动态DNS来处理端点的动态性质。英国和卡塔尔都有ISP提供的动态IP,而且这两者都经常变化。
幸运的是,这两个设备(EdgeRouter Pro和Q-tel)都内置了对动态DNS服务的支持。EdgeRouter支持更多提供商,但它们都支持DynDNS。我注册了该服务,并为两端设置了两个域名。
然后将此信息输入EdgeRouter,interface
仅表示路由器上用于监控变化的动态IP的端口;
当我到达卡塔尔时,我为另一个DynDNS地址配置了光纤网关;
出于本文的目的,我们称这两个端点为router1.dyndns.info
和router2.dyndns.info
。
建立DMZ(隔离区)
Q-tel设备有点麻烦,一开始我还不确定需要建立哪些端口,因为我还没有确定如何将两个站点连接起来。因此,最简单的方法是设置一个DMZ,并将所有流量路由到内部路由器(即EdgeRouter POE),让它处理所有防火墙策略和路由。我已经为其(ER-POE)配置了一个静态IP地址192.168.100.2
,其互联网端口连接到Q-tel网关的一个以太网端口。Q-Tel设备本身默认为192.168.100.1
,这就是为什么在ER-POE上选择该地址的原因。
Q-Tel网关具有多种功能,支持互联网、语音和IP TV,这就是为什么该设备上配置了一个奇怪的WAN名称。
我总可以在以后回到这里建立一些特定的端口转发规则,但目前我很高兴ER-POE上的防火墙应该能很好地完成它的工作。
EdgeRouter POE初始配置
同样,有一个基本向导可以应用,它将“Internet”放在Eth0,Lan_1放在Eth1,然后Lan_2在Eth2、Eth3和Eth4上。Eth0连接到Q-Tel,并配置为静态IP地址192.168.100.2
。
我在ER-POE上创建了两个DHCP服务,一个用于服务Lan_1地址范围192.168.101.0/24
,第二个用于Lan_2的192.168.102.0/24
。
初始带宽测试
现在我已经有两个可以远程访问的路由器,并且使用了动态DNS作为它们的端点,我可以进行它们之间的带宽测试。
EdgeRouters在固件中内置了iPerf3,它们在Web界面上提供了一些基本功能的GUI包装器,但这并没有提供太多信息,而且我发现它有点不稳定,更喜欢通过Web界面使用命令行界面。
为了进行此测试,我需要在两台机器上为端口(您可以更改)5201
打开防火墙。
在远端(Router1),我将其设置为“服务器”,使用;
iperf3 -s
在近端(Router2),我发出以下命令,它以“客户端”模式运行,持续30秒,并忽略前5秒,以便连接有时间进行预热。
iperf3 -c router1.dyndns.info -t 30 -O 5
两个控制台都会开始输出当前的传输速率等信息,然后输出整体测试速度。我发现这会因一天中的时间而异。这是非常典型的,我经常在卡塔尔下午晚些时候和傍晚看到掉线。然而,下面的例子是我写文章时的情况,而不是我进行初步测试时的实际时间。输出显示此时速度约为45Mb/s,考虑到我穿越的是公共互联网和住宅线路,并且两个站点之间的距离为5,503公里(基于我的闪电探测器GPS传感器),这还不错。
打开隧道
隧道配置的第一部分是生成一个用于连接的密钥。这很简单,只需打开Router1上的CLI控制台并执行;
generate vpn openvpn-key /config/auth/secret
接下来是将密钥传输到Router2。我尝试通过记事本会话复制粘贴,但总是被告知密钥已损坏。最后,我打开了SSH端口22
,并使用以下命令将密钥文件推送到Router2;
sudo scp /config/auth/secret username@router2.dyndns.info:/config/auth/secret
并在提示时输入密码。
在Router1上输入了以下命令;
进入配置模式
configure
定义隧道接口和操作模式
set interfaces openvpn vtun0
set interfaces openvpn vtun0 mode site-to-site
分配端口(如果需要,可以更改,只需使防火墙匹配)
set interfaces openvpn vtun0 local-port 1194
set interfaces openvpn vtun0 remote-port 1194
接下来是为隧道端点分配地址,这不能是网络上任何现有子网的一部分,然后是远程隧道端点的公共地址。
set interfaces openvpn vtun0 local-address 10.99.99.1
set interfaces openvpn vtun0 remote-address 10.99.99.2
set interfaces openvpn vtun0 remote-host router2.dyndns.info
配置要使用的密钥和链路的压缩算法
set interfaces openvpn vtun0 shared-secret-key-file /config/auth/secret
set interfaces openvpn vtun0 openvpn-option "--comp-lzo"
现在配置OpenVPN的最后一个选项
set interfaces openvpn vtun0 openvpn-option "--float"
set interfaces openvpn vtun0 openvpn-option "--ping 10"
set interfaces openvpn vtun0 openvpn-option "--ping-restart 20"
set interfaces openvpn vtun0 openvpn-option "--ping-timer-rem"
set interfaces openvpn vtun0 openvpn-option "--persist-tun"
set interfaces openvpn vtun0 openvpn-option "--persist-key"
set interfaces openvpn vtun0 openvpn-option "--user nobody"
set interfaces openvpn vtun0 openvpn-option "--group nogroup"
现在我们必须配置隧道端点所在的远程子网以及要使用的接口
set protocols static interface-route 192.168.101.0/24 next-hop-interface vtun0
最后,我们提交更改
commit
save
exit
为Router2重复同样的操作,并且
进入配置模式
configure
定义隧道接口和操作模式
set interfaces openvpn vtun0
set interfaces openvpn vtun0 mode site-to-site
分配端口(确保与Router1中的设置相同)
set interfaces openvpn vtun0 local-port 1194
set interfaces openvpn vtun0 remote-port 1194
接下来是为隧道端点分配地址,这不能是网络上任何现有子网的一部分,然后是远程隧道端点的公共地址。
set interfaces openvpn vtun0 local-address 10.99.99.2
set interfaces openvpn vtun0 remote-address 10.99.99.1
set interfaces openvpn vtun0 remote-host router1.dyndns.info
配置要使用的密钥和链路的压缩算法
set interfaces openvpn vtun0 shared-secret-key-file /config/auth/secret
set interfaces openvpn vtun0 openvpn-option "--comp-lzo"
现在配置OpenVPN的最后一个选项
set interfaces openvpn vtun0 openvpn-option "--float"
set interfaces openvpn vtun0 openvpn-option "--ping 10"
set interfaces openvpn vtun0 openvpn-option "--ping-restart 20"
set interfaces openvpn vtun0 openvpn-option "--ping-timer-rem"
set interfaces openvpn vtun0 openvpn-option "--persist-tun"
set interfaces openvpn vtun0 openvpn-option "--persist-key"
set interfaces openvpn vtun0 openvpn-option "--user nobody"
set interfaces openvpn vtun0 openvpn-option "--group nogroup"
现在我们必须配置隧道端点所在的远程子网以及要使用的接口
set protocols static interface-route 192.168.0.0/24 next-hop-interface vtun0
最后,我们提交更改
commit
save
exit
一切顺利的话,这将启动并打开隧道。
可以从任何一个路由器的命令行控制台使用以下命令检查隧道状态
show interfaces openvpn
show interfaces openvpn detail
show openvpn status site-to-site
如果出于任何原因需要强制重启隧道,可以通过以下方式实现
restart openvpn interface vtun0
配置跨隧道路由
在卡塔尔的Router2端,我不想将所有流量都路由到隧道中。ER-POE上的所有正常流量将按正常方式路由到互联网,即192.168.102.0/24
子网中的所有流量。
我只想将192.168.101.0/24
子网中的流量路由到隧道中。要实现这一点,我们需要使用源地址防火墙修改规则。
注意:对于接下来的部分,我实际上手动编辑了配置文件,然后将其上传回路由器,但命令应该是下面这些!
此过程的第一部分是定义两个新的路由表(不要忘记进入配置模式)。
configure
set protocols static table 1 route 0.0.0.0/0 next-hop-interface eth0
set protocols static table 2 route 0.0.0.0/0 next-hop-interface vtun0
现在我们创建两个规则集来使用这两个表并路由流量。
set firewall modify SOURCE_ROUTE rule 10 description 'Traffic to internet'
set firewall modify SOURCE_ROUTE rule 10 source address 192.168.102.0/24
set firewall modify SOURCE_ROUTE rule 10 modify table 1
set firewall modify SOURCE_ROUTE rule 20 description 'Traffic to tunnel'
set firewall modify SOURCE_ROUTE rule 20 source address 192.168.101.0/24
set firewall modify SOURCE_ROUTE rule 20 modify table 2
将更改应用于内部接口;
set interfaces eth1 firewall in modify SOURCE_ROUTE
commit
save
现在,一切都应该就绪,只有子网192.168.101.0/24
中的IP地址将被路由到VPN隧道。
将笔记本电脑连接到eth1端口以及交换的eth2、eth3、eth4端口并通过DHCP获取地址后,我们就可以测试路由了。最好的测试方法是直接打开Google并输入“我在哪里”,您将看到一个根据您所在的端口变化的地图……成功!当然,真正的测试是BBC iPlayer……但我们就不多说了 ;-)
隧道性能
我进行了进一步的带宽测试,并设法达到了约11Mb/s的最大速度,这足以观看流媒体电影。
为了测试隧道,我们以同样的方式打开远端的服务器,但在本地端,这次我们告诉它连接到隧道的远端端点。
iperf3 -c 10.99.99.1 -t 30 -O 5
下一步是什么?
还有一些事情可以继续探索:
- DHCP桥接 - 应该可以通过远程DHCP服务器分配DHCP地址。
- 性能 - 我可以尝试不同的压缩算法,看看哪种最快。
- 协议 - 我可以考虑将隧道协议从TCP更改为UDP,看看这对性能有何影响。
但是,链路正在工作,稳定并且目前满足我的需求……那么为什么要冒险去弄坏它呢。
附加问题
您可能会在拓扑视图中注意到,我提到了1and1域名托管,这之所以出现,是因为有一天我在工作时想远程登录路由器检查一切是否正常。不幸的是,对我创建的DynDNS域的访问受到限制。但是,我还有其他几个域名,所以我只是从其中一个域名设置了一些转发子域名,转发到DynDNS域名,问题就解决了……
参考文献
- iPerf3
- EdgeMAX - 基于策略的路由(基于源地址)
- EdgeMAX - OpenVPN 站点到站点
- Ubiquiti EdgeRouter:为家庭使用配置这款极其低成本的企业级路由器
- OpenVPN 手册
关注点
我简直不敢相信一开始理解这件事有多难,毕竟,我实际上并没有将路由器用于任何超出默认设置的功能。
OpenVPN 不是我尝试的第一个协议。我最初研究了L2TP/IPSec(第二层隧道协议/IP安全),甚至尝试按照视频教程操作,但那简直是一团糟。我不知道是Q-Tel路由器的额外复杂性,还是动态寻址问题,它就是无法工作。(https://help.ubnt.com/hc/en-us/articles/204959404-EdgeMAX-Set-up-L2TP-over-IPsec-VPN-server)
另一件有趣的事情是电视,一台英国三星电视,有一天互联网似乎出了问题,链路就断了,无论我怎么做,它都无法恢复。最后,我不得不将电视恢复出厂设置,当SmartHub功能启动时,全部是阿拉伯语,没有更改的选项。修复链路并用笔记本电脑证明它正在工作,然后再次将电视恢复出厂设置,这次电视显示为英语,并允许我安装区域特定应用程序。
我确信最初遇到了DNS配置问题,导致它拾取了路由器上的某些缓存名称。直到我删除了接口的DNS转发,并将DHCP重新配置为发出Google DNS IP而不是路由器接口IP后,一切才恢复正常。
最大的麻烦是布线。我最初尝试通过几个不同的管道拉入cat-5线,但都没有成功。最后,我使用了电力线AV适配器在楼下实现了一个跳接,然后使用另一对电力线AV适配器在楼上跳接,到达网络设备所在的位置。
总的来说,这是一个有趣的小“项目”……我对结果很满意。我不得不承认,Ubiquiti硬件是我迄今为止最好的网络产品。它们不断扩展GUI功能,并且仍然有很多功能需要通过命令行才能实现。我想找到“美观”和“实用”之间的平衡,有点像Windows和Powershell!
时间会证明它如何运行,但到目前为止一切都很好。这大约只有4周时间,只发生过一次故障,那就是DNS配置不正确。希望现在已经修正了,事情现在应该非常稳定了。
历史
- 2016年10月4日 - 命令修正,补充图像和错别字修复。
- 2016年10月1日 - 第一版。