VPN(Virtual Private Network,即“虚拟私人网络”)是一种通过在数据传输过程中加密的方式来保障数据传输安全的通信方式,L2TP是其中的一种加密方式。VPN被人熟知是可以用来翻墙,不过翻墙不是VPN的主要功能,如果搭建VPN纯粹用来翻墙,可以参考翻墙利器SS,搭建教程:CentOS 搭建 Shadowsocks (ss),SS是纯粹用来翻墙的,所以稳定性和传输速度损耗的控制均比VPN好,不过,后来SS作者被请去喝茶了,原来的SS也就没再更新,也就有了SSR,算是SS的另外一个会更新的分支:ssrpanel:搭建shadowsocksr流量监控和用户管理面板

L2tp的搭建比较繁琐,涉及的部件较多,所以本文也略长,如有任何疑问或看不懂的地方,欢迎留言。

准备

搭建L2TP需要环境支持,所以需要提前查看是否支持,不支持的自行Google

1# 查看主机是否支持pptp,返回结果为yes就表示通过
2modprobe ppp-compress-18 && echo yes
3
4# 查看是否开启了TUN
5# 有的虚拟机主机需要开启,返回结果为**cat: /dev/net/tun: File descriptor in bad state**。就表示通过。
6cat /dev/net/tun

安装

L2TP VPN的支持需要以下组件:

  • xl2tp
  • libreswan
 1# 先更新
 2yum install update
 3yum update -y
 4
 5# 安装EPEL源,因为CentOS7官方源中已经去掉了xl2tpd
 6yum install -y epel-release
 7
 8# 安装xl2tpd和libreswan(libreswan用以实现IPSec,原先的openswan已经停止维护)
 9yum install -y xl2tpd libreswan lsof
10
11#安装iptables防火墙,一般都有自带
12yum install iptables

配置

xl2tpd

1# 编辑xl2tpd配置文件
2vim /etc/xl2tpd/xl2tpd.conf

配置文件如下,需要修改的部分已作说明:

 1;
 2; This is a minimal sample xl2tpd configuration file for use
 3; with L2TP over IPsec.
 4;
 5; The idea is to provide an L2TP daemon to which remote Windows L2TP/IPsec
 6; clients connect. In this example, the internal (protected) network
 7; is 192.168.1.0/24.  A special IP range within this network is reserved
 8; for the remote clients: 192.168.1.128/25
 9; (i.e. 192.168.1.128 ... 192.168.1.254)
10;
11; The listen-addr parameter can be used if you want to bind the L2TP daemon
12; to a specific IP address instead of to all interfaces. For instance,
13; you could bind it to the interface of the internal LAN (e.g. 192.168.1.98
14; in the example below). Yet another IP address (local ip, e.g. 192.168.1.99)
15; will be used by xl2tpd as its address on pppX interfaces.<font>
16
17[global]
18listen-addr = 服务器内网IP            # 去掉前面的分号,并将=后面改为服务器本地IP
19auth file = /etc/ppp/chap-secrets   # 添加本行
20port = 1701                                    # 添加本行
21;
22; requires openswan-2.5.18 or higher - Also does not yet work in combination
23; with kernel mode l2tp as present in linux 2.6.23+
24; ipsec saref = yes
25; Use refinfo of 22 if using an SAref kernel patch based on openswan 2.6.35 or
26;  when using any of the SAref kernel patches for kernels up to 2.6.35.
27; saref refinfo = 30
28;
29; force userspace = yes
30;
31; debug tunnel = yes
32
33[lns default]
34ip range = 192.168.1.128-192.168.1.254   #设置ip池,ip range是分配给用户的ip,有多少个用户就需要分配多少ip,所以建议分配多一点
35local ip = 192.168.1.99                  # local ip是分配给本机的ip
36require chap = yes
37refuse pap = yes
38require authentication = yes
39name = LinuxVPNserver
40ppp debug = yes
41pppoptfile = /etc/ppp/options.xl2tpd
42length bit = yes

ppp

1# 编辑pppoptfile文件
2vim /etc/ppp/options.xl2tpd

配置文件如下

 1ipcp-accept-local
 2ipcp-accept-remote
 3ms-dns  8.8.8.8         #添加本行
 4ms-dns  8.8.4.4         #添加本行
 5# ms-dns  192.168.1.1
 6# ms-dns  192.168.1.3
 7# ms-wins 192.168.1.2
 8# ms-wins 192.168.1.4
 9name xl2tpd
10noccp                         #前面不加#
11auth
12crtscts
13idle 1800
14mtu 1410                   #第一次配置不建议设置mtu,mru,否则可能789错误
15mru 1410
16nodefaultroute
17debug
18lock
19proxyarp
20connect-delay 5000
21# To allow authentication against a Windows domain EXAMPLE, and require the
22# user to be in a group "VPN Users". Requires the samba-winbind package
23# require-mschap-v2
24# plugin winbind.so
25# ntlm_auth-helper '/usr/bin/ntlm_auth --helper-protocol=ntlm-server-1 --require-membership-of="EXAMPLE\\VPN Users"'
26# You need to join the domain on the server, for example using samba:
27# http://rootmanager.com/ubuntu-ipsec-l2tp-windows-domain-auth/setting-up-openswan-xl2tpd-with-native-windows-clients-lucid.html
28refuse-pap
29refuse-chap
30refuse-mschap
31require-mschap-v2       # Windows连接必须设置
32persist
33logfile /var/log/xl2tpd.log

IPSec

1# 修改ipsec 主配置文件
2vim /etc/ipsec.conf

配置文件如下:

 1# /etc/ipsec.conf - Libreswan IPsec configuration file
 2
 3# This file:  /etc/ipsec.conf
 4#
 5# Enable when using this configuration file with openswan instead of libreswan
 6#version 2
 7#
 8# Manual:     ipsec.conf.5
 9
10# basic configuration
11config setup
12        # which IPsec stack to use, "netkey" (the default), "klips" or "mast".
13        # For MacOSX use "bsd"
14        protostack=netkey
15        #
16        # Normally, pluto logs via syslog. If you want to log to a file,
17        # specify below or to disable logging, eg for embedded systems, use
18        # the file name /dev/null
19        # Note: SElinux policies might prevent pluto writing to a log file at
20        #       an unusual location.
21        #logfile=/var/log/pluto.log
22        #
23        # The interfaces= line is only required for the klips/mast stack
24        #interfaces="%defaultroute"
25        #interfaces="ipsec0=eth0 ipsec1=ppp0"
26        #
27        # If you want to limit listening on a single IP - not required for
28        # normal operation
29        #listen=127.0.0.1
30                #listen=127.0.0.1
31        #
32        # Do not set debug options to debug configuration issues!
33        #
34        # plutodebug / klipsdebug = "all", "none" or a combation from below:
35        # "raw crypt parsing emitting control kernel pfkey natt x509 dpd
36        #  private".
37        # Note: "crypt" is not included with "all", as it can show confidential
38        #       information. It must be specifically specified
39        # examples:
40        # plutodebug="control parsing"
41        # plutodebug="all crypt"
42        # Again: only enable plutodebug or klipsdebug when asked by a developer
43        #plutodebug=none
44        #klipsdebug=none
45        #
46        # Enable core dumps (might require system changes, like ulimit -C)
47        # This is required for abrtd to work properly
48        # Note: SElinux policies might prevent pluto writing the core at
49        #       unusual locations
50        dumpdir=/var/run/pluto/
51        #
52        # NAT-TRAVERSAL support
53        # exclude networks used on server side by adding %v4:!a.b.c.0/24
54        # It seems that T-Mobile in the US and Rogers/Fido in Canada are
55        # using 25/8 as "private" address space on their wireless networks.
56        # This range has never been announced via BGP (at least upto 2015)
57        virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:100.64.0.0/10,%v6:fd00::/8,%v6:fe80::/10
58
59# For example connections, see your distribution's documentation directory,
60# or https://libreswan.org/wiki/
61#
62# There is also a lot of information in the manual page, "man ipsec.conf"
63#
64# It is best to add your IPsec connections as separate files in /etc/ipsec.d/

注意

  • 此配置文件不加 left=服务器ipinclude /etc/ipsec.d/*.conf 或者其他行
  • 第一行config setup必须左对齐,即前面不能有空格,否则会报错
  • 其他每一行都必须以Tab开头,否则会报错
  • 如果安装的是 openswan,可能需要在 config setup 之前添加 version 2.0

IPSec

先设置预共享密钥PSK

1# 编辑配置文件
2vim /etc/ipsec.secrets

配置文件如下:

1include /etc/ipsec.d/*.secrets
21.2.3.4 %any: PSK "wenjinyu"
  • 格式为 服务器IP %any: PSK “预共享密钥”,其中 %any:PSK 之间有空格

接下来是配置服务器

1# 修改/etc/ipsec.d/l2tp_psk.conf文件
2vim /etc/ipsec.d/l2tp_psk.conf

配置文件如下:

 1conn L2TP-PSK-NAT
 2        rightsubnet=vhost:%priv
 3        also=L2TP-PSK-noNAT
 4conn L2TP-PSK-noNAT
 5        authby=secret
 6        pfs=no
 7        auto=add
 8        keyingtries=3
 9        dpddelay=30
10        dpdtimeout=120
11        dpdaction=clear
12        rekey=no
13        ikelifetime=8h
14        keylife=1h
15        type=transport
16        left=1.2.3.4        #修改为服务器IP
17        leftprotoport=17/1701
18        right=%any
19        rightprotoport=17/%any

注意

  • conn开头的两行必须左对齐,开头不能有空格,其他每一行必须以Tab开头

添加账号密码

1vim /etc/ppp/chap-secrets

配置文件如下:

1# Secrets for authentication using CHAP
2# client        server  secret                  IP addresses
3user * passwd *

配置形式为 用户名+*+密码+*

  • 第一个星号是服务类型,在这里是L2TP,因为PPTP的账号密码管理文件也是此文件,所以以通配符*代替更好
  • 第二个星号是用户地址限制,如果填进去某个IP,则是限制只能此IP连接该VPN

开启内核转发

必须开启此项,连接VPN时才能访问公网,不然只能访问服务器内网

1vim /etc/sysctl.conf

配置文件如下:

 1# Kernel sysctl configuration file for Red Hat Linux
 2#
 3# For binary values, 0 is disabled, 1 is enabled.  See sysctl(8) and
 4# sysctl.conf(5) for more details.
 5#
 6# Use '/sbin/sysctl -a' to list all possible parameters.
 7
 8# Controls IP packet forwarding
 9net.ipv4.ip_forward = 1            #此处的值改为1,开启内核转发
10
11# Controls source route verification
12
13# Do not accept source routing
14net.ipv4.conf.default.accept_source_route = 0
15
16# Controls the System Request debugging functionality of the kernel
17kernel.sysrq = 0
18
19# Controls whether core dumps will append the PID to the core filename.
20# Useful for debugging multi-threaded applications.
21kernel.core_uses_pid = 1
22
23# Controls the use of TCP syncookies
24
25# Controls the default maxmimum size of a mesage queue
26kernel.msgmnb = 65536
27
28# Controls the maximum size of a message, in bytes
29kernel.msgmax = 65536
30
31# Controls the maximum shared segment size, in bytes
32kernel.shmmax = 68719476736
33
34# Controls the maximum number of shared memory segments, in pages
35kernel.shmall = 4294967296
36
37vm.swappiness = 0
38net.ipv4.neigh.default.gc_stale_time = 120
39
40
41# see details in https://help.aliyun.com/knowledge_detail/39428.html
42net.ipv4.conf.all.rp_filter = 0
43net.ipv4.conf.default.rp_filter = 0                #此处的值必须是0
44net.ipv4.conf.default.arp_announce = 2
45net.ipv4.conf.lo.arp_announce=2
46net.ipv4.conf.all.arp_announce=2
47net.ipv4.conf.all.send_redirects = 0               #添加这几行
48net.ipv4.conf.default.send_redirects = 0           #添加这几行
49net.ipv4.conf.all.log_martians = 0                 #添加这几行
50net.ipv4.conf.default.log_martians = 0             #添加这几行
51net.ipv4.conf.all.accept_redirects = 0             #添加这几行
52net.ipv4.conf.default.accept_redirects = 0         #添加这几行
53net.ipv4.icmp_ignore_bogus_error_responses = 1     #添加这几行
54
55# see details in https://help.aliyun.com/knowledge_detail/41334.html
56net.ipv4.tcp_max_tw_buckets = 5000
57net.ipv4.tcp_syncookies = 1
58net.ipv4.tcp_max_syn_backlog = 1024
59net.ipv4.tcp_synack_retries = 2
60
61//以下三行在我的服务器报错,所以注释掉了,如果没报错则不用注释
62#net.ipv6.conf.all.disable_ipv6 = 1
63#net.ipv6.conf.default.disable_ipv6 = 0
64#net.ipv6.conf.lo.disable_ipv6 = 1

重新加载内核配置项,使刚才的更改生效

1sysctl -p

如果输出结果有显示 net.ipv4.ip_forward = 1 ,则说明更改生效

测试

开启IPSec

1ipsec setup start

ipsec setup start等同于service ipsec start提示信息如下:

1Redirecting to: service ipsec start
2Starting pluto IKE daemon for IPsec:                    [  OK  ]

确认IPSec状态

1ipsec verify

如果配置正确,那么提示信息应该像这个样子:

 1Verifying installed system and configuration files
 2
 3Version check and ipsec on-path                         [OK]
 4Libreswan 3.15 (netkey) on 2.6.32-696.16.1.el6.x86_64
 5Checking for IPsec support in kernel                    [OK]
 6 NETKEY: Testing XFRM related proc values
 7         ICMP default/send_redirects                    [OK]
 8         ICMP default/accept_redirects                  [OK]
 9         XFRM larval drop                               [OK]
10Pluto ipsec.conf syntax                                 [OK]
11Hardware random device                                  [N/A]
12Checking rp_filter                                      [OK]
13Checking that pluto is running                          [OK]
14 Pluto listening for IKE on udp 500                     [OK]
15 Pluto listening for IKE/NAT-T on udp 4500              [OK]
16 Pluto ipsec.secret syntax                              [OK]
17Checking 'ip' command                                   [OK]
18Checking 'iptables' command                             [OK]
19Checking 'prelink' command does not interfere with FIPSChecking for obsolete ipsec.conf options                          [OK]
20Opportunistic Encryption                                [DISABLED]

如果有错误信息,部分问题解决如下:

1Pluto listening for IKE on udp 500            [FAILED]

解决办法:安装 lsofyum install lsof

1Checking NAT and MASQUERADEing           [N/A]

解决办法:更改iptables规则:iptables -t nat -A POSTROUTING -j MASQUERADE

1can not load config '/etc/ipsec.conf': /etc/ipsec.conf:58: syntax error, unexpected KEYWORD, expecting $end [rightsubnet]

解决办法:/etc/ipsec.conf 文件除了 conn 开头的两行之外,其他的都要以 Tab缩进 开头

1SAref kernel support                  [N/A]

解决办法:修改/etc/xl2tpd/xl2tpd.conf

1[global]
2ipsec saref = no  # 将yes改为no
1Two or more interfaces found, checking IP forwarding   [FAILED]
2Checking NAT and MASQUERADEing           [OK]

解决办法:只要 cat /proc/sys/net/ipv4/ip_forward 返回结果是 1 就没事,如果还不行,就按照上面更改 sysctl.conf 文件

开启xl2tpd

1service xl2tpd restart

提示信息如下:

1stopping xl2tpd:                                        [  OK  ]
2Starting xl2tpd:                                        [  OK  ]

xl2tp debug

1xl2tpd -D

测试连接

关闭iptables:

1service iptables stop

此时关闭iptables防火墙进行测试,已经可以连上VPN,可以上外网

其他

防火墙iptables设置

不开防火墙裸奔也不是办法,所以将防火墙默认拒绝所有接口,然后开放需要使用的接口即可。

清空防火墙配置:

1iptables -P INPUT ACCEPT     # 改成 ACCEPT 标示接收一切请求
2iptables -F                  # 清空默认所有规则
3iptables -X                  # 清空自定义所有规则
4iptables -Z                  # 计数器置0

配置防火墙:

1iptables -A INPUT -i lo -j ACCEPT                                # 允许127.0.0.1访问本地服务
2iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT         # 允许访问外部服务
3iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT        # 允许 ping
4iptables -A INPUT -p tcp --dport 22 -j ACCEPT                    # 开启 ssh 端口

配置ip转发:

1iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth1 -j MASQUERADE

对iptables规则进行保存:

1service iptables save

重启iptables,使规则生效:

1service iptables restart

添加开机自启:

1chkconfig iptables on           # 开机启动 iptables
2chkconfig xl2tpd on             # 开机启动 xl2tpd
3chkconfig ipsec on              # 开机启动 IPSec

报错修复

运行 ipsec verify 时报错:

  • 报错信息
1ICMP default/send_redirects    [NOT DISABLED]
2ICMP default/accept_redirects   [NOT DISABLED]
  • 解决办法:

根据提示,需要关闭sendredirects和acceptredirects。查看这两个下的所有选项,根据网卡数量,选项个数无法确定,其中也可能会包含IPv6的选项,IPv6的不需要改

1sysctl -a | grep -e 'send_redirects'
2sysctl -a | grep -e 'accept_redirects'

可以直接通过下面的脚本把上面显示的所有IPv4的选项全部设置为0

1#!/bin/bash
2for each in /proc/sys/net/ipv4/conf/*
3do
4echo 0 > $each/send_redirects
5echo 0 > $each/accept_redirects
6done

修改完成后,再进行一次 ipsec 验证即可看到结果,[NOT DISABLE]已变为[OK]

客户端设置

  1. Windows设置:错误 789、792
  • windows+r 打开运行,输入 services.msc,查找 ipsec policy agent,启用服务
  • 打开注册表,路径HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Rasman\Parameters
    • 添加DWORD值(32位)值,名称 ProhibitIpSec,值为 1
    • 由于缺省的 Windows XP L2TP 传输策略不允许不使用 IPSec 加密的 L2TP 传输,修改 AllowL2TPWeakCrypto 的值为 1
    • 重启
  1. iOS 联通移动信号无法连接,只能wifi
  2. Android Android对l2tp的支持有bug,所以连不上

后期

  • 查看连接情况:

CentOS:/var/log/secure Debian:/var/log/auth.log

小记

配置文件

配置文件路径 设置内容
/etc/xl2tpd/xl2tpd.conf ip池、内网IP
/etc/ppp/options.xl2tpd mtu、dns
/etc/ipsec.conf IPSec主配置文件
/etc/ipsec.secrets 预共享密钥
/etc/ipsec.d/l2tp_psk.conf 服务器IP
/etc/ppp/chap-secrets 帐号密码
/etc/sysctl.conf 开启内核转发
/var/log/secure 日志

所需要安装的软件

软件 作用
libreswan(ipsec) 提供一个密钥
ppp 拨号软件,提供用户名和密码
xl2tpd 提供L2TP服务
sysctl 提供服务器内部转发
iptables 提供请求从服务器内部转向外部,外部响应转向服务器内部