container-openvpn/bin/ovpn_genconfig

201 lines
4.6 KiB
Plaintext
Raw Normal View History

#!/bin/bash
#
# Generate OpenVPN configs
#
# Convert 1.2.3.4/24 -> 255.255.255.0
cidr2mask()
{
local i
local subnetmask=""
local cidr=${1#*/}
local full_octets=$(($cidr/8))
local partial_octet=$(($cidr%8))
for ((i=0;i<4;i+=1)); do
if [ $i -lt $full_octets ]; then
subnetmask+=255
elif [ $i -eq $full_octets ]; then
subnetmask+=$((256 - 2**(8-$partial_octet)))
else
subnetmask+=0
fi
[ $i -lt 3 ] && subnetmask+=.
done
echo $subnetmask
}
# Used often enough to justify a function
getroute() {
echo ${1%/*} $(cidr2mask $1)
}
usage() {
echo "usage: $0 [-d]"
echo " -u SERVER_PUBLIC_URL"
echo " [-s SERVER_SUBNET]"
echo " [-r ROUTE ...]"
echo " [-p PUSH ...]"
echo
echo "optional arguments:"
echo " -d Disable NAT routing and default route"
echo " -c Enable client-to-client option"
2015-01-17 08:56:21 +00:00
echo " -D Disable built in external dns (google dns)"
2015-01-17 08:56:46 +00:00
echo " -N Configure NAT to access external server network"
2015-01-17 09:07:52 +00:00
echo " -m Set client MTU"
}
if [ "$DEBUG" == "1" ]; then
set -x
fi
set -e
OVPN_ENV=$OPENVPN/ovpn_env.sh
OVPN_SERVER=192.168.255.0/24
OVPN_DEFROUTE=1
2015-01-17 08:56:46 +00:00
OVPN_NAT=0
2015-01-17 08:56:21 +00:00
OVPN_DNS=1
OVPN_ROUTES=()
TMP_ROUTES=()
OVPN_PUSH=()
TMP_PUSH=()
# Import defaults if present
[ -r "$OVPN_ENV" ] && source "$OVPN_ENV"
# Parse arguments
2015-01-17 09:07:52 +00:00
while getopts ":r:s:du:cp:DNm:" opt; do
case $opt in
r)
TMP_ROUTES+=("$OPTARG")
;;
s)
OVPN_SERVER=$OPTARG
;;
d)
OVPN_DEFROUTE=0
;;
u)
OVPN_SERVER_URL=$OPTARG
;;
c)
OVPN_CLIENT_TO_CLIENT=1
;;
p)
TMP_PUSH+=("$OPTARG")
;;
2015-01-17 08:56:21 +00:00
D)
OVPN_DNS=0
;;
2015-01-17 08:56:46 +00:00
N)
OVPN_NAT=1
;;
2015-01-17 09:07:52 +00:00
m)
OVPN_MTU=$OPTARG
;;
\?)
set +x
echo "Invalid option: -$OPTARG" >&2
usage
exit 1
;;
:)
set +x
echo "Option -$OPTARG requires an argument." >&2
usage
exit 1
;;
esac
done
# if new routes were not defined with -r, use default
[ ${#TMP_ROUTES[@]} -gt 0 ] && OVPN_ROUTES=${TMP_ROUTES[@]}
# if new push directives were not defined with -p, use default
[ ${#TMP_PUSH[@]} -gt 0 ] && OVPN_PUSH=${TMP_PUSH[@]}
# Server name is in the form "udp://vpn.example.com:1194"
if [[ "$OVPN_SERVER_URL" =~ ^((udp|tcp)://)?([0-9a-zA-Z\.\-]+)(:([0-9]+))?$ ]]; then
OVPN_PROTO=${BASH_REMATCH[2]};
OVPN_CN=${BASH_REMATCH[3]};
OVPN_PORT=${BASH_REMATCH[5]};
else
set +x
echo "Common name not specified, see '-u'"
usage
exit 1
fi
# Apply defaults
[ -z "$OVPN_PROTO" ] && OVPN_PROTO=udp
[ -z "$OVPN_PORT" ] && OVPN_PORT=1194
[ ${#OVPN_ROUTES[@]} -eq 0 ] && OVPN_ROUTES=("192.168.254.0/24")
export OVPN_SERVER OVPN_ROUTES OVPN_DEFROUTE
export OVPN_SERVER_URL OVPN_ENV OVPN_PROTO OVPN_CN OVPN_PORT
2015-01-17 09:07:52 +00:00
export OVPN_CLIENT_TO_CLIENT OVPN_PUSH OVPN_NAT OVPN_DNS OVPN_MTU
# Preserve config
if [ -f "$OVPN_ENV" ]; then
bak_env=$OVPN_ENV.$(date +%s).bak
echo "Backing up $OVPN_ENV -> $bak_env"
mv "$OVPN_ENV" "$bak_env"
fi
export | grep OVPN_ > "$OVPN_ENV"
conf=$OPENVPN/openvpn.conf
if [ -f "$conf" ]; then
bak=$conf.$(date +%s).bak
echo "Backing up $conf -> $bak"
mv "$conf" "$bak"
fi
cat > "$conf" <<EOF
server $(getroute $OVPN_SERVER)
verb 3
#duplicate-cn
key $EASYRSA_PKI/private/${OVPN_CN}.key
ca $EASYRSA_PKI/ca.crt
cert $EASYRSA_PKI/issued/${OVPN_CN}.crt
dh $EASYRSA_PKI/dh.pem
tls-auth $EASYRSA_PKI/ta.key
key-direction 0
keepalive 10 60
persist-key
persist-tun
proto $OVPN_PROTO
# Rely on Docker to do port mapping, internally always 1194
port 1194
dev tun0
status /tmp/openvpn-status.log
client-config-dir $OPENVPN/ccd
2014-12-31 20:57:22 +00:00
user nobody
group nogroup
EOF
[ -n "$OVPN_CLIENT_TO_CLIENT" ] && echo "client-to-client" >> "$conf"
2015-01-17 08:56:21 +00:00
[ "$OVPN_DNS" == "1" ] && echo push "dhcp-option DNS 8.8.4.4" >> "$conf"
[ "$OVPN_DNS" == "1" ] && echo push "dhcp-option DNS 8.8.8.8" >> "$conf"
# Append Routes
for i in "${OVPN_ROUTES[@]}"; do
# If user passed "0" skip this, assume no extra routes
[ "$i" = "0" ] && break;
echo route $(getroute "$i") >> "$conf"
done
# Append push commands
for i in "${OVPN_PUSH[@]}"; do
echo push \"$i\" >> "$conf"
done
# Clean-up duplicate configs (always return success)
diff -q "$bak_env" "$OVPN_ENV" 2> /dev/null && rm "$bak_env" || true
diff -q "$bak" "$conf" 2> /dev/null && rm "$bak" || true
echo "Successfully generated config"