mirror of
				https://github.com/teddysun/across.git
				synced 2025-10-31 16:55:33 +08:00 
			
		
		
		
	Added L2TP/IPSec VPN Server Docker Image
Signed-off-by: Teddysun <i@teddysun.com>
This commit is contained in:
		
							
								
								
									
										3
									
								
								docker/l2tp/.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docker/l2tp/.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | .dockerignore | ||||||
|  | README.md | ||||||
|  | l2tp.env | ||||||
							
								
								
									
										25
									
								
								docker/l2tp/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								docker/l2tp/Dockerfile
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										128
									
								
								docker/l2tp/README.md
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										304
									
								
								docker/l2tp/ipsec
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										16
									
								
								docker/l2tp/l2tp.env
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										264
									
								
								docker/l2tp/l2tp.sh
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										131
									
								
								docker/l2tp/l2tpctl.sh
									
									
									
									
									
										Normal 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 | ||||||
		Reference in New Issue
	
	Block a user