Created
November 19, 2018 17:47
-
-
Save fluks/c0f9d24753a55dd62a9969399d83da6c to your computer and use it in GitHub Desktop.
Open and close a VPN connection with strict firewall rules
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -e | |
#set -x | |
# Default interface. | |
eth=eth0 | |
vpn_device=tun0 | |
vpn_port=1194 | |
vpn_proto=udp | |
function usage() { | |
echo "usage: $(basename "$0") us1|us2|nl1|nl2|jp1 on|off" >&2 | |
} | |
declare -A vpn_con | |
# Get VPN settings from a command line argument. | |
function get_vpn() { | |
declare -A vpn_con_us1=( [name]="us-free-01.protonvpn.com.udp1194" [host]="us-free-01.protonvpn.com" ) | |
declare -A vpn_con_us2=( [name]="us-free-02.protonvpn.com.udp1194" [host]="us-free-02.protonvpn.com" ) | |
declare -A vpn_con_nl1=( [name]="nl-free-01.protonvpn.com.udp1194" [host]="nl-free-01.protonvpn.com" ) | |
declare -A vpn_con_nl2=( [name]="nl-free-02.protonvpn.com.udp1194" [host]="nl-free-02.protonvpn.com" ) | |
declare -A vpn_con_jp1=( [name]="jp-free-01.protonvpn.com.udp1194" [host]="jp-free-01.protonvpn.com" ) | |
case "$1" in | |
"us1" | "us2" | "nl1" | "nl2" | "jp1") | |
local tmp="vpn_con_$1[name]" | |
vpn_con[name]=${!tmp} | |
tmp="vpn_con_$1[host]" | |
vpn_con[host]=${!tmp} | |
;; | |
*) | |
usage | |
exit 1 | |
;; | |
esac | |
} | |
ips=() | |
# Get IPs of a VPN host. | |
function get_ips() { | |
# Ip is last in the line. | |
for ip in $(host "${vpn_con[host]}" | rev | cut -d ' ' -f 1 | rev); do | |
ips+=("$ip") | |
done | |
} | |
# Allow or delete minimal ufw rules to open a VPN connection, DNS and OpenVPN | |
# to selected VPN's IPs. | |
# param delete? Set rules if non-empty, delete them otherwise. | |
function ufw_openvpn_open_rules() { | |
local del= | |
if [[ -n $1 ]]; then | |
del=delete | |
fi | |
sudo ufw $del allow out on "$eth" proto udp to any port 53 | |
for ip in "${ips[@]}"; do | |
sudo ufw $del allow out on "$eth" proto "$vpn_proto" to "$ip" port "$vpn_port" | |
done | |
} | |
get_vpn "$1" | |
get_ips | |
if [[ $2 = 'on' ]]; then | |
sudo ufw default deny incoming | |
sudo ufw default deny outgoing | |
sudo ufw allow out on "$vpn_device" | |
ufw_openvpn_open_rules | |
set +e | |
sudo nmcli --ask con up id "${vpn_con[name]}" | |
set -e | |
ufw_openvpn_open_rules del | |
elif [[ $2 = 'off' ]]; then | |
sudo nmcli --ask con down id "${vpn_con[name]}" | |
sudo ufw default allow outgoing | |
sudo ufw delete allow out on "$vpn_device" | |
else | |
usage | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requirements
Usage
get_vpn
function. Name is the name you gave for the connection in NetworkManager. You can get them by runningnmcli con
.us1, us2, nl2, ...
everywhere in the script. Also the ends of the array names inget_vpn
function. It's up to you how you name them.Replace
us1
above with the alias you gave to the connection names.