Skip to content

Instantly share code, notes, and snippets.

@vbuaraujo
Created August 23, 2018 18:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vbuaraujo/073ccd3d8a15bf393552e1a4830b87ce to your computer and use it in GitHub Desktop.
Save vbuaraujo/073ccd3d8a15bf393552e1a4830b87ce to your computer and use it in GitHub Desktop.
#!/bin/bash
# vpnsetup.sh - Set up a L2TP VPN on Debian/Ubuntu systems.
# Written by Vítor De Araújo <https://elmord.org/>.
# Version 1.2, 2018-08-23.
# Location where the VPN control script will be installed.
VPNCTL_SCRIPT=/usr/local/bin/vpn
# Am I bash?
[[ 1 ]] 2>/dev/null || {
echo "ERROR: I need to run with 'bash', not 'sh'."
exit 1
}
yes_or_no() {
local prompt="$1" reply
while :; do
read -n 1 -p "$prompt [y/n] " reply
echo ""
case "$reply" in
[yY]) return 0 ;;
[nN]) return 1 ;;
*) echo "Please answer 'y' or 'n'!" ;;
esac
done
}
prompt() {
local prompt="$1" var="$2"
while :; do
read -p "$prompt" "$var"
if [[ -z "${!var}" ]]; then
echo "Please type an answer!"
else
return 0
fi
done
}
# Am I root?
if [[ $UID -ne 0 ]]; then
echo "ERROR: I need to run as root."
exit 1
fi
# Ask configs from user.
echo "WARNING: This script will overwrite your IPSec and xl2tpd files."
echo "If you have other VPNs configured, they will be lost!"
yes_or_no "Continue?" || exit
prompt "Enter the remote IP address: " REMOTE_IP
prompt "Enter the VPN secret key: " PSK
prompt "Enter your username: " USERNAME
prompt "Enter your password: " PASSWORD
echo ""
echo "I need to know your local IP address."
# Try to discover local IP address.
LOCAL_IP=
local_ips="$(
ip addr |
sed -n 's/^ *inet \([^/]*\).*/\1/p' |
grep -vF '127.0.0.1'
)"
local_ips_count="$(wc -l <<<"$local_ips")"
if (( local_ips_count == 1 )) &&
yes_or_no "Is your local IP address $local_ips?"
then
LOCAL_IP="$local_ips"
else
if (( local_ips_count > 1 )); then
echo "Hint: it's probably one of these:"
echo "$local_ips"
fi
prompt "Enter your local IP address: " LOCAL_IP
fi
echo ""
# Install things.
echo "Running 'apt-get update' before installing packages can help"
echo "avoid some installation errors."
if yes_or_no "Do you want to run it?"; then
apt-get update
fi
echo "Installing xl2tpd..."
apt-get install xl2tpd
if yes_or_no "Download and compile Openswan?"; then
echo "Downloading dependencies..."
apt-get install --no-install-recommends \
gcc make libc6-dev libgmp3-dev flex bison || {
yes_or_no "Errors while installing dependencies. Continue?" ||
exit 1
}
mkdir /tmp/openswan
cd /tmp/openswan
wget https://download.openswan.org/openswan/openswan-latest.tar.gz \
-O pkg-openswan-latest.tar.gz
tar -xvf pkg-openswan-latest.tar.gz
cd openswan-*
make programs
make install
make install programs
fi
# Create config files.
cat <<EOF >/etc/ipsec.conf
version 2.0 # conforms to second version of ipsec.conf specification
config setup
dumpdir=/var/run/pluto/
nat_traversal=yes
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,%v6:fd00::/8,%v6:fe80::/10
oe=off
protostack=auto
conn L2TP-PSK-CLIENT
authby=secret
pfs=no
rekey=yes
keyingtries=3
type=transport
left=$LOCAL_IP
leftprotoport=17/1701
right=$REMOTE_IP
rightprotoport=17/1701
auto=add
EOF
cat <<EOF >/etc/ipsec.secrets
$LOCAL_IP $REMOTE_IP : PSK "$PSK"
EOF
cat <<EOF >/etc/xl2tpd/xl2tpd.conf
[lac L2TPserver]
lns = $REMOTE_IP
; require chap = yes
; refuse pap = yes
; require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd.client
length bit = yes
EOF
cat <<EOF >/etc/ppp/options.l2tpd.client
ipcp-accept-local
ipcp-accept-remote
refuse-eap
require-mschap-v2
noccp
noauth
idle 1800
mtu 1410
mru 1410
#defaultroute
#usepeerdns
debug
connect-delay 5000
name "$USERNAME"
password "$PASSWORD"
EOF
# This seems to be necessary on Ubuntu, though not Debian.
NETFILTER_MODULES_FILE="/etc/modules-load.d/vpn-netfilter.conf"
cat <<EOF >"$NETFILTER_MODULES_FILE"
nf_nat_pptp
nf_conntrack_pptp
nf_conntrack_proto_gre
EOF
echo "Loading netfilter modules..."
while read module; do
modprobe "$module"
done <"$NETFILTER_MODULES_FILE"
# Create the vpn script.
cat <<'EOF' >"$VPNCTL_SCRIPT"
#!/bin/bash
usage() {
echo "Usage: ${0##*/} up|down" >&2
}
restart_services() {
echo "Stopping xl2tpd..."
service xl2tpd stop
sleep 5
echo "Restarting ipsec..."
/etc/init.d/ipsec restart || service ipsec restart
sleep 2
echo "Starting xl2tpd..."
service xl2tpd start
sleep 5
}
vpn_up() {
restart_services
echo "Bringing up IPsec client connection..."
ipsec auto --up L2TP-PSK-CLIENT
sleep 2
echo "Bringing up xl2tpd connection..."
start_tail_syslog
echo "c L2TPserver" >/var/run/xl2tpd/l2tp-control
sleep 15
stop_tail_syslog
echo "Adding route to remote network..."
#route add -net 10.98.0.0/24 dev ppp0
ip route add 10.98.0.0/24 dev ppp0
echo "Done!"
}
vpn_down() {
echo "Bringing down xl2tpd connection..."
start_tail_syslog
echo "d L2TPserver" >/var/run/xl2tpd/l2tp-control
sleep 10
stop_tail_syslog
echo "Bringing down IPsec client connection..."
ipsec auto --down L2TP-PSK-CLIENT
echo "Done!"
}
start_tail_syslog() {
tail -f /var/log/syslog &
tail_pid="$!"
disown # Avoid annoying 'Terminated' message at the end.
trap "kill $tail_pid; exit" EXIT INT
}
stop_tail_syslog() {
kill "$tail_pid"
trap - EXIT INT
}
[[ $# -eq 1 ]] || { usage; exit 1; }
case "$1" in
up) vpn_up ;;
down) vpn_down ;;
*) usage; exit 1 ;;
esac
EOF
chmod 755 "$VPNCTL_SCRIPT"
echo ""
echo "Script $VPNCTL_SCRIPT created."
echo "You can now run '${VPNCTL_SCRIPT##*/} up' to bring up the VPN."
echo ""
if yes_or_no "Do you want to start the VPN now?"; then
echo "Running '${VPNCTL_SCRIPT##*/} up'..."
"$VPNCTL_SCRIPT" up
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment