1 #!/bin/bash
  2 
  3 ##################################################################
  4 # OpenVPN server selection script
  5 ##################################################################
  6 # Select from a list of .ovpn configuration files and connect
  7 # to the chosen server, using ufw rules to prevent vpn leaks
  8 #
  9 # Expects udp and tcp .ovpn files in the same directory
 10 # Expected filename formats: server-UDP.ovpn and server-TCP.ovpn
 11 ##################################################################
 12 # made with <3 by ~inthreedee ( https://tilde.town/~inthreedee/ )
 13 ##################################################################
 14 
 15 ovpnDir="$HOME/scripts/vpn"
 16 loginFile="$HOME/.config/vpn/login.conf"
 17 useLoginFile=1
 18 
 19 if [ ! -x "$(command -v openvpn)" ]; then
 20     echo "OpenVPN not installed, aborting."
 21     exit 1
 22 elif [ ! -x "$(command -v ufw)" ]; then
 23     echo "Uncomplicated Firewall not installed, aborting."
 24     exit 1
 25 elif [ ! -d "$ovpnDir" ]; then
 26     echo "Configuration directory not found, aborting."
 27     exit 1
 28 elif [ ! -f "$loginFile" ]; then
 29     useLoginFile=0
 30 fi
 31 
 32 # sets ufw rule to prevent leaks
 33 function ufw_set {
 34     echo "Setting ufw rules..."
 35     # deny all outgoing connections
 36     # requires an existing rule that allows connections out on tun0
 37     if [ -n "$ip" ]; then
 38         # allow us to connect to this server to establish the vpn tunnel
 39         echo "Allowing connections to $connection"
 40         sudo ufw allow out to "$ip"
 41     fi
 42     sudo ufw default deny outgoing
 43 }
 44 
 45 # remove the temporary ufw rules
 46 function ufw_cleanup {
 47     echo "Removing ufw rules..."
 48     if [ -n "$ip" ]; then
 49         sudo ufw delete allow out to "$ip"
 50     fi
 51     sudo ufw default allow outgoing
 52 }
 53 
 54 # build the list of UDP .ovpn files
 55 function udp_set {
 56     unset filelist
 57     readarray -d '' filelist < <(find . -maxdepth 1 -name "*UDP.ovpn" -type f -printf "%f\0" | sed 's/-UDP.ovpn//g' | sort -z)
 58     protocol="udp"
 59 }
 60 
 61 # build the list of TCP .ovpn files
 62 function tcp_set {
 63     unset filelist
 64     readarray -d '' filelist < <(find . -maxdepth 1 -name "*TCP.ovpn" -type f -printf "%f\0" | sed 's/-TCP.ovpn//g' | sort -z)
 65     protocol="tcp"
 66 }
 67 cd "$ovpnDir"
 68 # assume UDP until told otherwise
 69 udp_set
 70 looping=1
 71 
 72 # outer loop allows toggling between udp and tcp server lists
 73 while [ "$looping" -eq 1 ]
 74 do
 75     if [ "$protocol" == "tcp" ]; then
 76         echo -e "\nDisplaying TCP server list. Which would you like to connect to?"
 77         PS3="Enter a number to connect, 'udp' to show UDP servers, or 'q' to quit: "
 78     else
 79         echo -e "\nDisplaying UDP server list. Which would you like to connect to?"
 80         PS3="Enter a number to connect, 'tcp' to show TCP servers, or 'q' to quit: "
 81     fi
 82 
 83     select filename in "${filelist[@]}"
 84     do
 85         if [ "$REPLY" == "q" ]; then
 86             looping=0
 87             break
 88         fi
 89         if [ "$REPLY" == "tcp" ]; then
 90             tcp_set
 91             looping=1
 92             break
 93         fi
 94         if [ "$REPLY" == "udp" ]; then
 95             udp_set
 96             looping=1
 97             break
 98         fi
 99         if [ -z "$filename" ]; then
100             echo "Invalid selection"
101             continue
102         fi
103 
104         # add the extension back to the filename
105         if [ "$protocol" == "tcp" ]; then
106             filename+="-TCP.ovpn"
107         else
108             filename+="-UDP.ovpn"
109         fi
110 
111         # get the ip we'll be connecting to
112         ip="$(grep "remote" "$filename" | awk '{print $2}' | xargs dig +short | tail -n1)"
113         # store some of that ip info for debugging
114         connection="$(grep "remote" "$filename" | awk '{print $2}') -> $(grep "remote" "$filename" | awk '{print $2}' | xargs dig +short)"
115         # set ufw rules that prevent leaks
116         ufw_set
117         # undo ufw rules at script exit
118         trap ufw_cleanup EXIT
119 
120         if [ "$useLoginFile" -eq 0 ]; then
121             sudo openvpn --config "$filename" --auth-nocache --remote-cert-tls server
122         else
123             sudo openvpn --config "$filename" --auth-user-pass "$loginFile" --auth-nocache --remote-cert-tls server
124         fi
125 
126         looping=0
127         break
128     done
129 done