diff --git a/openvpn-install.sh b/openvpn-install.sh index 26bf31c..a482364 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -110,6 +110,11 @@ check_ip() { printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX" } +find_public_ip() { + # Get public IP and sanitize with grep + get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")") +} + abort_and_exit () { echo "Abort. No changes were made." >&2 exit 1 @@ -208,31 +213,43 @@ if [[ ! -e /etc/openvpn/server/server.conf ]]; then if [[ $(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') -eq 1 ]]; then ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}') else - number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') - echo - echo "Which IPv4 address should be used?" - ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | nl -s ') ' - read -p "IPv4 address [1]: " ip_number - until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do - echo "$ip_number: invalid selection." - read -p "IPv4 address [1]: " ip_number - done - [[ -z "$ip_number" ]] && ip_number="1" - ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | sed -n "$ip_number"p) + find_public_ip + ip_list=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}') + ip_match=0 + while IFS= read -r line; do + if [ "$line" = "$get_public_ip" ]; then + ip_match=1 + ip="$line" + fi + done <<< "$ip_list" + if [ "$ip_match" = 0 ]; then + number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') + echo + echo "Which IPv4 address should be used?" + ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | nl -s ') ' + read -rp "IPv4 address [1]: " ip_number + until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do + echo "$ip_number: invalid selection." + read -rp "IPv4 address [1]: " ip_number + done + [[ -z "$ip_number" ]] && ip_number="1" + ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | sed -n "$ip_number"p) + fi 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 - echo - echo "This server is behind NAT. What is the public IPv4 address or hostname?" - # Get public IP and sanitize with grep - get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")") - read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip - # If the checkip service is unavailable and user didn't provide input, ask again - until [[ -n "$get_public_ip" || -n "$public_ip" ]]; do - echo "Invalid input." - read -p "Public IPv4 address / hostname: " public_ip - done - [[ -z "$public_ip" ]] && public_ip="$get_public_ip" + find_public_ip + if [ -z "$get_public_ip" ]; then + echo + echo "This server is behind NAT. What is the public IPv4 address?" + read -rp "Public IPv4 address: " public_ip + until check_ip "$public_ip"; do + echo "Invalid input." + read -rp "Public IPv4 address: " public_ip + done + else + public_ip="$get_public_ip" + fi fi # If system has a single IPv6, it is selected automatically if [[ $(ip -6 addr | grep -c 'inet6 [23]') -eq 1 ]]; then @@ -244,10 +261,10 @@ if [[ ! -e /etc/openvpn/server/server.conf ]]; then echo echo "Which IPv6 address should be used?" ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | nl -s ') ' - read -p "IPv6 address [1]: " ip6_number + read -rp "IPv6 address [1]: " ip6_number until [[ -z "$ip6_number" || "$ip6_number" =~ ^[0-9]+$ && "$ip6_number" -le "$number_of_ip6" ]]; do echo "$ip6_number: invalid selection." - read -p "IPv6 address [1]: " ip6_number + read -rp "IPv6 address [1]: " ip6_number done [[ -z "$ip6_number" ]] && ip6_number="1" ip6=$(ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | sed -n "$ip6_number"p) @@ -256,10 +273,10 @@ if [[ ! -e /etc/openvpn/server/server.conf ]]; then echo "Which protocol should OpenVPN use?" echo " 1) UDP (recommended)" echo " 2) TCP" - read -p "Protocol [1]: " protocol + read -rp "Protocol [1]: " protocol until [[ -z "$protocol" || "$protocol" =~ ^[12]$ ]]; do echo "$protocol: invalid selection." - read -p "Protocol [1]: " protocol + read -rp "Protocol [1]: " protocol done case "$protocol" in 1|"") @@ -271,10 +288,10 @@ if [[ ! -e /etc/openvpn/server/server.conf ]]; then esac echo echo "What port should OpenVPN listen to?" - read -p "Port [1194]: " port + read -rp "Port [1194]: " port until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do echo "$port: invalid port." - read -p "Port [1194]: " port + read -rp "Port [1194]: " port done [[ -z "$port" ]] && port="1194" echo @@ -286,10 +303,10 @@ if [[ ! -e /etc/openvpn/server/server.conf ]]; then echo " 5) Quad9" echo " 6) AdGuard DNS" echo " 7) Custom" - read -p "DNS server [2]: " dns + read -rp "DNS server [2]: " dns until [[ -z "$dns" || "$dns" =~ ^[1-7]$ ]]; do echo "$dns: invalid selection." - read -p "DNS server [2]: " dns + read -rp "DNS server [2]: " dns done if [ "$dns" = "7" ]; then read -rp "Enter primary DNS server: " dns1 @@ -305,7 +322,7 @@ if [[ ! -e /etc/openvpn/server/server.conf ]]; then fi echo echo "Enter a name for the first client:" - read -p "Name [client]: " unsanitized_client + read -rp "Name [client]: " unsanitized_client # Allow a limited set of characters to avoid conflicts client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client") [[ -z "$client" ]] && client="client" @@ -594,21 +611,21 @@ else echo " 3) Revoke an existing client" echo " 4) Remove OpenVPN" echo " 5) Exit" - read -p "Option: " option + read -rp "Option: " option until [[ "$option" =~ ^[1-5]$ ]]; do echo "$option: invalid selection." - read -p "Option: " option + read -rp "Option: " option done case "$option" in 1) echo echo "Provide a name for the client:" - read -p "Name: " unsanitized_client + read -rp "Name: " unsanitized_client [ -z "$unsanitized_client" ] && abort_and_exit client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client") while [[ -z "$client" || -e /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt ]]; do echo "$client: invalid name." - read -p "Name: " unsanitized_client + read -rp "Name: " unsanitized_client [ -z "$unsanitized_client" ] && abort_and_exit client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client") done @@ -633,11 +650,11 @@ else echo echo "Select the client to export:" tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') ' - read -p "Client: " client_number + read -rp "Client: " client_number [ -z "$client_number" ] && abort_and_exit until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do echo "$client_number: invalid selection." - read -p "Client: " client_number + read -rp "Client: " client_number [ -z "$client_number" ] && abort_and_exit done client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_number"p) @@ -658,19 +675,19 @@ else echo echo "Select the client to revoke:" tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') ' - read -p "Client: " client_number + read -rp "Client: " client_number [ -z "$client_number" ] && abort_and_exit until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do echo "$client_number: invalid selection." - read -p "Client: " client_number + read -rp "Client: " client_number [ -z "$client_number" ] && abort_and_exit 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 "Confirm $client revocation? [y/N]: " revoke + read -rp "Confirm $client revocation? [y/N]: " revoke until [[ "$revoke" =~ ^[yYnN]*$ ]]; do echo "$revoke: invalid selection." - read -p "Confirm $client revocation? [y/N]: " revoke + read -rp "Confirm $client revocation? [y/N]: " revoke done if [[ "$revoke" =~ ^[yY]$ ]]; then echo @@ -701,10 +718,10 @@ else ;; 4) echo - read -p "Confirm OpenVPN removal? [y/N]: " remove + read -rp "Confirm OpenVPN removal? [y/N]: " remove until [[ "$remove" =~ ^[yYnN]*$ ]]; do echo "$remove: invalid selection." - read -p "Confirm OpenVPN removal? [y/N]: " remove + read -rp "Confirm OpenVPN removal? [y/N]: " remove done if [[ "$remove" =~ ^[yY]$ ]]; then echo