通过 ipsec/L2TP 搭建 VPN

ipsec/L2TP, VPN

基本概念

L2TP 第二层隧道协议(Layer Two Tunneling Protocol)是一种虚拟隧道协议,通常用于虚拟专用网。L2TP协议自身不提供加密与可靠性验证的功能,可以和安全协议搭配使用,从而实现数据的加密传输。L2TP 用来创建隧道连接,而 ipsec 协议则用来加密数据。因此, L2TP 协议经常会和 ipsec 协议一同出现。

准备环境

  • ubuntu Desktop 版本
  • ubuntu 开启路由转发功能
    • 编辑 /etc/systl.conf 文件,取消 ipv4.ip_forward=1 前的注释,使用 sysctl -p 重新加载配置文件
  • ubuntu 开启 NAT 转发(非常重要!!!)
    • 使用 iptables -t nat -A POSTROUTING -j MASQUERADE 命令,开启 NAT MASQUERADE 功能,便于让同网络的其他主机数据以 NAT 的方式发送。

构建 vpn server

该文章主要介绍使用 docker 镜像快速搭建 vpn server 服务器,服务器部署参考了:here

  1. 首先安装 docker 环境,ubuntu 中 docker 的安装可参考: here
  2. 安装 docker-compose, 可以参考:here, docker-compose 能够更方便的管理 docker
  3. 编写 docker-compose.yaml 文件,可使用以下内容作为参考。
  4. 使用 docker-compose up -d 命令快速启动 vpn server,然后使用docker-compose logs -f 查看容器日志,记下日志中的以下内容:Server IP,IPsec PSK,Username,Password
 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
# docker-compose.yaml
version: '3'

services:
  vpn:
    image: hwdsl2/ipsec-vpn-server
    restart: always
    env_file:
      - ./vpn.env
    ports:
      - "500:500/udp"
      - "4500:4500/udp"
      - "1701:1701"
    privileged: true
    hostname: ipsec-vpn-server
    container_name: ipsec-vpn-server

# vpn.env

# Note: All the variables to this image are optional.
# See README for more information.
# To use, uncomment and replace with your own values.

# Define IPsec PSK, VPN username and password
# - DO NOT put "" or '' around values, or add space around =
# - DO NOT use these special characters within values: \ " '
VPN_IPSEC_PSK=random_or_online_generate_PSK
VPN_USER=yourself_username
VPN_PASSWORD=yourself_password

# Define additional VPN users
# - DO NOT put "" or '' around values, or add space around =
# - DO NOT use these special characters within values: \ " '
# - Usernames and passwords must be separated by spaces
# VPN_ADDL_USERS=additional_username_1 additional_username_2
# VPN_ADDL_PASSWORDS=additional_password_1 additional_password_2

# Use a DNS name for the VPN server
# - The DNS name must be a fully qualified domain name (FQDN)
# VPN_DNS_NAME=vpn.example.com

# Specify a name for the first IKEv2 client
# - Use one word only, no special characters except '-' and '_'
# - The default is 'vpnclient' if not specified
# VPN_CLIENT_NAME=your_client_name

# Use alternative DNS servers
# - By default, clients are set to use Google Public DNS
# - Example below shows Cloudflare's DNS service
# VPN_DNS_SRV1=127.0.0.53
# VPN_DNS_SRV2=1.0.0.1

客户端操作

  1. 安装有 Decktop 的 ubuntu 版本
  2. 安装 VPN 客户端所需软件包:network-manager-l2tp-gnome
  3. VPN 客户端部署参考:here

客户端部署

按照以下步骤操作完成后,即可完成连接。

  1. Go to Settings -> Network -> VPN. Click the + button.
  2. Select Layer 2 Tunneling Protocol (L2TP).
  3. Enter anything you like in the Name field.
  4. Enter Your VPN Server IP for the Gateway.
  5. Enter Your VPN Username for the User name.
  6. Right-click the ? in the Password field, select Store the password only for all user.
  7. Enter Your VPN Password for the Password.
  8. Leave the NT Domain field blank.
  9. Click the IPsec Settings... button.
  10. Check the Enable IPsec tunnel to L2TP host checkbox.
  11. Leave the Gateway ID field blank.
  12. Enter Your VPN IPsec PSK for the Pre-shared key.
  13. Expand the Advanced section.
  14. Enter aes128-sha1-modp2048 for the Phase1 Algorithms.
  15. Enter aes128-sha1 for the Phase2 Algorithms.
  16. Click OK, then click Add to save the VPN connection information.
  17. Turn the VPN switch ON.

监听

由于客户端的连接并不能保持长久的连接,因此,我们需要一个监听脚本来进行。我写了一个简单的脚本并将其作为服务运行,可作参考。

监听脚本

 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
# listen-vpn script

#!/usr/bin/env sh


dev_name=xxxx
log_path=xxxx/reconnect.log
ca_path=xxxx.pem

echo "-----------------------------------------------" >> $log_path
echo "$(date +%F) $(date +%T) log can write access..." >> $log_path
echo "-----------------------------------------------" >> $log_path

modifyMtu(){
        nic_name=$(ifconfig | awk '{print $1}' | grep ppp | head -n 1 | awk -F ":" '{print $1}')
        mtu=$(ifconfig $nic_name | awk '{print $4}' | head -n 1)
        vpnserver=10.4.1.13

        if [ $mtu != 1500 ];then
                echo "$(date +%F) $(date +%T) mtu is low,changing to 1500..." >> $log_path
                ifconfig $nic_name mtu 1500 up >> $log_path
                echo "$(date +%F) $(date +%T) modify vpn server mtu.." >> $log_path
                ssh -i $ca_path ubuntu@$vpnserver docker exec ipsec-vpn-server ip a s $nic_name >> $log_path
                ssh -i $ca_path ubuntu@$vpnserver docker exec ipsec-vpn-server ifconfig $nic_name mtu 1500 up >> $log_path
                ssh -i $ca_path ubuntu@$vpnserver docker exec ipsec-vpn-server ip a s $nic_name >> $log_path
        fi
}

while true
do
        ifconfig ppp0 2> /dev/zero
        if [ $? != 0 ];then
                echo "$(date +%F) $(date +%T) start vpn..." >> $log_path
                echo "" >> $log_path
                nmcli connection up $dev_name >> $log_path
                echo "the vpn had started..." >> $log_path
                echo "-----------------------------------------------" >> $log_path
                modifyMtu
        else
                modifyMtu
                sleep 15
        fi
done

服务自动运行脚本

  • 服务存储路径:/etc/systemd/system/listen-vpn.service
  • 使用命令sudo systemctl start/stop listen-vpn.service 启动或者停止服务
  • 使用命令sudo systemctl enable listen-vpn.service 开启开机启动
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# listen-vpn.service 

[Unit]
Description=Listen vpn NIC and modify mtu

[Service]
Type=simple
ExecStart=/usr/bin/listen-vpn
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy