Projekte & Automatisierung

Howto OpenVPN

auf einem OpenWRT Router

Die OpenVPN Scripte stammen aus dem openwrt.org und wurden so angepasst, dass diese Scripte nahezu automatisch durch laufen, lediglich der Name des Servers muss im Server-Script eingegeben werden. Im Client-Script wird dagegen der Name des Clients und die VPN IP / DNS benötigt.

Script für den OpenVPN Server

#!/bin/sh
opkg update
opkg install nano openvpn-easy-rsa openvpn-openssl
# Configure firewall
uci rename firewall.@zone[0]="lan"
uci rename firewall.@zone[1]="wan"
uci rename firewall.@forwarding[0]="lan_wan"
uci del_list firewall.lan.device="tun0"
uci add_list firewall.lan.device="tun0"
uci -q delete firewall.vpn
uci set firewall.ovpn="rule"
uci set firewall.ovpn.name="Allow-OpenVPN"
uci set firewall.ovpn.src="wan"
uci set firewall.ovpn.dest_port="1194"
uci set firewall.ovpn.proto="udp"
uci set firewall.ovpn.target="ACCEPT"
uci commit firewall
/etc/init.d/firewall restart
# setup server
clear
echo -n "Name des Servers eingeben : "
read name
clear
# Configuration parameters
export EASYRSA_PKI="/etc/easy-rsa/pki"
export EASYRSA_REQ_CN="${name}"
#Server ca expire
export EASYRSA_CA_EXPIRE="7500"
#Server Certificate expire
export EASYRSA_CERT_EXPIRE="3650"
#Diffie-Hellman
export EASYRSA_KEY_SIZE="2048"

# Remove and re-initialize the PKI directory
easyrsa --batch init-pki

# Generate DH parameters
easyrsa --batch gen-dh
 
# Create a new CA
easyrsa --batch build-ca nopass

touch ${EASYRSA_PKI}/crl.pem
chmod 0644 ${EASYRSA_PKI}/crl.pem

easyrsa --batch gen-req $name nopass
easyrsa --batch sign-req server $name
openssl verify -CAfile ${EASYRSA_PKI}/ca.crt ${EASYRSA_PKI}/issued/$name.crt
 
# Generate TLS PSK
OVPN_PKI="/etc/easy-rsa/pki"
openvpn --genkey --secret ${OVPN_PKI}/tc.pem

# Configuration parameters
OVPN_ID=$name
OVPN_CRL="$(cat ${EASYRSA_PKI}/crl.pem)"
OVPN_DIR="/etc/openvpn"
OVPN_PKI="/etc/easy-rsa/pki"
OVPN_DEV="$(uci get firewall.lan.device | sed -e "s/^.*\s//")"
OVPN_PORT="$(uci get firewall.ovpn.dest_port)"
OVPN_PROTO="$(uci get firewall.ovpn.proto)"
OVPN_POOL="10.10.8.0 255.255.255.0"
OVPN_DNS="${OVPN_POOL%.* *}.1"
OVPN_DOMAIN="$(uci get dhcp.@dnsmasq[0].domain)"
OVPN_DH="$(cat ${OVPN_PKI}/dh.pem)"
OVPN_TC="$(sed -e "/^#/d;/^\w/N;s/\n//" ${OVPN_PKI}/tc.pem)"
OVPN_CA="$(openssl x509 -in ${OVPN_PKI}/ca.crt)"
NL=$'\n'
OVPN_FP="$(openssl x509 -noout -fingerprint -sha256 -inform pem -in ${EASYRSA_PKI}/ca.crt | cut -d'=' -f 2)"

# Configure VPN server
umask u=rw,g=,o=
grep -l -r -e "TLS Web Server Auth" "${OVPN_PKI}/issued" \
| sed -e "s/^.*\///;s/\.\w*$//" \
| while read -r OVPN_ID
do
OVPN_CERT="$(openssl x509 -in ${OVPN_PKI}/issued/${OVPN_ID}.crt)"
OVPN_KEY="$(cat ${OVPN_PKI}/private/${OVPN_ID}.key)"
rm ${OVPN_DIR}/*.conf
rm ${OVPN_DIR}/*.ovpn
cat << EOF > ${OVPN_DIR}/${OVPN_ID}.conf
verb 3
user nobody
group nogroup
dev ${OVPN_DEV}
port ${OVPN_PORT}
proto ${OVPN_PROTO}4
server ${OVPN_POOL}
topology subnet
client-to-client
keepalive 10 120
persist-tun
persist-key

ifconfig-pool-persist ipp.txt 600
remote-cert-tls client
verify-hash ${OVPN_FP} SHA256
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RS>
ncp-ciphers AES-256-GCM:AES-256-CBC:AES-128-GCM:AES-128-CBC
cipher AES-128-GCM
auth SHA1
mute-replay-warnings
script-security 1
explicit-exit-notify 1
tun-mtu 1500

push "dhcp-option DNS ${OVPN_DNS}"
push "dhcp-option DOMAIN ${OVPN_DOMAIN}"
push "redirect-gateway def1"
push "persist-tun"
push "persist-key"
<dh>${NL}${OVPN_DH}${NL}</dh>
<tls-crypt>${NL}${OVPN_TC}${NL}</tls-crypt>
<ca>${NL}${OVPN_CA}${NL}</ca>
<cert>${NL}${OVPN_CERT}${NL}</cert>
<key>${NL}${OVPN_KEY}${NL}</key>
EOF
done
/etc/init.d/openvpn restart

# Provide VPN instance management
ls ${OVPN_DIR}/*.conf \
| while read -r OVPN_CONF
do
OVPN_ID="$(basename ${OVPN_CONF%.*} | sed -e "s/\W/_/g")"
uci -q delete openvpn.${OVPN_ID}
uci set openvpn.${OVPN_ID}="openvpn"
uci set openvpn.${OVPN_ID}.enabled="1"
uci set openvpn.${OVPN_ID}.config="${OVPN_CONF}"
done
uci commit openvpn
/etc/init.d/openvpn restart

Script für den OpenVPN Client

#!/bin/sh
clear
echo -n "Name des Clients eingeben : "
read name
clear
echo -n "VPN IP / DNS : "
read ip
clear
# Configuration parameters
export EASYRSA_PKI="/etc/easy-rsa/pki"
# get the servername
OVPN_SUBJECT="$(basename /etc/openvpn/*.conf .conf)"
export EASYRSA_REQ_CN="${name}"
# easyrsa --batch build-client-full $name nopass
easyrsa --batch gen-req $name nopass
easyrsa --batch sign-req client $name
openssl verify -CAfile ${EASYRSA_PKI}/ca.crt ${EASYRSA_PKI}/issued/$name.crt
# Fetch IP address
. /lib/functions/network.sh
network_flush_cache
network_find_wan NET_IF
network_get_ipaddr OVPN_SERV "${NET_IF}"
 
# Fetch FQDN from DDNS client
OVPN_FQDN="$(uci -q get "$(uci -q show ddns \
| sed -n -e "/\.enabled='1'$/s//.lookup_host/p" \
| sed -n -e "1p")")"
if [ -n "${OVPN_FQDN}" ]
then
OVPN_SERV="${OVPN_FQDN}"
fi
 
# Configuration parameters
OVPN_ID=$name
OVPN_IP=$ip
OVPN_DIR="/etc/openvpn"
OVPN_PKI="/etc/easy-rsa/pki"
OVPN_DEV="$(uci get firewall.lan.device | sed -e "s/^.*\s//")"
OVPN_PORT="$(uci get firewall.ovpn.dest_port)"
OVPN_PROTO="$(uci get firewall.ovpn.proto)"
OVPN_TC="$(sed -e "/^#/d;/^\w/N;s/\n//" ${OVPN_PKI}/tc.pem)"
OVPN_CA="$(openssl x509 -in ${OVPN_PKI}/ca.crt)"
NL=$'\n'
OVPN_FP="$(openssl x509 -noout -fingerprint -sha256 -inform pem -in ${EASYRSA_PKI}/ca.crt | cut -d'=' -f 2)"
#OVPN_SUBJECT="$(openssl x509 -in ${EASYRSA_PKI}/issued/${name}.crt -text -noout | grep Subject: | cut -d'=' -f 2)"

# Generate VPN client profiles
umask u=rw,g=,o=
grep -l -r -e "TLS Web Client Auth" "${OVPN_PKI}/issued" \
| sed -e "s/^.*\///;s/\.\w*$//" \
| while read -r OVPN_ID
do
OVPN_CERT="$(openssl x509 -in ${OVPN_PKI}/issued/${OVPN_ID}.crt)"
OVPN_KEY="$(cat ${OVPN_PKI}/private/${OVPN_ID}.key)"
cat << EOF > ${OVPN_DIR}/${OVPN_ID}.ovpn
verb 3
dev ${OVPN_DEV%%[0-9]*}
nobind
client
remote ${OVPN_IP} ${OVPN_PORT} ${OVPN_PROTO}4
auth-nocache
remote-cert-tls server

persist-tun
persist-key
resolv-retry infinite
connect-retry 60 600
verify-hash ${OVPN_FP} SHA256
verify-x509-name ${OVPN_SUBJECT} name
cipher AES-128-GCM
auth SHA1
key-direction 1
tun-mtu 1500

<tls-crypt>${NL}${OVPN_TC}${NL}</tls-crypt>
<ca>${NL}${OVPN_CA}${NL}</ca>
<cert>${NL}${OVPN_CERT}${NL}</cert>
<key>${NL}${OVPN_KEY}${NL}</key>
EOF
done
ls ${OVPN_DIR}/*.ovpn

Falls eine Domain vorhanden sein sollte, kann mit Hilfe eines Scripts, die IP-Adresse die dem Router zugewiesen wurde, an die DynDNS weitergegeben werden. Die nötigen Einstellungen beim Provider sind unterschiedliche. Daher sollte sich vorab informiert werden, wie die Einstellungen vorgenommen werden müssen, um der DNS eine IP-Adresse zuzuweisen. Hier ein Script, welches den Abgleich der IP-Adresse vornimmt.

DynDNS Script

#!/bin/sh
IPHOME=`curl ipinfo.io/ip`
IPDATEI='ipold.txt'
IPOLD=$(cat $IPDATEI);
if [ "$IPOLD" != "$IPHOME" ] ; then
    # Muss an den Server angepasst werden, in diesem Beispiel ist es Serverprofis.
    IPNOW=$(/usr/bin/curl CONTROL_PANNEL'?'hostname=DynDNS_Adresse'&'cUser=USERNAME'&'cPass='PASSWORD')
    echo $IPHOME > $IPDATEI
    echo "Update"
    echo "###########"
    echo $IPNOW
    echo $IPHOME
    echo "###########"
else
    echo "No Update"
fi

Neustart des WAN-Interface bei fehlender Internetverbindung

Falls das WAN-Interface ein Problem haben sollte, sei es ein IP Problem oder es hat sich aufgehangen, wird es automatisch neugestartet, solange bis eine Internetverbindung aufgebaut wurde.

#!/bin/sh
ping -c1 www.google.de > /dev/null
if [ $? -eq 0 ]
  then
    echo ok
    exit 0
else
  ifdown wwan
  sleep 5
  ifup wwan
fi