Added L2TP/IPSec VPN Server Docker Image

Signed-off-by: Teddysun <i@teddysun.com>
This commit is contained in:
Teddysun 2018-06-30 15:54:13 +09:00
parent 686fd98b77
commit 890f0473c0
No known key found for this signature in database
GPG Key ID: 09BD4C080AD6C46D
7 changed files with 871 additions and 0 deletions

View File

@ -0,0 +1,3 @@
.dockerignore
README.md
l2tp.env

25
docker/l2tp/Dockerfile Normal file
View File

@ -0,0 +1,25 @@
# Dockerfile for L2TP/IPSec VPN Server
# Copyright (C) 2018 Teddysun <i@teddysun.com>
FROM debian:stretch
MAINTAINER Teddysun <i@teddysun.com>
RUN set -ex \
&& printf "deb http://deb.debian.org/debian sid main" > /etc/apt/sources.list.d/sid.list \
&& apt-get update \
&& apt-get -t sid install -y --no-install-recommends libreswan xl2tpd \
&& apt-get install -y --no-install-recommends wget iproute2 openssl ca-certificates kmod net-tools iptables \
&& apt-get -y autoremove \
&& apt-get -y clean \
&& rm -rf /var/lib/apt/lists/*
COPY ./ipsec /etc/init.d/ipsec
COPY ./l2tp.sh /usr/bin/l2tp
COPY ./l2tpctl.sh /usr/bin/l2tpctl
RUN chmod 755 /etc/init.d/ipsec /usr/bin/l2tp /usr/bin/l2tpctl
VOLUME /lib/modules
EXPOSE 500/udp 4500/udp
CMD [ "/usr/bin/l2tp" ]

128
docker/l2tp/README.md Normal file
View File

@ -0,0 +1,128 @@
## L2TP/IPsec VPN Server Docker Image by Teddysun
Docker image to run a L2TP/IPsec VPN Server, with both `L2TP/IPsec PSK` and `IPSec Xauth PSK`.
Based on Debian 9 (Stretch) with latest libreswan (IPsec VPN software) and xl2tpd (L2TP daemon).
Docker images are built for quick deployment in various computing cloud providers.
For more information on docker and containerization technologies, refer to [official document][1].
## Prepare the host
If you need to install docker by yourself, follow the [official installation guide][2].
## Pull the image
```bash
$ docker pull teddysun/l2tp
```
This pulls the latest release of shadowsocks-libev.
It can be found at [Docker Hub][3].
## Start a container
You **must create a environment file** `/etc/l2tp.env` in host at first, and sample value is below:
```
VPN_IPSEC_PSK=teddysun.com
VPN_USER=vpnuser
VPN_PASSWORD=vpnpassword
VPN_PUBLIC_IP=
VPN_L2TP_NET=
VPN_L2TP_LOCAL=
VPN_L2TP_REMOTE=
VPN_XAUTH_NET=
VPN_XAUTH_REMOTE=
VPN_DNS1=
VPN_DNS2=
```
This will create a default user account for L2TP/IPsec VPN login, which can be used by your **multiple devices**.
The IPSec PSK (pre-shared key) is specified by the `VPN_IPSEC_PSK` environment variable.
The username is specified in `VPN_USER` environment variable.
and password is specified in `VPN_PASSWORD` environment variable.
If your VPS has multiple public IP addresses, maybe public IP need to specified in `VPN_PUBLIC_IP` environment variable.
There is an example to start a container:
```bash
$ docker run -d --privileged -p 500:500/udp -p 4500:4500/udp --name l2tp --env-file /etc/l2tp.env -v /lib/modules:/lib/modules teddysun/l2tp
```
**Note**: The UDP port number `500` and `4500` must be opened in firewall.
## Check container details
If you want to view the container logs:
```bash
$ docker logs l2tp
```
Output log like below:
```
L2TP/IPsec VPN Server with the Username and Password is below:
Server IP: Your Server public IP
IPSec PSK: IPSec PSK (pre-shared key)
Username : VPN username
Password : VPN password
Redirecting to: /etc/init.d/ipsec start
Starting pluto IKE daemon for IPsec: Initializing NSS database
xl2tpd[1]: Not looking for kernel SAref support.
xl2tpd[1]: Using l2tp kernel support.
xl2tpd[1]: xl2tpd version xl2tpd-1.3.12 started on 1d20eaecd9f2 PID:1
xl2tpd[1]: Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.
xl2tpd[1]: Forked by Scott Balmos and David Stipp, (C) 2001
xl2tpd[1]: Inherited by Jeff McAdams, (C) 2002
xl2tpd[1]: Forked again by Xelerance (www.xelerance.com) (C) 2006-2016
xl2tpd[1]: Listening on IP address 0.0.0.0, port 1701
```
To check the status of your L2TP/IPSec VPN server, you can confirm `ipsec status` to your container like below:
```bash
$ docker exec -it l2tp ipsec status
```
## Manage VPN Users
If you want to add, modify or remove user accounts, please do it simple like below:
### List all users
```bash
$ docker exec -it l2tp l2tpctl -l
```
### Add a user
```bash
$ docker exec -it l2tp l2tpctl -a
```
### Delete a user
```bash
$ docker exec -it l2tp l2tpctl -d
```
### Modify a user password
```bash
$ docker exec -it l2tp l2tpctl -m
```
### Print help information
```bash
$ docker exec -it l2tp l2tpctl -h
```
[1]: https://docs.docker.com/
[2]: https://docs.docker.com/install/
[3]: https://hub.docker.com/r/teddysun/l2tp/

304
docker/l2tp/ipsec Normal file
View File

@ -0,0 +1,304 @@
#!/bin/sh
# IPsec startup and shutdown script
#
### BEGIN INIT INFO
# Provides: ipsec
# Required-Start: $network $remote_fs $syslog $named
# Required-Stop: $syslog $remote_fs
# Default-Start:
# Default-Stop: 0 1 6
# Short-Description: Start Libreswan IPsec at boot time
# Description: Enable automatic key management for IPsec (KLIPS and NETKEY)
### END INIT INFO
#
### see https://bugzilla.redhat.com/show_bug.cgi?id=636572
### Debian and Fedora interpret the LSB differently for Default-Start:
# Copyright (C) 1998, 1999, 2001 Henry Spencer.
# Copyright (C) 2002 Michael Richardson <mcr@freeswan.org>
# Copyright (C) 2006 Michael Richardson <mcr@xelerance.com>
# Copyright (C) 2008 Michael Richardson <mcr@sandelman.ca>
# Copyright (C) 2008-2015 Tuomo Soini <tis@foobar.fi>
# Copyright (C) 2012 Paul Wouters <paul@libreswan.org>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# ipsec sysv style init.d script for starting and stopping
# the IPsec security subsystem (KLIPS and Pluto).
#
# This script becomes /etc/init.d/ipsec
# and is also accessible as "ipsec setup"
#
# The startup and shutdown times are a difficult compromise (in particular,
# it is almost impossible to reconcile them with the insanely early/late
# times of NFS filesystem startup/shutdown). Startup is after startup of
# syslog and pcmcia support; shutdown is just before shutdown of syslog.
#
# chkconfig: - 47 76
# description: IPsec provides encrypted and authenticated communications; \
# NETKEY/KLIPS is the kernel half of it, Pluto is the user-level management daemon.
test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x
# Source function library.
if [ -f /etc/init.d/functions ]; then
. /etc/init.d/functions
elif [ -f /lib/lsb/init-functions ]; then
. /lib/lsb/init-functions
fi
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 6
if [ $(id -u) -ne 0 ]; then
echo "permission denied (must be superuser)" | \
logger -s -p daemon.error -t ipsec_setup 2>&1
exit 4
fi
if [ $(ip addr list | grep -c cipsec) -ne 0 ]; then
echo "Cisco IPsec client is already loaded, aborting! (cipsec# device found)"
exit 1
fi
# where the private directory and the config files are
IPSEC_CONF="${IPSEC_CONF:-/etc/ipsec.conf}"
IPSEC_EXECDIR="${IPSEC_EXECDIR:-/usr/lib/ipsec}"
IPSEC_SBINDIR="${IPSEC_SBINDIR:-/usr/sbin}"
unset PLUTO_OPTIONS
rundir=/var/run/pluto
plutopid=${rundir}/pluto.pid
plutoctl=${rundir}/pluto.ctl
lockdir=/var/lock/subsys
lockfile=${lockdir}/ipsec
ipsecversion=/proc/net/ipsec_version
kamepfkey=/proc/net/pfkey
# /etc/resolv.conf related paths
LIBRESWAN_RESOLV_CONF=${rundir}/libreswan-resolv-conf-backup
ORIG_RESOLV_CONF=/etc/resolv.conf
# there is some confusion over the name - just do both
[ -f /etc/sysconfig/ipsec ] && . /etc/sysconfig/ipsec
[ -f /etc/sysconfig/pluto ] && . /etc/sysconfig/pluto
# misc setup
umask 022
# standardize PATH, and export it for everything else's benefit
PATH="${IPSEC_SBINDIR}:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin"
export PATH
mkdir -p ${rundir}
chmod 700 ${rundir}
verify_config() {
[ -f ${IPSEC_CONF} ] || exit 6
config_error=$(ipsec addconn --config ${IPSEC_CONF} --checkconfig 2>&1)
RETVAL=$?
if [ ${RETVAL} -gt 0 ]; then
echo "Configuration error - the following error occurred:"
echo ${config_error}
echo "IKE daemon status was not modified"
exit ${RETVAL}
fi
}
start() {
echo -n "Starting pluto IKE daemon for IPsec: "
ipsec _stackmanager start
# pluto searches the current directory, so this is required for making it selinux compliant
cd /
# Create nss db or convert from old format to new sql format
ipsec --checknss
# Enable nflog if configured
ipsec --checknflog > /dev/null
# This script will enter an endless loop to ensure pluto restarts on crash
ipsec _plutorun --config ${IPSEC_CONF} --nofork ${PLUTO_OPTIONS} &
[ -d ${lockdir} ] || mkdir -p ${lockdir}
touch ${lockfile}
# Because _plutorun starts pluto at background we need to make sure pluto is started
# before we know if start was successful or not
for waitsec in 1 2 3 4 5; do
if status >/dev/null; then
RETVAL=0
break
else
echo -n "."
sleep 1
RETVAL=1
fi
done
if [ ${RETVAL} -ge 1 ]; then
rm -f ${lockfile}
fi
echo
return ${RETVAL}
}
stop() {
if [ -e ${plutoctl} ]; then
echo "Shutting down pluto IKE daemon"
ipsec whack --shutdown 2>/dev/null
# don't use seq, might not exist on embedded
for waitsec in 1 2 3 4 5 6 7 8 9 10; do
if [ -s ${plutopid} ]; then
echo -n "."
sleep 1
else
break
fi
done
echo
rm -f ${plutoctl} # we won't be using this anymore
fi
if [ -s ${plutopid} ]; then
# pluto did not die peacefully
pid=$(cat ${plutopid})
if [ -d /proc/${pid} ]; then
kill -TERM ${pid}
RETVAL=$?
sleep 5;
if [ -d /proc/${pid} ]; then
kill -KILL ${pid}
RETVAL=$?
fi
if [ ${RETVAL} -ne 0 ]; then
echo "Kill failed - removing orphaned ${plutopid}"
fi
else
echo "Removing orphaned ${plutopid}"
fi
rm -f ${plutopid}
fi
ipsec _stackmanager stop
ipsec --stopnflog > /dev/null
# cleaning up backup resolv.conf
if [ -e ${LIBRESWAN_RESOLV_CONF} ]; then
if grep 'Libreswan' ${ORIG_RESOLV_CONF} > /dev/null 2>&1; then
cp ${LIBRESWAN_RESOLV_CONF} ${ORIG_RESOLV_CONF}
fi
rm -f ${LIBRESWAN_RESOLV_CONF}
fi
rm -f ${lockfile}
return ${RETVAL}
}
restart() {
verify_config
stop
start
return $?
}
status() {
local RC
if [ -f ${plutopid} ]; then
if [ -r ${plutopid} ]; then
pid=$(cat ${plutopid})
if [ -n "$pid" -a -d /proc/${pid} ]; then
RC=0 # running
else
RC=1 # not running but pid exists
fi
else
RC=4 # insufficient privileges
fi
fi
if [ -z "${RC}" ]; then
if [ -f ${lockfile} ]; then
RC=2
else
RC=3
fi
fi
case "${RC}" in
0)
echo "ipsec: pluto (pid ${pid}) is running..."
return 0
;;
1)
echo "ipsec: pluto dead but pid file exits"
return 1
;;
2)
echo "ipsec: pluto dead but subsys locked"
return 2
;;
4)
echo "ipsec: pluto status unknown due to insufficient privileges."
return 4
;;
esac
echo "ipsec: pluto is stopped"
return 3
}
condrestart() {
verify_config
RETVAL=$?
if [ -f ${lockfile} ]; then
restart
RETVAL=$?
fi
return ${RETVAL}
}
version() {
ipsec version
return $?
}
# do it
case "$1" in
start)
start
RETVAL=$?
;;
stop)
stop
RETVAL=$?
;;
restart)
restart
RETVAL=$?
;;
reload|force-reload)
restart
RETVAL=$?
;;
condrestart|try-restart)
condrestart
RETVAL=$?
;;
status)
status
RETVAL=$?
${IPSEC_EXECDIR}/whack --status 2>/dev/null | grep Total | sed 's/^000\ Total\ //'
;;
version)
version
RETVAL=$?
;;
*)
echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status|version}"
RETVAL=2
esac
exit ${RETVAL}

16
docker/l2tp/l2tp.env Normal file
View File

@ -0,0 +1,16 @@
# This file is part of L2TP/IPSec VPN Server Docker image.
# Define your own values for these environment variables.
# DO NOT put "" or '' around values, or add space around =
# DO NOT use these special characters within values: \ " '
VPN_IPSEC_PSK=teddysun.com
VPN_USER=vpnuser
VPN_PASSWORD=vpnpassword
VPN_PUBLIC_IP=
VPN_L2TP_NET=
VPN_L2TP_LOCAL=
VPN_L2TP_REMOTE=
VPN_XAUTH_NET=
VPN_XAUTH_REMOTE=
VPN_DNS1=
VPN_DNS2=

264
docker/l2tp/l2tp.sh Normal file
View File

@ -0,0 +1,264 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#
# This is a Shell script for configure and start L2TP/IPSec VPN server with Docker image
#
# Copyright (C) 2018 Teddysun <i@teddysun.com>
#
# Reference URL:
# https://github.com/libreswan/libreswan
# https://github.com/xelerance/xl2tpd
if [ ! -f "/.dockerenv" ]; then
echo "Error: This script must be run in a Docker container." >&2
exit 1
fi
if ip link add dummy0 type dummy 2>&1 | grep -q "not permitted"; then
echo "Error: This Docker image must be run in privileged mode." >&2
exit 1
fi
ip link delete dummy0 >/dev/null 2>&1
rand(){
index=0
str=""
for i in {a..z}; do arr[index]=${i}; index=$(expr ${index} + 1); done
for i in {A..Z}; do arr[index]=${i}; index=$(expr ${index} + 1); done
for i in {0..9}; do arr[index]=${i}; index=$(expr ${index} + 1); done
for i in {1..10}; do str="$str${arr[$RANDOM%$index]}"; done
echo ${str}
}
is_64bit(){
if [ "$(getconf WORD_BIT)" == "32" ] && [ "$(getconf LONG_BIT)" == "64" ]; then
return 0
else
return 1
fi
}
# Environment file name
l2tp_env_file="/etc/l2tp.env"
# Auto generated
if [ -z "${VPN_IPSEC_PSK}" ] && [ -z "${VPN_USER}" ] && [ -z "${VPN_PASSWORD}" ]; then
if [ -f "${l2tp_env_file}" ]; then
echo "Loading previously generated environment variables for L2TP/IPSec VPN Server..."
. "${l2tp_env_file}"
else
echo "L2TP/IPSec VPN Server environment variables is not set. Use default environment variables..."
VPN_IPSEC_PSK="teddysun.com"
VPN_USER="vpnuser"
VPN_PASSWORD="$(rand)"
echo "VPN_IPSEC_PSK=${VPN_IPSEC_PSK}" > ${l2tp_env_file}
echo "VPN_USER=${VPN_USER}" >> ${l2tp_env_file}
echo "VPN_PASSWORD=${VPN_PASSWORD}" >> ${l2tp_env_file}
chmod 600 ${l2tp_env_file}
fi
fi
# Environment variables:
# VPN_IPSEC_PSK
# VPN_USER
# VPN_PASSWORD
if [ -z "${VPN_IPSEC_PSK}" ] || [ -z "${VPN_USER}" ] || [ -z "${VPN_PASSWORD}" ]; then
echo "Error: Environment variables must be specified. please edit your environment file and retry again." >&2
exit 1
fi
if printf '%s' "${VPN_IPSEC_PSK} ${VPN_USER} ${VPN_PASSWORD}" | LC_ALL=C grep -q '[^ -~]\+'; then
echo "Error: Environment variables must not contain non-ASCII characters." >&2
exit 1
fi
case "${VPN_IPSEC_PSK} ${VPN_USER} ${VPN_PASSWORD}" in
*[\\\"\']*)
echo "Error: Environment variables must not contain these special characters like: \\ \" '"
exit 1
;;
esac
# Environment variables:
# VPN_PUBLIC_IP
PUBLIC_IP=${VPN_PUBLIC_IP:-''}
[ -z "${PUBLIC_IP}" ] && PUBLIC_IP=$( wget -qO- -t1 -T2 ipv4.icanhazip.com )
[ -z "${PUBLIC_IP}" ] && PUBLIC_IP=$( wget -qO- -t1 -T2 ipinfo.io/ip )
# Environment variables:
# VPN_L2TP_NET
# VPN_L2TP_LOCAL
# VPN_L2TP_REMOTE
# VPN_XAUTH_NET
# VPN_XAUTH_REMOTE
# VPN_DNS1
# VPN_DNS2
L2TP_NET=${VPN_L2TP_NET:-'192.168.18.0/24'}
L2TP_LOCAL=${VPN_L2TP_LOCAL:-'192.168.18.1'}
L2TP_REMOTE=${VPN_L2TP_REMOTE:-'192.168.18.10-192.168.18.250'}
XAUTH_NET=${VPN_XAUTH_NET:-'192.168.20.0/24'}
XAUTH_REMOTE=${VPN_XAUTH_REMOTE:-'192.168.20.10-192.168.20.250'}
DNS1=${VPN_DNS1:-'8.8.8.8'}
DNS2=${VPN_DNS2:-'8.8.4.4'}
# Create IPSec config
cat > /etc/ipsec.conf <<EOF
version 2.0
config setup
protostack=netkey
nhelpers=0
uniqueids=no
interfaces=%defaultroute
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!${L2TP_NET},%v4:!${XAUTH_NET}
conn shared
left=%defaultroute
leftid=${PUBLIC_IP}
right=%any
encapsulation=yes
authby=secret
pfs=no
rekey=no
keyingtries=5
dpddelay=30
dpdtimeout=120
dpdaction=clear
ike=3des-sha1,3des-sha2,aes-sha1,aes-sha1;modp1024,aes-sha2,aes-sha2;modp1024
phase2alg=3des-sha1,3des-sha2,aes-sha1,aes-sha2,aes256-sha2_512
sha2-truncbug=yes
conn l2tp-psk
auto=add
leftprotoport=17/1701
rightprotoport=17/%any
type=transport
phase2=esp
also=shared
conn xauth-psk
auto=add
leftsubnet=0.0.0.0/0
rightaddresspool=${XAUTH_REMOTE}
modecfgdns=${DNS1},${DNS2}
leftxauthserver=yes
rightxauthclient=yes
leftmodecfgserver=yes
rightmodecfgclient=yes
modecfgpull=yes
xauthby=file
ike-frag=yes
ikev2=never
cisco-unity=yes
also=shared
EOF
cat > /etc/xl2tpd/xl2tpd.conf <<EOF
[global]
port = 1701
[lns default]
local ip = ${L2TP_LOCAL}
ip range = ${L2TP_REMOTE}
require chap = yes
refuse pap = yes
require authentication = yes
name = l2tpd
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
EOF
cat > /etc/ppp/options.xl2tpd <<EOF
+mschap-v2
ipcp-accept-local
ipcp-accept-remote
ms-dns ${DNS1}
ms-dns ${DNS2}
noccp
auth
mtu 1280
mru 1280
proxyarp
lcp-echo-failure 4
lcp-echo-interval 30
connect-delay 5000
EOF
cat > /etc/ipsec.secrets <<EOF
%any %any : PSK "${VPN_IPSEC_PSK}"
EOF
cat > /etc/ppp/chap-secrets <<EOF
${VPN_USER} l2tpd ${VPN_PASSWORD} *
EOF
VPN_PASSWORD_ENC=$(openssl passwd -1 "${VPN_PASSWORD}")
cat > /etc/ipsec.d/passwd <<EOF
${VPN_USER}:${VPN_PASSWORD_ENC}:xauth-psk
EOF
chmod 600 /etc/ipsec.secrets /etc/ppp/chap-secrets /etc/ipsec.d/passwd
# Update sysctl settings
if is_64bit; then
SHM_MAX=68719476736
SHM_ALL=4294967296
else
SHM_MAX=4294967295
SHM_ALL=268435456
fi
sysctl -eqw kernel.msgmnb=65536
sysctl -eqw kernel.msgmax=65536
sysctl -eqw kernel.shmmax=${SHM_MAX}
sysctl -eqw kernel.shmall=${SHM_ALL}
sysctl -eqw net.ipv4.ip_forward=1
sysctl -eqw net.ipv4.conf.all.accept_source_route=0
sysctl -eqw net.ipv4.conf.all.accept_redirects=0
sysctl -eqw net.ipv4.conf.all.send_redirects=0
sysctl -eqw net.ipv4.conf.all.rp_filter=0
sysctl -eqw net.ipv4.conf.default.accept_source_route=0
sysctl -eqw net.ipv4.conf.default.accept_redirects=0
sysctl -eqw net.ipv4.conf.default.send_redirects=0
sysctl -eqw net.ipv4.conf.default.rp_filter=0
sysctl -eqw net.ipv4.conf.eth0.send_redirects=0
sysctl -eqw net.ipv4.conf.eth0.rp_filter=0
# Create iptables rules
iptables -I INPUT 1 -p udp --dport 1701 -m policy --dir in --pol none -j DROP
iptables -I INPUT 2 -m conntrack --ctstate INVALID -j DROP
iptables -I INPUT 3 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT 4 -p udp -m multiport --dports 500,4500 -j ACCEPT
iptables -I INPUT 5 -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
iptables -I INPUT 6 -p udp --dport 1701 -j DROP
iptables -I FORWARD 1 -m conntrack --ctstate INVALID -j DROP
iptables -I FORWARD 2 -i eth+ -o ppp+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 3 -i ppp+ -o eth+ -j ACCEPT
iptables -I FORWARD 4 -i ppp+ -o ppp+ -s "${L2TP_NET}" -d "${L2TP_NET}" -j ACCEPT
iptables -I FORWARD 5 -i eth+ -d "${XAUTH_NET}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD 6 -s "${XAUTH_NET}" -o eth+ -j ACCEPT
iptables -A FORWARD -j DROP
iptables -t nat -I POSTROUTING -s "${XAUTH_NET}" -o eth+ -m policy --dir out --pol none -j MASQUERADE
iptables -t nat -I POSTROUTING -s "${L2TP_NET}" -o eth+ -j MASQUERADE
cat <<EOF
L2TP/IPsec VPN Server with the Username and Password is below:
Server IP: ${PUBLIC_IP}
IPSec PSK: ${VPN_IPSEC_PSK}
Username : ${VPN_USER}
Password : ${VPN_PASSWORD}
EOF
# Load IPsec kernel module
modprobe af_key
# Start services
mkdir -p /run/pluto /var/run/pluto /var/run/xl2tpd
rm -f /run/pluto/pluto.pid /var/run/pluto/pluto.pid /var/run/xl2tpd.pid
/usr/sbin/ipsec start
exec /usr/sbin/xl2tpd -D -c /etc/xl2tpd/xl2tpd.conf

131
docker/l2tp/l2tpctl.sh Normal file
View File

@ -0,0 +1,131 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#
# This is a Shell script for configure and start L2TP/IPSec VPN server with Docker image
#
# Copyright (C) 2018 Teddysun <i@teddysun.com>
#
# Reference URL:
# https://github.com/libreswan/libreswan
# https://github.com/xelerance/xl2tpd
rand(){
index=0
str=""
for i in {a..z}; do arr[index]=${i}; index=$(expr ${index} + 1); done
for i in {A..Z}; do arr[index]=${i}; index=$(expr ${index} + 1); done
for i in {0..9}; do arr[index]=${i}; index=$(expr ${index} + 1); done
for i in {1..10}; do str="$str${arr[$RANDOM%$index]}"; done
echo ${str}
}
list_users(){
if [ ! -f /etc/ppp/chap-secrets ];then
echo "Error: /etc/ppp/chap-secrets file not found."
exit 1
fi
local line="+-------------------------------------------+\n"
local string=%20s
printf "${line}|${string} |${string} |\n${line}" Username Password
grep -v "^#" /etc/ppp/chap-secrets | awk '{printf "|'${string}' |'${string}' |\n", $1,$3}'
printf ${line}
}
add_user(){
while :
do
read -p "Please enter Username:" user
if [ -z ${user} ]; then
echo "Username can not be empty"
else
grep -w "${user}" /etc/ppp/chap-secrets > /dev/null 2>&1
if [ $? -eq 0 ];then
echo "Username (${user}) already exists. Please re-enter your username."
else
break
fi
fi
done
pass="$(rand)"
echo "Please enter ${user}'s password:"
read -p "(Default Password: ${pass}):" tmppass
[ ! -z ${tmppass} ] && pass=${tmppass}
pass_enc=$(openssl passwd -1 "${pass}")
echo "${user} l2tpd ${pass} *" >> /etc/ppp/chap-secrets
echo "${user}:${pass_enc}:xauth-psk" >> /etc/ipsec.d/passwd
echo "Username (${user}) add completed."
}
del_user(){
while :
do
read -p "Please enter Username you want to delete it:" user
if [ -z ${user} ]; then
echo "Username can not be empty"
else
grep -w "${user}" /etc/ppp/chap-secrets >/dev/null 2>&1
if [ $? -eq 0 ];then
break
else
echo "Username (${user}) is not exists. Please re-enter your username."
fi
fi
done
sed -i "/^\<${user}\>/d" /etc/ppp/chap-secrets
sed -i "/^\<${user}\>/d" /etc/ipsec.d/passwd
echo "Username (${user}) delete completed."
}
mod_user(){
while :
do
read -p "Please enter Username you want to change password:" user
if [ -z ${user} ]; then
echo "Username can not be empty"
else
grep -w "${user}" /etc/ppp/chap-secrets >/dev/null 2>&1
if [ $? -eq 0 ];then
break
else
echo "Username (${user}) is not exists. Please re-enter your username."
fi
fi
done
pass="$(rand)"
echo "Please enter ${user}'s new password:"
read -p "(Default Password: ${pass}):" tmppass
[ ! -z ${tmppass} ] && pass=${tmppass}
pass_enc=$(openssl passwd -1 "${pass}")
sed -i "/^\<${user}\>/d" /etc/ppp/chap-secrets
sed -i "/^\<${user}\>/d" /etc/ipsec.d/passwd
echo "${user} l2tpd ${pass} *" >> /etc/ppp/chap-secrets
echo "${user}:${pass_enc}:xauth-psk" >> /etc/ipsec.d/passwd
echo "Username ${user}'s password has been changed."
}
action=$1
case ${action} in
-l|--list)
list_users
;;
-a|--add)
add_user
;;
-d|--del)
del_user
;;
-m|--mod)
mod_user
;;
-h|--help)
echo "Usage: `basename $0` -l,--list List all users"
echo " `basename $0` -a,--add Add a user"
echo " `basename $0` -d,--del Delete a user"
echo " `basename $0` -m,--mod Modify a user password"
echo " `basename $0` -h,--help Print this help information"
;;
*)
echo "Usage: `basename $0` [-l,--list|-a,--add|-d,--del|-m,--mod|-h,--help]" && exit
;;
esac