用docker一步搭建VPN(L2TP)

昨天在阿里云服务器内网搭建了pptp协议的VPN,但是在使用的过程中出了问题,一般的例如curl、wget的请求能够正常使用VPN网络,但是使用docker pull 命令拉取镜像时,进度条走不到一秒钟就停下来了,ping www.baidu.com连ip都无法显示出来,不仅VPN假死,DNS解析都受到了影响。于是查看系统日志,发现丢包严重,即VPN服务器发送给当前服务器的数据包基本被丢弃了,百度谷歌均无果,再折腾了路由表,也没有任何好转,于是怀疑是pptp协议的锅,准备使用L2TP协议试试。

除了上面提到的VPN客户端使用docker遇到的问题,其实服务端也受到了很大影响,按照昨天的配置方式,在配置nat转发时我们改动了iptables、而docker默认情况下端口映射的实现就是使用iptables、所以昨天的配置其实是影响到了VPN服务端的docker的正常运行,即便通过修改配置能够兼容到docker,后期修改时稍有不慎,直接就影响到业务了。作为一个docker爱好者,早应该想到无侵入形式的docker部署VPN。

好了,话不多说。

1、编写docker-compose编排文件

vi /data/docker/l2tp-ipsec-vpn-server/docker-compose.yml

main:
  image: fcojean/l2tp-ipsec-vpn-server
  environment:
    - VPN_IPSEC_PSK=abcdefg#itmx
    - VPN_USER_CREDENTIAL_LIST=[{"login":"itmx","password":"123456789"}]
    - VPN_PUBLIC_IP=VPN服务器的IP,若无此项,默认为公网IP
  ports:
    - "500:500/udp"
    - "4500:4500/udp"
  volumes:
    - /lib/modules:/lib/modules:ro
  privileged: true
  restart: always

写好编排文件之后,需要在 Docker 主机上加载 IPsec af_key 内核模块:

sudo modprobe af_key

2、启动容器

docker-compose up -d

别忘记在安全组中放行UDP协议500和4500端口哦

3、查看启动状态

#查看日志
docker-compose logs -f

#如需查看你的 IPsec VPN 服务器状态,可以在容器中运行 ipsec status 命令

docker exec -it l2tpipsecvpnserver_main_1 ipsec status

#若要查看当前已建立的 VPN 连接
docker exec -it l2tpipsecvpnserver_main_1 ipsec whack --trafficstatus

如果日志输出如下,则是创建成功了,如果没有日志输出,那可能是忘记加载模块,执行之后再试试

Attaching to l2tpipsecvpnserver_main_1 
main_1 | Trying to auto discover IPs of this server... 
main_1 | ================================================ 
main_1 | IPsec VPN server is now ready for use! 
main_1 | Connect to your new VPN with these details: 
main_1 | DNS: 8.8.8.8 
main_1 | Server IP: 你的公网IP 
main_1 | IPsec PSK: abcdefg#itmx 
main_1 | Users credentials : 
main_1 | Login : itmx Password : 123456789 
main_1 | Write these down. You'll need them to connect! 
main_1 | Setup VPN Clients: https://git.io/vpnclients 
main_1 | ================================================ 
main_1 | Redirecting to: /etc/init.d/ipsec start 
main_1 | Starting pluto IKE daemon for IPsec: Initializing NSS database ...

到此,VPN服务端就建立成功了!没错,你没看错,用Docker就是这么简单!


4、连接VPN

我这里主要介绍的是centos 7下连接L2TP,其他其他下连接请参考文末参考连接

如果服务器也使用docker,先检查一下IP转发是否开启

#检查是否开启ip转发,结果是1则已开启
cat /proc/sys/net/ipv4/ip_forward

#如果结果不是1,则
vi /etc/sysctl.conf

#修改或加入此行
net.ipv4.ip_forward = 1

#再通过以下命令使配置生效

sysctl -p

第一步、安装软件

yum -y install epel-release yum --enablerepo=epel -y install strongswan xl2tpd

第二步、编写配置文件

先准备几个必须的变量,从服务端的日志中可以获得

VPN_SERVER_IP='你的VPN服务器IP'
VPN_IPSEC_PSK='你的IPsec预共享密钥'
VPN_USER='你的VPN用户名'
VPN_PASSWORD='你的VPN密码'

接下来配置 strongSwan

cat > /etc/ipsec.conf <<EOF 
# ipsec.conf - strongSwan IPsec configuration file 
# basic configuration config setup 
# strictcrlpolicy=yes 
# uniqueids = no 
# Add connections here. 
# Sample VPN connections conn %default
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
keyexchange=ikev1
authby=secret
ike=aes128-sha1-modp1024,3des-sha1-modp1024!
esp=aes128-sha1-modp1024,3des-sha1-modp1024!
conn myvpn 
keyexchange=ikev1 
left=%defaultroute 
auto=add
authby=secret
type=transport
leftprotoport=17/1701
rightprotoport=17/1701
right=$VPN_SERVER_IP
EOF

cat > /etc/ipsec.secrets <<EOF : PSK "$VPN_IPSEC_PSK" EOF
chmod 600 /etc/ipsec.secrets

# For CentOS/RHEL & Fedora ONLY
mv /etc/strongswan/ipsec.conf /etc/strongswan/ipsec.conf.old 2>/dev/null
mv /etc/strongswan/ipsec.secrets /etc/strongswan/ipsec.secrets.old 2>/dev/null
ln -s /etc/ipsec.conf /etc/strongswan/ipsec.conf
ln -s /etc/ipsec.secrets /etc/strongswan/ipsec.secrets

然后配置xl2tpd

cat > /etc/xl2tpd/xl2tpd.conf <<EOF
[lac myvpn]
lns = $VPN_SERVER_IP
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd.client
length bit = yes
EOF

cat > /etc/ppp/options.l2tpd.client <<EOF
ipcp-accept-local
ipcp-accept-remote
refuse-eap
require-chap
noccp
noauth
mtu 1280
mru 1280
noipdefault
defaultroute
usepeerdns
connect-delay 5000
name $VPN_USER
password $VPN_PASSWORD
EOF

chmod 600 /etc/ppp/options.l2tpd.client

至此 VPN 客户端配置已完成。按照下面的步骤进行连接。

第三步、建立连接

注意: 当你每次尝试连接到 VPN 时,必须重复下面的所有步骤。

#创建 xl2tpd 控制文件
mkdir -p /var/run/xl2tpd
touch /var/run/xl2tpd/l2tp-control

#重启服务
service strongswan restart
service xl2tpd restart

#开始 IPsec 连接
strongswan up myvpn

#开始 L2TP 连接
echo "c myvpn" > /var/run/xl2tpd/l2tp-control

#到此,若连接成功,执行ip addr并且检查输出。现在你应该看到一个新的网络接口 ppp0

由于我的当前服务器并没有公网IP,所以对于路由表route我无需做太多的配置,直接添加一个新的默认路由,并且开始通过 VPN 服务器发送数据:

route add default dev ppp0

到此,我的当前服务器就能够正常访问互联网了,试试 curl ip.cn


好了,时间不早了,更多操作请参考以下链接👇


Docker 上的 IPsec VPN 服务器

配置 IPsec/L2TP VPN 客户端

评论