Skip to content

Instantly share code, notes, and snippets.

@fluks
Created November 19, 2018 17:47
Show Gist options
  • Save fluks/c0f9d24753a55dd62a9969399d83da6c to your computer and use it in GitHub Desktop.
Save fluks/c0f9d24753a55dd62a9969399d83da6c to your computer and use it in GitHub Desktop.
Open and close a VPN connection with strict firewall rules
#!/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
@fluks
Copy link
Author

fluks commented Nov 19, 2018

Requirements

  • nmcli and ufw
  • A VPN set up to work with NetworkManager

Usage

  • Change variables in the beginning of the script to what you have.
  • Change name and host keys in get_vpn function. Name is the name you gave for the connection in NetworkManager. You can get them by running nmcli con.
  • Change us1, us2, nl2, ... everywhere in the script. Also the ends of the array names in get_vpn function. It's up to you how you name them.
vpn_with_ufw_rules.sh us1 on
vpn_with_ufw_rules.sh us1 off

Replace us1 above with the alias you gave to the connection names.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment