Linux Policy-based site-to-site IPsec VPN动态IP的配置及内网穿透的应用(StrongSwan)

上一篇文章提到了一点StrongSwan的配置。

本文继续使用StrongSwan。

StrongSwan的left和right是支持使用域名的,利用此可以实现动态IP的支持;上一篇文章用了type=transport模式转发UDP端口构建L2TPv3,如果没有L2组网的需求,其实可以直接利用type=tunnel模式实现L3转发。

网络拓扑:

上图中的路由器lan-router1和lan-router2都是通过pppoe接入互联网的,域名lan-router1.router和lan-router2.router通过ddns分别解析到了各自pppoe0的IP地址上;server1和server2分别通过lan-router1和lan-router2接入互联网。

下面的操作将在server1与lan-router2之间构建site-to-site IPsec VPN,接通192.168.1.0/24与10.0.0.0/24这两个内网。

提醒:用StrongSwan构建site-to-site IPsec VPN的话,需要至少有一端的UDP 500和4500端口在公网可以访问。

1. 配置StrongSwan

安装StrongSwan就不再阐述了。

在IPsec的配置文件中,left指本地,right指对方。

2.1 server1的配置

编辑/etc/ipsec.conf,末尾加入:

这里left直接用0.0.0.0表示任何IP都接受连接,right用lan-router2的ddns域名lan-router2.router。

其中left/rightsubnet分别定义了server1的内网IP段,server2的内网IP段,意思就是leftsubnet和rightsubnet之间的流量将走site-to-site IPsec VPN。left/rightsubnet支持定义多个子网的,用逗号分隔。

在server1的auto是route,意思是当内核遇到目的地为rightsubnet的流量,自动发起协商构建site-to-site IPsec VPN。

left/rightid是不建议省略的,另外记得在开头添加@阻止把字符串当成域名解析成IP。

其余的参数,大概就是使用aes-128加密,sha1签名,ikev2协议交换密钥,30秒发送一次心跳包(使用NAT的话尤其重要),心跳包超过120秒无回应重新构建连接(dpdaction=restart)。

编辑/etc/ipsec.secrets,在末尾加入(其中的pre-shared-key是密码,记得改成你自己定的值)

ipsec.secrets的格式,上一篇文章也有提到,是:

2.2 server2的配置

server2需开放UDP端口500与4500。

编辑/etc/ipsec.conf,末尾加入:

其实大体上就是把server1的配置中的left和right调换过来。

当然,这边的right用了域名lan-router1.router,这个域名是会解析到lan-router1 的pppoe0接口的IP的。

此外,这边的auto是add,dpdaction是clear,主要原因是server1处于内网,在server2是无法主动发起协商请求的,所以让StrongSwan启动时仅加载此配置,不作任何其它操作,并且心跳回应超时后,不重建连接。

编辑/etc/ipsec.secrets,在末尾加入(其中的pre-shared-key是密码,记得改成你自己定的值)

2.3 重启StrongSwan并发起协商构建连接

server1和lan-router2执行下面的命令重启StrongSwan:

发起协商是仅能从server1发起的,原因上一篇文章和开头已提过:

如果up有提示successfully,但是ping不通的话,见本文2.3防火墙的配置。

在lan-router2上测试:

因为设置了心跳,所以无需担心路由器上的NAT记录超时,此外server1上设置了自动重连,所以更换IP或者其它原因导致VPN断开后,只要ddns更新的DNS记录生效了或者网络恢复正常,理论上server1是会自动重连的,当然,理论上。

2. 其它配置

2.1 L2TPv3、GRE等应用

通过上面构造的VPN,因为server1和lan-router2都是分别拥有一个固定的内网IP的,所以可以直接指定双方的内网IP构建L2TPv3(详见上一篇文章)或者GRE之类的。

2.2 启用IPv4转发以及设置SNAT规则

上面配置的都是/24的子网,如果两边都未启用IPv4转发,双方都仅能访问对方的IP。

本文的拓扑中,server1是需要启用IPv4转发并设置SNAT的,lan-router2上一般不需要进行这两项配置。

如何启用IPv4转发以及设置SNAT规则,网络上很多资料,这个各位自行按实际情况解决。

2.3 防火墙的配置

这里给个匹配IPsec流量的规则,自行按需应用吧:

例如lan-router2上pppoe0接口可能配了防火墙对入网流量进行了较为严格的入网流量控制,会导致lan-router2可以主动访问server1但server1无法主动访问lan-router2,加入以下规则即可解决:

转发的类似,加入FORWARD链即可。

一款鲜为人知的杰出VPN方案 —— ACCEL-PPP

因PPTP简单、方便,无特别需要,平时需要用到VPN时一般都会首选PPTP。

数月前使用PPTP的过程中发现,Linux下的PoPToP方案极限速率仅有20 Mbps左右,而Windows下“网络策略和访问服务”提供的PPTP上限速率则高些,能达到70 – 80 Mbps。

当时了解到一款名为ACCEL-PPP的方案,尝试了一番,效果不负其名——ACCEL。

但今天发现,此方案的中文介绍、资料近乎无(英文介绍也不多),遂撰写此文,欲让更多人了解到此杰作。

 

服务器配置:

  • CPU: Intel Xeon L5520 *2
  • RAM: 48GB
  • 网络适配器: Intel 千兆网络适配器
  • 硬盘: 256GB SSD

 

网络环境:

  • ISP: 中国电信
  • 公网速率: 100 Mbps
  • 路由器: EdgeRouter X SFP (with hwnat, ipsec offload enable)

 

本文部分词语定义:

极限速率 —— 当数据传输速率在30秒内不能稳定提升,则视当前已达极限速率

 

PoPToP

PoPToP就是Linux更新源所提供的的pptpd。

达到极限速率后,使用top看到服务器上pptpd进程的CPU使用率仅有25-30%:

图1 —— PoPToP极限速率
图2 —— pptpd进程CPU使用率1
图3 —— pptpd进程CPU使用率2

速率已达极限,而资源使用却未达极限,明显问题在于PoPToP方案的资源利用率底下。

ACCEL-PPP PPTP

图4 —— ACCEL-PPP PPTP极限速率
图5 —— ACCEL-PPP PPTP CPU使用率

ACCEL-PPP的PPTP极限速率能达到50 Mbps多,使用top查看CPU使用率,可以发现大部分都被ksoftirqd占用,且使用率几乎可达一个核心的极限。

虽然未能达到我公网带宽的极限速率,但能充分利用资源达到如此高的速率已经很不错了。

ACCEL-PPP的文档没对其工作原理作出介绍,我也未深究其源码,暂不能解释其“高效”、以及受限于其“极限”的原因。

ACCEL-PPP L2TP与xl2tpd的性能对比

使用StrongSwan,IPSec PSK

xl2tpd

图6 —— xl2tpd效率1
图7 —— xl2tpd效率2

ACCEL-PPP L2TP

图8 —— ACCEL-PPP L2TP效率1
图9 —— ACCEL-PPP效率2

孰优孰劣,明显至极。

ACCEL-PPP的安装

本节以Debian 9为例,安装ACCEL-PPP。

安装编译器,cmake:

取得ACCEL-PPP源码(编写本文时,SourceForge的ACCEL-PPP 1.11.2的源码扩展名虽为.tar.bz2,但实际上只由tar打包,并无使用bzip压缩)

编译ACCEL-PPP:

ACCEL-PPP编译前需要使用cmake对所需的功能进行设置,支持的选项有以下:

  • -DBUILD_PPTP_DRIVER=TRUE —— 本选项用于编译PPTP内核模块,内核版本>= 2.6.37已内置PPTP模块,无需启用该选项。
  • -DBUILD_IPOE_DRIVER=TRUE —— 本选项用于编译IPoE内核模块。IPoE共享接口模式或VLAN监控下需要此模块。
  • -DBUILD_VLAN_MON_DRIVER=TRUE —— 编译VLAN监控模块。
  • -DKDIR=/usr/src/linux —— 若需要构建PPTP内核模块,则需要使用本选项指定内核源码目录。
  • -DCMAKE_INSTALL_PREFIX=/some/location —— 指定ACCEL-PPP安装目录,默认为/usr/local。
  • -DCMAKE_BUILD_TYPE=Debug —— 选择编译为DEBUG版本以用于调试抑或为RELEASE版本。
  • -DLOG_PGSQL=TRUE —— 编译log_pgsql模块用于使用PostreSQL数据库记录日志。
  • -DRADIUS=FALSE —— 关闭radius模块。
  • -DNETSNMP=TRUE —— 启用SNMP模块。
  • -DLUA=TRUE —— 启用LUA支持(仅用于IPoE)。
  • -DSHAPE=TRUE —— 启用流量控制功能。

本文编译为Release版本,关闭Radius,PGSQL,流量控制等功能。

重命名配置文件:

ACCEL-PPP的配置

从man可获取到accel-ppp配置文件的完整文档:

本小节仅对部分配置项进行说明。

[modules]

本部分定义了ACCEL-PPP需要启用的功能。

例如

则表示启用文件日志,pptp,l2tp等功能。

[core]

用于配置核心模块的参数。

当前版本支持的有以下两项:

[ppp]

ACCEL-PPP内置的ppp模块参数配置。

具体略。

[dns]

[client-ip-range]

[pptp]

[l2tp]

[chap-secrets]

[ip-pool]

示例配置文件

运行并使用ACCEL-PPP

客户端的使用方式与平常无差异,使用IPSec的,按照正常方式对IPSec进行配置即可。

总结

ACCEL-PPP网站有有言:

ACCEL-PPP是一个高性能的Linux VPN服务器应用。

致力于聚合各种热门的VPN技术。

单VPN上,对比如今广泛使用的PoPToP与xl2tp,ACCEL-PPP的优势非常明显,但如此杰作却鲜为人知,实为作者感到不平。

若你尝试ACCEL-PPP后,觉得好用,记得推荐给你身边的朋友!

ACCEL-PPP官网:http://accel-ppp.org/

SourceForge项目:https://sourceforge.net/projects/accel-ppp/

社区:http://accel-ppp.org/forum/

虚拟专用网(VPN)之无法访问百度之谜

不久前开了个香港Sunny Vsion的VPN,平时我一般都不使用VPN,今天才发现无法访问百度,而尝试其他网站却正常,遂探讨了一番。

我使用的都是学校的中国电信网络,本地连接VPN后,访问百度网站无任何回应,在服务器上可以成功地使用curl对百度发起请求,检查了iptables,未发现任何问题。

既然服务器能访问,那么理论上VPN也有权访问,但现在却与理论背道而驰。为了找出问题的根源,搬出抓包神器——tcpdump。

首先我在服务器上抓取本地分别透过VPN访问cPanel/WHM的208.74.0.0/16与百度的103.235.46.39/32的数据包,以作对比,查找错误。

cPanel/WHM:

百度:

首先,在两边的记录,都可以看到Flags [P.],这是开始传输内容的标记,因此可以肯定,我们本地与百度之间的TCP三次握手是顺利地完成了的,不然也就不会开始传输数据。

在与cPanel/WHM服务器通讯时,看到了Flags [F.],这是完成数据传输,结束TCP连接的标记。

但是在百度却没看到Flags [F.],可以看到103.235.46.39发送了很多类似seq 1:1063的数据包,但是我们本地仅返回了ack 1063给百度,根据TCP协议,ack的可以理解为“确认收到”,ack 1063,那就是说我们本地告诉百度的服务器确认收到了seq 1:1063的数据包。

TCP是一个可靠的协议,之所以说可靠,是因为服务器会重新发送客户端没有收到的数据包,可以保障数据的完整性,既然我们本地仅返回了ack 1063,百度服务器很自然就会重发我们没收到的数据包,也就对应了百度那边的抓包结果最后面的seq 1063:2515。

总算找到方向了:我们本地可能没有完整地收到百度发送的所有数据包!

为了确定我们本地是否真的没有收到数据包,我再次访问百度,并进行了双边抓包:

本地:

服务器:

服务器完完整整地收到了百度发送的数据包,我们本地收到了seq 1:1062,但下一个seq是6870:8262,再下一个居然是18426:19782!这丢包率真把我给吓坏了……

赶紧从本地MTR到服务器看看:

MTR To Server

然后走VPN MTR到百度看看:

MTR To BAIDU via VPN

虽然MTR可以看到有少量丢包,不过这丢包率完全不符合我TCPDUMP的结果,这说明这丢包根本不是线路不佳造成的。

完全不服……

想起来之前在家研究广电机顶盒时,遇到过桥架网卡后因为其中一个网卡MTU非1500(桥接后,桥接网卡的MTU不能大于MTU最小的网卡的MTU)而导致PPPOE连接成功却打不开网页的情况。

MTU是什么不在此长篇大论,至于为什么要减掉一部分数值,是构建了虚拟隧道的问题,数据包进入虚拟隧道前,还是要封装成适合进入这个虚拟隧道的类型的,因此数据包体积会比原来大,具体细节,不在此长篇大论,各位有兴趣可以通过搜索引擎了解。

更好服务器上也用桥接网卡,于是看了下br0(桥接网卡), eth0(物理网卡)和服务器与我本地通讯的ppp1的MTU:

MTU

br0和eth0都是1500, ppp1是1496,我本地的ppp也是1496。

看起来是非常正常且毫无问题的,因为默认情况下VPN构建的ppp的MTU都是1496这个值……

不过既然是非线路问题导致的丢包,改改MTU也无妨,于是分别在服务器和本地都把VPN构建的ppp的MTU改成1400:

再次curl百度:

CURL BAIDU

是成功地连上了……

不过我之前都在未桥架的服务器上搭建VPN,为了探究清楚是桥架还是该服务器的网络环境的问题,我又在另一台使用了桥架的服务器搭建了VPN并访问百度: CURL BAIDU USA

还好是成功的,ppp的mtu同样是1496,这就说明了这个问题在这次与桥接不沾边,是这台Sunny Vision服务器的问题。

虽然最后成功解决了无法打开百度(现在应该是说比较大的网页)的问题,但最大的问题是,目前为止,对于是何导致了此服务器无法使用1496,我还没有任何思绪……

才疏学浅啊,若各位有见解,请告知一下……

VPN下路由表的编辑,实现部分IP直连

平常在Windows下使用VPN,各位都会发现,所有出网的数据包都通过VPN了。虽然这样可以访问某些被“禁止访问”的网站,但访问国内的网站,速度却慢了。

事实上,连接VPN后,Windows会自动把系统的默认网关改为VPN的,因此数据包都通过了VPN服务器。既然如此,我们再对路由表进行操作,添加一些对国内IP生效的路由规则,那样就能实现访问国外网站时通过VPN,访问国内网站时直连。

Windows下对路由表进行操作的命令是route,route的用法如下:

上面分别是添加路由,更改路由,以及删除路由的用法。

首先连接VPN,让Windows自动更改路由。

接下来使用route对国内IP的路由表进行更改,下面提供一个国内IP的IP段列表:

Windows的打开cmd,执行以下的命令(不要保存为BAT再运行)

 

Linux使用pptpclient连接VPN后并无自动更改路由,所以需要自己添加一条规则,可以ip这个命令(ppp设备名称可以通过ifconfig查看),执行以下命令即可:

 

执行完上面的命令后,即可实现访问国内的网站直连,访问国外网站走VPN。