因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%:



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


ACCEL-PPP的PPTP极限速率能达到50 Mbps多,使用top查看CPU使用率,可以发现大部分都被ksoftirqd占用,且使用率几乎可达一个核心的极限。
虽然未能达到我公网带宽的极限速率,但能充分利用资源达到如此高的速率已经很不错了。
ACCEL-PPP的文档没对其工作原理作出介绍,我也未深究其源码,暂不能解释其“高效”、以及受限于其“极限”的原因。
ACCEL-PPP L2TP与xl2tpd的性能对比
使用StrongSwan,IPSec PSK
xl2tpd


ACCEL-PPP L2TP


孰优孰劣,明显至极。
ACCEL-PPP的安装
本节以Debian 9为例,安装ACCEL-PPP。
安装编译器,cmake:
| 
					 1  | 
						apt-get install build-essential cmake  | 
					
取得ACCEL-PPP源码(编写本文时,SourceForge的ACCEL-PPP 1.11.2的源码扩展名虽为.tar.bz2,但实际上只由tar打包,并无使用bzip压缩):
| 
					 1 2  | 
						ACCEL_PPP_VERSION="1.11.2" wget -O- "https://sourceforge.net/projects/accel-ppp/files/accel-ppp-${ACCEL_PPP_VERSION}.tar.bz2/download" | tar -xvf-  | 
					
编译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,流量控制等功能。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | 
						mkdir accel-ppp-${ACCEL_PPP_VERSION}/build pushd accel-ppp-${ACCEL_PPP_VERSION}/build BUILD_JOBS=8 cmake \ -DBUILD_DRIVER=false \ -DCMAKE_INSTALL_PREFIX=/usr/local \ -DCMAKE_BUILD_TYPE=Release \ -DLOG_PGSQL=FALSE \ -DSHAPER=FALSE \ -DRADIUS=false \ -DNETSNMP=FALSE \ .. make -j${BUILD_JOBS} make -j${BUILD_JOBS} install popd  | 
					
重命名配置文件:
| 
					 1  | 
						mv /etc/accel-ppp.conf.dist /etc/accel-ppp.conf  | 
					
ACCEL-PPP的配置
从man可获取到accel-ppp配置文件的完整文档:
| 
					 1  | 
						man accel-ppp.conf  | 
					
本小节仅对部分配置项进行说明。
[modules]
本部分定义了ACCEL-PPP需要启用的功能。
例如
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  | 
						log_file pptp l2tp auth_mschap_v2 auth_mschap_v1 auth_chap_md5 auth_pap chap-secrets ippool pppd_compat  | 
					
则表示启用文件日志,pptp,l2tp等功能。
[core]
用于配置核心模块的参数。
当前版本支持的有以下两项:
| 
					 1 2 3 4 5  | 
						       log-error=path               错误日志文件路径        thread-count=n               工作线程数  | 
					
[ppp]
ACCEL-PPP内置的ppp模块参数配置。
具体略。
[dns]
| 
					 1 2 3 4  | 
						dns1=x.x.x.x     首选DNS服务器 dns2=x.x.x.x     备选DNS服务器  | 
					
[client-ip-range]
| 
					 1 2 3  | 
						设置允许连接本服务器的客户IP,格式:     x.x.x.x/mask (如:10.0.0.0/8)     x.x.x.x-y (如:10.0.0.1-254)  | 
					
[pptp]
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21  | 
						       配置PPTP模块参数        bind=x.x.x.x               PPTP服务器所监听的IP地址        port=n               指定PPTP服务器端口        verbose=n               如果n大于0,PPTP模块将会启用日志        echo-interval=n               如果n大于0,PPTP模块会每n秒发送一个echo-request        echo-failure=n               n个echo-request请求未收到echo-reply后,中断连接        timeout=n               等待客户端回应,n秒后无回应视为超时(默认为5秒)        mppe=deny|allow|prefer|require  | 
					
[l2tp]
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  | 
						       配置L2TP模块        bind=x.x.x.x        port=n        host-name=string               给客户端发送的Host-Name属性        hello-interval=n               指定发送Hello控制消息的周期。用于keep alive连接,如果peer无回应,中断连接。        recv-window=n               设置本地receive window的大小。只有sequence number在[last-Nr + 1, last-Nr + recv-window]范围内才会被接收(last-Nr是最后一次消息的sequence number)。最小值为1,最大值为32768,默认为16。        timeout=n               指定等待客户端completes tunnel and session negotiation的超时时间(单位:秒)        rtimeout=n               指定等待确认收到消息的时间(单位秒),丢包后将会重发。每次重发,超时值都会x2.               如果rtimeout被设为1,第一次重发将会在1秒后,第二次重发将会在2秒后,以此类推,直到收到回应或到达retransmit值。               n默认为1。        rtimeout-cap=n               最长重发时间,rtimeout的增长不会超过此值。               必须大于rtimeout,根据RFC 2661,一定不能小于8(accel-ppp没有此限制)。               默认为16。        retransmit=n               指定最大的重发次数        verbose=n               n >= 0,将会启用日志        mppe=deny|allow|prefer|require        secret=string               设置密钥        hide-avps=n               n >= 0,接收到的L2TP数据包属性将会隐藏(AVPs支持)  | 
					
[chap-secrets]
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 
						       配置chap-secrets模块        gw-ip-address=x.x.x.x[/mask]               当启用chap-secrets分配IP时,指定ppp接口使用的本地IP。Mask用于IPoE。        chap-secrets=file               设置chap-secrets文件路径(默认为/etc/ppp/chap-secrets)        encrypted=0|1               chap-secrets是否已加密(见README)        username-hash=hash1[,hash2]               指定计算用户名hash值的hash链。               hash1,hash2是openssl所支持的hash算法(如md5,sha1等)。  | 
					
[ip-pool]
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | 
						       配置ippool模块        gw-ip-address=x.x.x.x               指定ppp接口所使用的本地地址        shuffle=1|0               Specifies whether to shuffle initial address list. # 我不太了解本选项的功能,可能是不按顺序给客户端分配IP。        gw=range               设置本地ppp接口的IP范围,格式:               x.x.x.x/mask[,name=pool_name] (如:10.0.0.0/8)               x.x.x.x-y[,name=pool_name] (如:10.0.0.1-254)        tunnel=range               指定ppp接口的远程地址范围,格式:               x.x.x.x/mask[,name=pool_name]               x.x.x.x-y[,name=pool_name]        x.x.x.x/mask[,name=pool_name] or x.x.x.x-y[,name=pool_name]               同样用于指定ppp接口远程地址范围.  | 
					
示例配置文件
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76  | 
						[modules] log_file pptp auth_mschap_v2 auth_mschap_v1 auth_chap_md5 auth_pap chap-secrets ippool pppd_compat [core] log-error=/var/log/accel-ppp/core.log thread-count=4 [ppp] verbose=1 min-mtu=1280 mtu=1400 mru=1400 mppe=require ipv4=require ipv6=deny ipv6-intf-id=0:0:0:1 ipv6-peer-intf-id=0:0:0:2 ipv6-accept-peer-intf-id=1 lcp-echo-interval=20 lcp-echo-timeout=120 unit-cache=1 [pptp] verbose=1 ip-pool=pool1 [l2tp] verbose=1 dictionary=/usr/local/share/accel-ppp/l2tp/dictionary hello-interval=60 ip-pool=pool2 [dns] dns1=8.8.8.8 dns2=8.8.4.4 [client-ip-range] 0.0.0.0/0 [ip-pool] gw-ip-address=10.1.1.1 10.10.2.2-254,name=pool1 10.1.1.2-254,name=pool2 [log] log-file=/var/log/accel-ppp/accel-ppp.log log-emerg=/var/log/accel-ppp/emerg.log log-fail-file=/var/log/accel-ppp/auth-fail.log copy=1 level=3 [pppd-compat] ip-up=/etc/ppp/ip-up ip-down=/etc/ppp/ip-down ip-change=/etc/ppp/ip-change radattr-prefix=/var/run/radattr verbose=1 [chap-secrets] chap-secrets=/etc/ppp/chap-secrets [cli] verbose=1 telnet=127.0.0.1:2000 tcp=127.0.0.1:2001 [accel-dp] socket=/var/run/accel-dp.sock  | 
					
运行并使用ACCEL-PPP
| 
					 1 2 3  | 
						# -d参数用于运行为Daemon模式 # -c参数指定配置文件路径 /usr/local/sbin/accel-pppd -d -c /etc/accel-ppp.conf  | 
					
客户端的使用方式与平常无差异,使用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/