From 6a29a6babdb6e2d813c6c585800debc1558ead2d Mon Sep 17 00:00:00 2001 From: Nyr Date: Thu, 26 Sep 2019 19:13:33 +0200 Subject: [PATCH] Miscellaneous improvements This commit contains lots changes which are not very significant on its own but provide important usability improvements and future proofing. It also includes changes which required OpenVPN v2.4+ and were pending until that version became widely available. - General cleanup - Improved IP address and NAT configuration - Added input validation and sanitization - Fix #603 - Remove "sndbuf" and "recvbuf" parameters - Add server-side "explicit-exit-notify" - Switch from "setenv opt" to "ignore-unknown-option" - Switch from "tls-auth" to "tls-crypt" - Other minor bugfixes and optimizations --- openvpn-install.sh | 291 ++++++++++++++++++++++++++------------------- 1 file changed, 168 insertions(+), 123 deletions(-) diff --git a/openvpn-install.sh b/openvpn-install.sh index 646ff87..1216b50 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -5,22 +5,22 @@ # Copyright (c) 2013 Nyr. Released under the MIT License. -if grep -qs "14.04" "/etc/os-release"; then +if grep -qs "14.04" /etc/os-release; then echo "Ubuntu 14.04 is too old and not supported" exit fi -if grep -qs "jessie" "/etc/os-release"; then +if grep -qs "jessie" /etc/os-release; then echo "Debian 8 is too old and not supported" exit fi -if grep -qs "CentOS release 6" "/etc/redhat-release"; then +if grep -qs "CentOS release 6" /etc/redhat-release; then echo "CentOS 6 is too old and not supported" exit fi -if grep -qs "Ubuntu 16.04" "/etc/os-release"; then +if grep -qs "Ubuntu 16.04" /etc/os-release; then echo 'Ubuntu 16.04 is no longer supported in the current version of openvpn-install Use an older version if Ubuntu 16.04 support is needed: https://git.io/vpn1604' exit @@ -44,31 +44,33 @@ You need to enable TUN before running this script" fi if [[ -e /etc/debian_version ]]; then - OS=debian - GROUPNAME=nogroup + os="debian" + group_name="nogroup" elif [[ -e /etc/centos-release || -e /etc/redhat-release ]]; then - OS=centos - GROUPNAME=nobody + os="centos" + group_name="nobody" else echo "Looks like you aren't running this installer on Debian, Ubuntu or CentOS" exit fi -newclient () { +new_client () { # Generates the custom client.ovpn - cp /etc/openvpn/server/client-common.txt ~/$1.ovpn - echo "" >> ~/$1.ovpn - cat /etc/openvpn/server/easy-rsa/pki/ca.crt >> ~/$1.ovpn - echo "" >> ~/$1.ovpn - echo "" >> ~/$1.ovpn - sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/$1.crt >> ~/$1.ovpn - echo "" >> ~/$1.ovpn - echo "" >> ~/$1.ovpn - cat /etc/openvpn/server/easy-rsa/pki/private/$1.key >> ~/$1.ovpn - echo "" >> ~/$1.ovpn - echo "" >> ~/$1.ovpn - sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/ta.key >> ~/$1.ovpn - echo "" >> ~/$1.ovpn + { + cat /etc/openvpn/server/client-common.txt + echo "" + cat /etc/openvpn/server/easy-rsa/pki/ca.crt + echo "" + echo "" + sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/"$1".crt + echo "" + echo "" + cat /etc/openvpn/server/easy-rsa/pki/private/"$1".key + echo "" + echo "" + sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/tc.key + echo "" + } > ~/"$1".ovpn } if [[ -e /etc/openvpn/server/server.conf ]]; then @@ -82,26 +84,35 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then echo " 2) Revoke an existing user" echo " 3) Remove OpenVPN" echo " 4) Exit" - read -p "Select an option [1-4]: " option - case $option in + read -p "Select an option: " option + until [[ "$option" =~ ^[1-4]$ ]]; do + echo "$option: invalid selection." + read -p "Select an option: " option + done + case "$option" in 1) echo echo "Tell me a name for the client certificate." - echo "Please, use one word only, no special characters." - read -p "Client name: " -e CLIENT + read -p "Client name: " unsanitized_client + client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client") + while [[ -z "$client" || -e /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt ]]; do + echo "$client: invalid client name." + read -p "Client name: " unsanitized_client + client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client") + done cd /etc/openvpn/server/easy-rsa/ - EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full $CLIENT nopass + EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass # Generates the custom client.ovpn - newclient "$CLIENT" + new_client "$client" echo - echo "Client $CLIENT added, configuration is available at:" ~/"$CLIENT.ovpn" + echo "Client $client added, configuration is available at:" ~/"$client.ovpn" exit ;; 2) # This option could be documented a bit better and maybe even be simplified # ...but what can I say, I want some sleep too - NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V") - if [[ "$NUMBEROFCLIENTS" = '0' ]]; then + number_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V") + if [[ "$number_of_clients" = 0 ]]; then echo echo "You have no existing clients!" exit @@ -109,60 +120,68 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then echo echo "Select the existing client certificate you want to revoke:" tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') ' - if [[ "$NUMBEROFCLIENTS" = '1' ]]; then - read -p "Select one client [1]: " CLIENTNUMBER - else - read -p "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER - fi - CLIENT=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p) + read -p "Select one client: " client_number + until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do + echo "$client_number: invalid selection." + read -p "Select one client: " client_number + done + client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_number"p) echo - read -p "Do you really want to revoke access for client $CLIENT? [y/N]: " -e REVOKE - if [[ "$REVOKE" = 'y' || "$REVOKE" = 'Y' ]]; then + read -p "Do you really want to revoke access for client $client? [y/N]: " revoke + until [[ "$revoke" =~ ^[yYnN]*$ ]]; do + echo "$revoke: invalid selection." + read -p "Do you really want to revoke access for client $client? [y/N]: " revoke + done + if [[ "$revoke" =~ ^[yY]$ ]]; then cd /etc/openvpn/server/easy-rsa/ - ./easyrsa --batch revoke $CLIENT + ./easyrsa --batch revoke "$client" EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl - rm -f pki/reqs/$CLIENT.req - rm -f pki/private/$CLIENT.key - rm -f pki/issued/$CLIENT.crt + rm -f pki/reqs/"$client".req + rm -f pki/private/"$client".key + rm -f pki/issued/"$client".crt rm -f /etc/openvpn/server/crl.pem cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem # CRL is read with each client connection, when OpenVPN is dropped to nobody - chown nobody:$GROUPNAME /etc/openvpn/server/crl.pem + chown nobody:"$group_name" /etc/openvpn/server/crl.pem echo - echo "Certificate for client $CLIENT revoked!" + echo "Certificate for client $client revoked!" else echo - echo "Certificate revocation for client $CLIENT aborted!" + echo "Certificate revocation for client $client aborted!" fi exit ;; 3) echo - read -p "Do you really want to remove OpenVPN? [y/N]: " -e REMOVE - if [[ "$REMOVE" = 'y' || "$REMOVE" = 'Y' ]]; then - PORT=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2) - PROTOCOL=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2) + read -p "Do you really want to remove OpenVPN? [y/N]: " remove + until [[ "$remove" =~ ^[yYnN]*$ ]]; do + echo "$remove: invalid selection." + read -p "Do you really want to remove OpenVPN? [y/N]: " remove + done + if [[ "$remove" =~ ^[yY]$ ]]; then + port=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2) + protocol=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2) if pgrep firewalld; then - IP=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24 -j SNAT --to ' | cut -d " " -f 10) + ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24 -j SNAT --to ' | cut -d " " -f 10) # Using both permanent and not permanent rules to avoid a firewalld reload. - firewall-cmd --remove-port=$PORT/$PROTOCOL + firewall-cmd --remove-port="$port"/"$protocol" firewall-cmd --zone=trusted --remove-source=10.8.0.0/24 - firewall-cmd --permanent --remove-port=$PORT/$PROTOCOL + firewall-cmd --permanent --remove-port="$port"/"$protocol" firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24 - firewall-cmd --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP - firewall-cmd --permanent --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP + firewall-cmd --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" + firewall-cmd --permanent --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" else systemctl disable --now openvpn-iptables.service rm -f /etc/systemd/system/openvpn-iptables.service fi - if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$PORT" != '1194' ]]; then - semanage port -d -t openvpn_port_t -p $PROTOCOL $PORT + if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then + semanage port -d -t openvpn_port_t -p "$protocol" "$port" fi systemctl disable --now openvpn-server@server.service rm -rf /etc/openvpn/server rm -f /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf rm -f /etc/sysctl.d/30-openvpn-forward.conf - if [[ "$OS" = 'debian' ]]; then + if [[ "$os" = "debian" ]]; then apt-get remove --purge -y openvpn else yum remove openvpn -y @@ -180,39 +199,59 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then done else clear - echo 'Welcome to this OpenVPN "road warrior" installer!' + echo "Welcome to this OpenVPN "road warrior" installer!" echo - # OpenVPN setup and first user creation - echo "I need to ask you a few questions before starting the setup." - echo "You can leave the default options and just press enter if you are ok with them." - echo - echo "First, provide the IPv4 address of the network interface you want OpenVPN" - echo "listening to." - # Autodetect IP address and pre-fill for the user - IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1) - read -p "IP address: " -e -i $IP IP + echo "I need to ask you a few questions before starting setup." + echo "You can use the default options and just press enter if you are ok with them." + # If system has a single IPv4, it is selected automatically. Else, ask the user + if [[ $(ip addr | grep inet | grep -v inet6 | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') -eq 1 ]]; then + ip=$(ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') + else + number_of_ips=$(ip addr | grep inet | grep -v inet6 | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') + echo + echo "What IPv4 address should the OpenVPN server bind to?" + ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | nl -s ') ' + read -p "IPv4 address [1]: " ip_number + until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ips" ]]; do + echo "$ip_number: invalid selection." + read -p "IPv4 address [1]: " ip_number + done + [[ -z "$ip_number" ]] && ip_number="1" + ip=$(ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sed -n "$ip_number"p) + fi # If $IP is a private IP address, the server must be behind NAT - if echo "$IP" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then + if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then echo echo "This server is behind NAT. What is the public IPv4 address or hostname?" - read -p "Public IP address / hostname: " -e PUBLICIP + get_public_ip=$(wget -4qO- "http://whatismyip.akamai.com/" || curl -4Ls "http://whatismyip.akamai.com/") + read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip + [ -z "$public_ip" ] && public_ip="$get_public_ip" fi echo echo "Which protocol do you want for OpenVPN connections?" echo " 1) UDP (recommended)" echo " 2) TCP" - read -p "Protocol [1-2]: " -e -i 1 PROTOCOL - case $PROTOCOL in - 1) - PROTOCOL=udp + read -p "Protocol [1]: " protocol + until [[ -z "$protocol" || "$protocol" =~ ^[12]$ ]]; do + echo "$protocol: invalid selection." + read -p "Protocol [1]: " protocol + done + case "$protocol" in + 1|"") + protocol=udp ;; 2) - PROTOCOL=tcp + protocol=tcp ;; esac echo echo "What port do you want OpenVPN listening to?" - read -p "Port: " -e -i 1194 PORT + read -p "Port [1194]: " port + until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do + echo "$port: invalid selection." + read -p "Port [1194]: " port + done + [[ -z "$port" ]] && port="1194" echo echo "Which DNS do you want to use with the VPN?" echo " 1) Current system resolvers" @@ -220,21 +259,27 @@ else echo " 3) Google" echo " 4) OpenDNS" echo " 5) Verisign" - read -p "DNS [1-5]: " -e -i 1 DNS + read -p "DNS [1]: " dns + until [[ -z "$dns" || "$dns" =~ ^[1-5]$ ]]; do + echo "$dns: invalid selection." + read -p "DNS [1]: " dns + done echo - echo "Finally, tell me your name for the client certificate." - echo "Please, use one word only, no special characters." - read -p "Client name: " -e -i client CLIENT + echo "Finally, tell me a name for the client certificate." + read -p "Client name [client]: " unsanitized_client + # Allow a limited set of characters to avoid conflicts + client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client") + [[ -z "$client" ]] && client="client" echo echo "Okay, that was all I needed. We are ready to set up your OpenVPN server now." read -n1 -r -p "Press any key to continue..." # If running inside a container, disable LimitNPROC to prevent conflicts if systemd-detect-virt -cq; then mkdir /etc/systemd/system/openvpn-server@server.service.d/ 2>/dev/null - echo '[Service] -LimitNPROC=infinity' > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf + echo "[Service] +LimitNPROC=infinity" > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf fi - if [[ "$OS" = 'debian' ]]; then + if [[ "$os" = "debian" ]]; then apt-get update apt-get install openvpn iptables openssl ca-certificates -y else @@ -243,8 +288,8 @@ LimitNPROC=infinity' > /etc/systemd/system/openvpn-server@server.service.d/disab yum install openvpn iptables openssl ca-certificates -y fi # Get easy-rsa - EASYRSAURL='https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz' - wget -O ~/easyrsa.tgz "$EASYRSAURL" 2>/dev/null || curl -Lo ~/easyrsa.tgz "$EASYRSAURL" + easy_rsa_url='https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz' + wget -O ~/easyrsa.tgz "$easy_rsa_url" 2>/dev/null || curl -Lo ~/easyrsa.tgz "$easy_rsa_url" tar xzf ~/easyrsa.tgz -C ~/ mv ~/EasyRSA-3.0.5/ /etc/openvpn/server/ mv /etc/openvpn/server/EasyRSA-3.0.5/ /etc/openvpn/server/easy-rsa/ @@ -255,14 +300,14 @@ LimitNPROC=infinity' > /etc/systemd/system/openvpn-server@server.service.d/disab ./easyrsa init-pki ./easyrsa --batch build-ca nopass EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass - EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full $CLIENT nopass + EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl # Move the stuff we need cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn/server # CRL is read with each client connection, when OpenVPN is dropped to nobody - chown nobody:$GROUPNAME /etc/openvpn/server/crl.pem - # Generate key for tls-auth - openvpn --genkey --secret /etc/openvpn/server/ta.key + chown nobody:"$group_name" /etc/openvpn/server/crl.pem + # Generate key for tls-crypt + openvpn --genkey --secret /etc/openvpn/server/tc.key # Create the DH parameters file using the predefined ffdhe2048 group echo '-----BEGIN DH PARAMETERS----- MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz @@ -273,33 +318,32 @@ YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== -----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem # Generate server.conf - echo "port $PORT -proto $PROTOCOL + echo "local $ip +port $port +proto $protocol dev tun -sndbuf 0 -rcvbuf 0 ca ca.crt cert server.crt key server.key dh dh.pem auth SHA512 -tls-auth ta.key 0 +tls-crypt tc.key topology subnet server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt" > /etc/openvpn/server/server.conf echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf # DNS - case $DNS in - 1) + case "$dns" in + 1|"") # Locate the proper resolv.conf # Needed for systems running systemd-resolved if grep -q "127.0.0.53" "/etc/resolv.conf"; then - RESOLVCONF='/run/systemd/resolve/resolv.conf' + resolv_conf="/run/systemd/resolve/resolv.conf" else - RESOLVCONF='/etc/resolv.conf' + resolv_conf="/etc/resolv.conf" fi # Obtain the resolvers from resolv.conf and use them for OpenVPN - grep -v '#' $RESOLVCONF | grep 'nameserver' | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read line; do + grep -v '#' "$resolv_conf" | grep nameserver | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read line; do echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server/server.conf done ;; @@ -323,12 +367,15 @@ ifconfig-pool-persist ipp.txt" > /etc/openvpn/server/server.conf echo "keepalive 10 120 cipher AES-256-CBC user nobody -group $GROUPNAME +group $group_name persist-key persist-tun status openvpn-status.log verb 3 crl-verify crl.pem" >> /etc/openvpn/server/server.conf + if [[ "$protocol" = "udp" ]]; then + echo "explicit-exit-notify" >> /etc/openvpn/server/server.conf + fi # Enable net.ipv4.ip_forward for the system echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/30-openvpn-forward.conf # Enable without waiting for a reboot or service restart @@ -338,25 +385,25 @@ crl-verify crl.pem" >> /etc/openvpn/server/server.conf # reload. # We don't use --add-service=openvpn because that would only work with # the default port and protocol. - firewall-cmd --add-port=$PORT/$PROTOCOL + firewall-cmd --add-port="$port"/"$protocol" firewall-cmd --zone=trusted --add-source=10.8.0.0/24 - firewall-cmd --permanent --add-port=$PORT/$PROTOCOL + firewall-cmd --permanent --add-port="$port"/"$protocol" firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24 # Set NAT for the VPN subnet - firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP - firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP + firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" + firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" else # Create a service to set up persistent iptables rules echo "[Unit] Before=network.target [Service] Type=oneshot -ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP -ExecStart=/sbin/iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT +ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip +ExecStart=/sbin/iptables -I INPUT -p $protocol --dport $port -j ACCEPT ExecStart=/sbin/iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT ExecStart=/sbin/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT -ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP -ExecStop=/sbin/iptables -D INPUT -p $PROTOCOL --dport $PORT -j ACCEPT +ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip +ExecStop=/sbin/iptables -D INPUT -p $protocol --dport $port -j ACCEPT ExecStop=/sbin/iptables -D FORWARD -s 10.8.0.0/24 -j ACCEPT ExecStop=/sbin/iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT RemainAfterExit=yes @@ -365,7 +412,7 @@ WantedBy=multi-user.target" > /etc/systemd/system/openvpn-iptables.service systemctl enable --now openvpn-iptables.service fi # If SELinux is enabled and a custom port was selected, we need this - if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$PORT" != '1194' ]]; then + if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then # Install semanage if not already present if ! hash semanage 2>/dev/null; then if grep -qs "CentOS Linux release 7" "/etc/centos-release"; then @@ -374,21 +421,17 @@ WantedBy=multi-user.target" > /etc/systemd/system/openvpn-iptables.service yum install policycoreutils-python-utils -y fi fi - semanage port -a -t openvpn_port_t -p $PROTOCOL $PORT + semanage port -a -t openvpn_port_t -p "$protocol" "$port" fi - # And finally, enable and start the OpenVPN service - systemctl enable --now openvpn-server@server.service # If the server is behind a NAT, use the correct IP address - if [[ "$PUBLICIP" != "" ]]; then - IP=$PUBLICIP + if [[ "$public_ip" != "" ]]; then + ip="$public_ip" fi # client-common.txt is created so we have a template to add further users later echo "client dev tun -proto $PROTOCOL -sndbuf 0 -rcvbuf 0 -remote $IP $PORT +proto $protocol +remote $ip $port resolv-retry infinite nobind persist-key @@ -396,14 +439,16 @@ persist-tun remote-cert-tls server auth SHA512 cipher AES-256-CBC -setenv opt block-outside-dns -key-direction 1 +ignore-unknown-option block-outside-dns +block-outside-dns verb 3" > /etc/openvpn/server/client-common.txt + # Enable and start the OpenVPN service + systemctl enable --now openvpn-server@server.service # Generates the custom client.ovpn - newclient "$CLIENT" + new_client "$client" echo echo "Finished!" echo - echo "Your client configuration is available at:" ~/"$CLIENT.ovpn" - echo "If you want to add more clients, you simply need to run this script again!" + echo "Your client configuration is available at:" ~/"$client.ovpn" + echo "If you want to add more clients, just run this script again!" fi