本文阐述 VPN 的基本原理、应用及实现
基本原理
应用
实现
PPTP
简介
点对点隧道协议(英语:Point to Point Tunneling Protocol,缩写为PPTP)是实现虚拟专用网(VPN)的方式之一。PPTP使用传输控制协议(TCP)创建控制通道来发送控制命令,以及利用通用路由封装(GRE)通道来封装点对点协议(PPP)数据包以发送数据。这个协议最早由微软等厂商主导开发,但因为它的加密方式容易被破解,微软已经不再建议使用这个协议。
PPTP的协议规范本身并未描述加密或身份验证的部分,它依靠点对点协议(PPP)来实现这些安全性功能。因为PPTP协议内置在微软视窗系统家族的各个产品中,在微软点对点协议(PPP)协议堆栈中,提供了各种标准的身份验证与加密机制来支持PPTP [1]。 在微软视窗系统中,它可以搭配PAP、CHAP、MS-CHAP v1/v2或EAP-TLS来进行身份验证。通常也可以搭配微软点对点加密(MPPE)或IPSec的加密机制来提高安全性[2]。
在Windows或Mac OS平台之外,Linux与FreeBSD等平台也提供开放源代码的版本。
原理
A PPTP tunnel is instantiated by communication to the peer on TCP port 1723. This TCP connection is then used to initiate and manage a GRE tunnel to the same peer. The PPTP GRE packet format is non standard, including a new acknowledgement number field replacing the typical routing field in the GRE header. However, as in a normal GRE connection, those modified GRE packets are directly encapsulated into IP packets, and seen as IP protocol number 47. The GRE tunnel is used to carry encapsulated PPP packets, allowing the tunnelling of any protocols that can be carried within PPP, including IP, NetBEUI and IPX.
In the Microsoft implementation, the tunneled PPP traffic can be authenticated with PAP, CHAP, MS-CHAP v1/v2 .
服务器
以 CentOS 7 为例:
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
#!/bin/sh
#
# 安装 PPTP VPN 服务端
#
# 修改自 https://github.com/HiSun001/centos7-pptp
#
# 当命令返回非 0 或使用未设置变量时强行退出
set -eu
# 调试开关(显示执行的命令)
set -x
NAME=aliyun
PASS=36798147
LOCAL_IP=192.168.12.1
REMOTE_IP='192.168.12.10-99'
ETH=eth0
yum -y install epel-release
yum -y install net-tools ppp pptpd
grep 'net\.ipv4\.ip_forward = 1' /etc/sysctl.conf >/dev/null || echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p
grep "$NAME pptpd $PASS" /etc/ppp/chap-secrets >/dev/null || cat >> /etc/ppp/chap-secrets <<END
$NAME pptpd $PASS *
END
cat >/etc/pptpd.conf <<END
option /etc/ppp/options.pptpd
localip $LOCAL_IP
remoteip $REMOTE_IP
END
cat >/etc/ppp/options.pptpd <<END
name pptpd
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
ms-dns 114.114.114.114
ms-dns 8.8.8.8
proxyarp
lock
nobsdcomp
novj
novjccomp
nologfd
END
systemctl start firewalld
systemctl enable firewalld
firewall-cmd --set-default-zone=public
firewall-cmd --permanent --add-port=1723/tcp
firewall-cmd --permanent --add-masquerade
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -i $ETH -p gre -j ACCEPT
firewall-cmd --reload
systemctl restart pptpd.service
systemctl enable pptpd.service
客户端
这部分讲解 VPN 客户端的配置,假设你的 VPN 服务器信息如下:
1
2
3
server_ip: 242.134.343.22
username: vpn
password: 123456
Windows 10
Settings(Win+I
) -> Network & Internet -> VPN -> Add a VPN connection:
名称 | 内容 | 说明 |
---|---|---|
VPN Provider | Windows(built-in) | 提供商 |
connection name | vpn1 |
取个你喜欢的名称即可 |
Server name or address | 242.134.343.22 |
VPN 服务器 IP 地址 |
VPN type | PPTP | PPTP是比较老的一种类型,较新的是 IPsec |
Type of sign-info | User name and password | 认证方式 |
User name | vpn |
用户名 |
Password | 123456 |
密码 |
可能遇到的问题:
- Windows 10 PPTP VPN No Internet?
1 2
PS C: \> Get-VpnConnection PS C: \> Set-VpnConnection -Name "YOURVPN" -SplitTunneling $True -PassThru
或者:Network and Internet settings -> Change adapter options -> select your vpn connection -> Properties -> Networking tab -> select TCP/IPv4 -> Properties -> Advanced -> uncheck Use default gateway on remote network
Linux
Ubuntu
假设你当前使用的用户是有管理员权限的普通用户(而非 root):
1
2
3
4
5
6
sudo apt install ppp pptp-linux -y
sudo pptpsetup --create vpn1 --server 242.134.343.22 --username vpn --password 123456 --start --encrypt
ip ad
cat /var/log/syslog
cat /etc/ppp/peers/vpn1
sudo pppd call vpn1
CentOS
假设你当前使用的用户是 root 用户:
1
2
3
4
5
6
yum install ppp pptp pptp-setup -y
pptpsetup --create vpn1 --server 242.134.343.22 --username vpn --password 123456 --start --encrypt
ip ad
cat /var/log/messages
cat /etc/ppp/peers/vpn1
pppd call vpn1
或者直接使用以下函数(注意替换参数):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
config_pptp_client(){
local server="${1-:server}"
local user="${2:-user}"
local pass="${3:-pass}"
yum install ppp pptp pptp-setup -y
modprobe nf_conntrack_pptp
echo nf_conntrack_pptp >> /etc/modules-load.d/vpn.conf
pptpsetup --create ali --server $server --username $user --password $pass --start --encrypt
cat <<EOF > /root/auto-reconnect-pptp.sh
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ip a | grep 'ppp[0-9]:' || pppd call ali
EOF
chmod +x /root/auto-reconnect-pptp.sh
echo '*/1 * * * * root /root/auto-reconnect-pptp.sh > /root/auto-reconnect-pptp.log 2>&1' >> /etc/crontab
}
遇到的问题
分配静态 IP?
可以在服务器上设置,应该也可以在客户端上设置。笔者只测试过前者
The forth column in
/etc/ppp/chap-secrets
lets you assign a static IP address per user. Replace the*
with the IP you want that user to have.
1 2   user1 * User1Passwd 192.168.10.1   user2 * User2Passwd 192.168.10.2
——引用自 PPTP with Static IP / Networking, Server, and Protection / Arch Linux Forums
Can’t ping other machines on the VPN LAN?
问题描述:我在 CentOS 上搭建了 PPTP VPN 服务器,但是在 Ubuntu PPTP 客户端上却无法 ping 通同样连接了 VPN 的另一个 Windows 主机。
我在网上找了好久都没有找到解决方法,后来发现是因为我进入了一个误区——我一直以为是 VPN 服务器端的配置问题。后来看到网上有人提到修改下子网掩码就行。于是找 VPN 服务器上和子网掩码相关的配置,找了半天愣是没找到。我使用mask
关键字在man 8 pppd
和man 5 pptpd.conf
中搜索都没有找到
最后在网上找到了一个简单但不是一劳永逸的解决方案——手动添加静态路由:
1
route add -net 192.168.9.0 netmask 255.255.255.0 dev ppp0
详情参见 vpn - pptp on Ubuntu server can’t ping other machines on the LAN - Server Fault
(我突然想到个问题,PPTP 是 Point to Point Tunneling Protocol 的缩写,即点对点协议,那么它的子网掩码只能为 255.255.255.255 了吧?不能改才正常 )
VirtualBox guest under NAT can’t use VPN?
问题描述:在 Virtual Box 的 CentOS 7 虚拟机(使用的是 NAT 网卡)上配置 PPTP client 无法成功连接 PPTP Server:
1
LCP: timeout sending Config-Requests
通过 PPTP Client 排查后得出问题出在 No GRE received by PPTP Client 的 Simultaneous Tunnels via NAT Gateway 处:
If you have a NAT gateway, such as a DSL router, that presents one IP address to the network on which the PPTP Server is contacted, then only one PPTP connection can be active at once. The PPTP Server will only accept one.
Attempting to start a second tunnel to another IP address may also fail if the NAT software cannot differentiate the two connections. This may cause the first connection to fail.
即对于使用 NAT 网关的我而言(网关通过 PPPOE 拨号上网),和同一 VPN 服务器只能有一个链接,因为 VPN 服务器无法区分两个复用源 IP 地址的连接。
但是事实上却并非如此,我使用同一局域网的另一个主机是可以成功连接 VPN 服务器的,但是我主机中的 CentOS 虚拟机(虚拟机使用的是 NAT 网卡)却不行(无论我主机是否断开 VPN):
1
2
3
4
5
6
root@ac:~# pptpsetup --create gcsj --server 242.134.343.22 --username vpn --password 123456 --start --encrypt
Using interface ppp0
Connect: ppp0 <--> /dev/pts/1
LCP: timeout sending Config-Requests
Connection terminated.
Modem hangup
这里的问题尚待深入研究
后来受到 networking - How can I make VirtualBox guests share the host’s VPN connection? - Ask Ubuntu 的启发,想到了 NAT + 端口转发的方法:
如此配置后,使用同一 VPN 的人不但处于同一局域网,还能使用我电脑的上安装的虚拟机,只需:
1
ssh -p 7722 root@192.168.9.20
即可。其中 192.168.9.20 是我从 VPN 服务器那里获取到的 IP
L2TP
参见 setup-ipsec-vpn/clients-zh.md at master · hwdsl2/setup-ipsec-vpn
IPsec
链接
下面总结了本文中使用的所有链接: