#!/bin/bash # Secure OpenVPN server installer for Debian, Ubuntu, CentOS, Fedora and Arch Linux # https://github.com/angristan/openvpn-install isRoot () { if [ "$EUID" -ne 0 ]; then return 1 fi } tunAvailable () { if [ ! -e /dev/net/tun ]; then return 1 fi } initialCheck () { if ! isRoot; then echo "Sorry, you need to run this as root" exit 1 fi if ! tunAvailable; then echo "TUN is not available" exit 1 fi } installQuestions () { if [ -z "$IPV6_SUPPORT" ]; then IPV6_SUPPORT=n fi if [ -z "$PORT" ]; then PORT=1194 fi if [ -z "$PROTOCOL" ]; then PROTOCOL=udp fi if [ -z "$DNS1" ]; then DNS1='1.1.1.1' fi CIPHER="AES-128-GCM" CERT_CURVE="prime256v1" CC_CIPHER="TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256" DH_CURVE="prime256v1" HMAC_ALG="SHA256" } initializeOpenVPN () { # Run setup questions first installQuestions # Get the "public" interface from the default route NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1) # Find out if the machine uses nogroup or nobody for the permissionless group if grep -qs "^nogroup:" /etc/group; then NOGROUP=nogroup else NOGROUP=nobody fi # An old version of easy-rsa was available by default in some openvpn packages if [[ -d /etc/openvpn/easy-rsa/ ]]; then rm -rf /etc/openvpn/easy-rsa/ fi # Install the latest version of easy-rsa from source local version="3.0.6" wget -O ~/EasyRSA-unix-v${version}.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v${version}/EasyRSA-unix-v${version}.tgz tar xzf ~/EasyRSA-unix-v${version}.tgz -C ~/ mv ~/EasyRSA-v${version}/ /etc/openvpn/ mv /etc/openvpn/EasyRSA-v${version}/ /etc/openvpn/easy-rsa/ chown -R root:root /etc/openvpn/easy-rsa/ rm -f ~/EasyRSA-unix-v${version}.tgz cd /etc/openvpn/easy-rsa/ echo "set_var EASYRSA_ALGO ec" > vars echo "set_var EASYRSA_CURVE $CERT_CURVE" >> vars # Generate a random, alphanumeric identifier of 16 characters for CN and one for server name SERVER_CN="cn_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)" SERVER_NAME="server_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)" echo "set_var EASYRSA_REQ_CN $SERVER_CN" >> vars # Create the PKI, set up the CA, the DH params and the server certificate ./easyrsa init-pki ./easyrsa --batch build-ca nopass ./easyrsa build-server-full "$SERVER_NAME" nopass EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl openvpn --genkey --secret /etc/openvpn/tls-crypt.key # Move all the generated files cp pki/ca.crt pki/private/ca.key "pki/issued/$SERVER_NAME.crt" "pki/private/$SERVER_NAME.key" /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn # Generate server.conf echo "port $PORT" > /etc/openvpn/server.conf if [[ "$IPV6_SUPPORT" = 'n' ]]; then echo "proto $PROTOCOL" >> /etc/openvpn/server.conf elif [[ "$IPV6_SUPPORT" = 'y' ]]; then echo "proto ${PROTOCOL}6" >> /etc/openvpn/server.conf fi echo "dev tun user nobody group $NOGROUP persist-key persist-tun keepalive 10 120 topology subnet server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt" >> /etc/openvpn/server.conf # DNS resolvers echo 'push "dhcp-option DNS '${DNS1}'"' >> /etc/openvpn/server.conf if [[ "$DNS_ONLY" = 'y' ]]; then echo '#push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server.conf else echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server.conf fi # IPv6 network settings if needed if [[ "$IPV6_SUPPORT" = 'y' ]]; then echo 'server-ipv6 fd42:42:42:42::/112 tun-ipv6 push tun-ipv6 push "route-ipv6 2000::/3" push "redirect-gateway ipv6"' >> /etc/openvpn/server.conf fi echo "dh none" >> /etc/openvpn/server.conf echo "ecdh-curve $DH_CURVE" >> /etc/openvpn/server.conf echo "tls-crypt tls-crypt.key 0" >> /etc/openvpn/server.conf echo "crl-verify crl.pem ca ca.crt cert $SERVER_NAME.crt key $SERVER_NAME.key auth $HMAC_ALG cipher $CIPHER ncp-ciphers $CIPHER tls-server tls-version-min 1.2 tls-cipher $CC_CIPHER status /var/log/openvpn/status.log verb 3" >> /etc/openvpn/server.conf # Enable routing echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/20-openvpn.conf if [[ "$IPV6_SUPPORT" = 'y' ]]; then echo 'net.ipv6.conf.all.forwarding=1' >> /etc/sysctl.d/20-openvpn.conf fi # Avoid an unneeded reboot sysctl --system # If SELinux is enabled and a custom port was selected, we need this if hash sestatus 2>/dev/null; then if sestatus | grep "Current mode" | grep -qs "enforcing"; then if [[ "$PORT" != '1194' ]]; then semanage port -a -t openvpn_port_t -p "$PROTOCOL" "$PORT" fi fi fi IP=$PUBLICIP # client-template.txt is created so we have a template to add further users later echo "client" > /etc/openvpn/client-template.txt if [[ "$PROTOCOL" = 'udp' ]]; then echo "proto udp" >> /etc/openvpn/client-template.txt elif [[ "$PROTOCOL" = 'tcp' ]]; then echo "proto tcp-client" >> /etc/openvpn/client-template.txt fi echo "remote $IP $PORT dev tun resolv-retry infinite nobind persist-key persist-tun remote-cert-tls server verify-x509-name $SERVER_NAME name auth $HMAC_ALG auth-nocache cipher $CIPHER tls-client tls-version-min 1.2 tls-cipher $CC_CIPHER setenv opt block-outside-dns # Prevent Windows 10 DNS leak verb 3" >> /etc/openvpn/client-template.txt } # Check for root, TUN, OS... initialCheck initializeOpenVPN