#!/bin/bash # Install using: sudo su -c "bash <(wget -qO- /url/to/install-openvpn-server.sh)" # Make sure script is ran as root if [[ $EUID -ne 0 ]]; then exec sudo /bin/bash "$0" "$@" fi # Helper functions add_iptables_rule() { local RULE="$1" local TABLE="filter" # Default table is filter if [[ "$RULE" =~ -t[[:space:]]+(nat|mangle|raw|filter) ]]; then TABLE="${BASH_REMATCH[1]}" RULE="${RULE/-t ${BASH_REMATCH[1]}/}" # Remove "-t " from RULE fi local RULE_ACTION=$(echo "$RULE" | awk '{print $1}') local RULE_REST=$(echo "$RULE" | cut -d' ' -f2-) if iptables-save -t "$TABLE" | grep -Fq -- "$RULE_REST"; then echo "Rule already exists in table $TABLE, skipping: -t $TABLE $RULE" else echo "Adding iptables rule to table $TABLE: -t $TABLE $RULE" iptables -t "$TABLE" $RULE fi } # Setup script read -e -p "Enter lan NIC: " -i $(ip route | grep default | sed -e 's/^.*dev.//' -e 's/.proto.*//') NIC_NAME read -e -p "Enter VPN subnet: " -i "172.19.100" VPN_SUBNET read -e -p "Enter LAN subnet: " -i "192.168.0" LAN_SUBNET read -e -p "Enter VPN public hostname: " -i "home.myspace.nu" VPN_PUBLIC_HOST read -e -p "Enter VPN public portnumber: " -i "1194" VPN_PUBLIC_PORT if [ $(dpkg-query -W -f='${Status}' openvpn 2>/dev/null | grep -c "ok installed") -eq 0 ]; then echo "Installing OpenVPN..." apt install openvpn easy-rsa -y fi if [ ! -d /etc/openvpn/easy-rsa ]; then echo "Setting up Certificate Authority" make-cadir /etc/openvpn/easy-rsa cd /etc/openvpn/easy-rsa ./easyrsa init-pki ./easyrsa build-ca ./easyrsa gen-req myservername nopass ./easyrsa gen-dh ./easyrsa sign-req server myservername cp pki/dh.pem pki/ca.crt pki/issued/myservername.crt pki/private/myservername.key /etc/openvpn/ fi if [ ! -d /var/log/openvpn ]; then mkdir -p /var/log/openvpn fi if [ ! -d /etc/openvpn/ccd ]; then mkdir -p /etc/openvpn/ccd fi if ufw status | grep -q "Status: active"; then echo Adding firewall rules... ufw allow $VPN_PUBLIC_PORT/udp ufw allow OpenSSH ufw enable ufw status verbose echo You might need to enable NAT / MASQUERADE forwarding in /etc/ufw/before.rules systemctl restart ufw fi if [ ! -f /etc/openvpn/myserver.conf ] || [[ " $@ " == *" --force "* ]]; then read -n 1 -p "Do you want to use username and password for login (y/N)? " answer if [[ ! -z "$answer" && "${answer^^}"=="Y" ]]; then EXTRA_CONFIG=$(cat <<-END script-security 2 # must be at least 2 auth-user-pass-verify /etc/openvpn/auth-script.sh via-file username-as-common-name # without this openvpn will use cn in the certificate as username duplicate-cn # you may need this if everyone is using same certificate verify-client-cert require END ) fi tee /etc/openvpn/myserver.conf > /dev/null < /usr/local/bin/add-openvpn-client.sh #!/bin/bash # Make sure script is ran as root if [[ $EUID -ne 0 ]]; then exec sudo /bin/bash "$0" "$@" fi DIR=$(pwd) for i in {1..255}; do CLIENT_NAME="client$i" if [ ! -f "/etc/openvpn/easy-rsa/pki/issued/$CLIENT_NAME.crt" ]; then break fi done VPN_SUBNET=$(grep -E '^server ' "/etc/openvpn/myserver.conf" | awk '{print $2}') VPN_PUBLIC_HOST=$(grep -E '^#public-host ' "/etc/openvpn/myserver.conf" | awk '{print $2}') VPN_PUBLIC_PORT=$(grep -E '^port ' "/etc/openvpn/myserver.conf" | awk '{print $2}') echo "Adding VPN client to $VPN_PUBLIC_HOST:$VPN_PUBLIC_PORT" read -e -p "Enter client name: " -i "$CLIENT_NAME" CLIENT_NAME if [ -f "/etc/openvpn/easy-rsa/pki/issued/$CLIENT_NAME.crt" ]; then echo Client $CLIENT_NAME already exists... exit 1 fi if grep -q "^auth-user-pass-verify" "/etc/openvpn/myserver.conf"; then read -e -p "Enter username: " -i "$CLIENT_NAME" CLIENT_USERNAME if grep -i -q "^$CLIENT_USERNAME" "/etc/openvpn/credentials"; then echo "Username $CLIENT_USERNAME already exists" exit 1 fi read -e -p "Enter password: " -i "$CLIENT_PASSWORD" CLIENT_PASSWORD CLIENT_PASSWORD_HASH=$(echo -n "$CLIENT_PASSWORD" | sha256sum | awk '{print $1}') echo "$CLIENT_USERNAME:$CLIENT_PASSWORD_HASH:$CLIENT_NAME" >> "/etc/openvpn/credentials" EXTRA_CONFIG="auth-user-pass" fi read -e -p "Use static IP for this client? VPN subnet is $VPN_SUBNET (Leave empty for dynamic): " -i "" CLIENT_IP if [ ! -z "${CLIENT_IP}" ]; then echo Setting IP... cat > "/etc/openvpn/ccd/$CLIENT_NAME" < $CLIENT_NAME.conf < $CA_CERT $CLIENT_CERT $CLIENT_KEY key-direction 1 $TA_KEY EOL EOF chmod +755 /usr/local/bin/add-openvpn-client.sh cat << 'EOF' > /usr/local/bin/remove-iptable-dups.sh #!/bin/bash iptables-save | awk '!seen[$0]++ || /^(\*|COMMIT)/' | iptables-restore EOF chmod +755 /usr/local/bin/remove-iptable-dups.sh cat << 'EOF' > /etc/openvpn/auth-script.sh #!/bin/bash readarray -t lines < $1 username=${lines[0]} password=${lines[1]} password_hash=$(echo -n "$password" | sha256sum | awk '{print $1}') if grep -i -q "^$username:$password_hash:" "/etc/openvpn/credentials"; then exit 0 # Authentication success else exit 1 # Authentication failed fi EOF chmod +755 /etc/openvpn/auth-script.sh