Skip to content

Instantly share code, notes, and snippets.

@p3nj
Last active September 8, 2021 09:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save p3nj/226dd609a76d89d496bdb1e809a674c5 to your computer and use it in GitHub Desktop.
Save p3nj/226dd609a76d89d496bdb1e809a674c5 to your computer and use it in GitHub Desktop.
Mullvad-WireGuard Script with macOS pfctl killswitch implant
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) 2016-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
die() {
echo "[-] Error: $1" >&2
exit 1
}
# Change this to your condition.
WIFI="en0"
VPN="utun3"
PROGRAM="${0##*/}"
ARGS=( "$@" )
SELF="${BASH_SOURCE[0]}"
[[ $SELF == */* ]] || SELF="./$SELF"
SELF="$(cd "${SELF%/*}" && pwd -P)/${SELF##*/}"
[[ $UID == 0 ]] || exec sudo -p "[?] $PROGRAM must be run as root. Please enter the password for %u to continue: " -- "$BASH" -- "$SELF" "${ARGS[@]}"
[[ ${BASH_VERSINFO[0]} -ge 4 ]] || die "bash ${BASH_VERSINFO[0]} detected, when bash 4+ required"
type curl >/dev/null || die "Please install curl and then try again."
type jq >/dev/null || die "Please install jq and then try again."
set -e
read -p "[?] Please enter your Mullvad account number: " -r ACCOUNT
echo "[+] Contacting Mullvad API for server locations."
declare -A SERVER_ENDPOINTS_IPV4
declare -A SERVER_ENDPOINTS
declare -A SERVER_PUBLIC_KEYS
declare -A SERVER_LOCATIONS
declare -a SERVER_CODES
RESPONSE="$(curl -LsS https://api.mullvad.net/public/relays/wireguard/v1/)" || die "Unable to connect to Mullvad API."
FIELDS="$(jq -r 'foreach .countries[] as $country (.; .; foreach $country.cities[] as $city (.; .; foreach $city.relays[] as $relay (.; .; $country.name, $city.name, $relay.hostname, $relay.public_key, $relay.ipv4_addr_in)))' <<<"$RESPONSE")" || die "Unable to parse response."
while read -r COUNTRY && read -r CITY && read -r HOSTNAME && read -r PUBKEY && read -r IPADDR; do
CODE="${HOSTNAME%-wireguard}"
SERVER_CODES+=( "$CODE" )
SERVER_LOCATIONS["$CODE"]="$CITY, $COUNTRY"
SERVER_PUBLIC_KEYS["$CODE"]="$PUBKEY"
SERVER_ENDPOINTS["$CODE"]="$IPADDR:51820"
SERVER_ENDPOINTS_IPV4["$CODE"]="$IPADDR"
done <<<"$FIELDS"
shopt -s nocasematch
for CODE in "${SERVER_CODES[@]}"; do
CONFIGURATION_FILE="/etc/wireguard/mullvad-$CODE.conf"
[[ -f $CONFIGURATION_FILE ]] || continue
while read -r line; do
[[ $line =~ ^PrivateKey\ *=\ *([a-zA-Z0-9+/]{43}=)\ *$ ]] && PRIVATE_KEY="${BASH_REMATCH[1]}" && break
done < "$CONFIGURATION_FILE"
[[ -n $PRIVATE_KEY ]] && echo "[+] Using existing private key." && break
done
shopt -u nocasematch
if [[ -z $PRIVATE_KEY ]]; then
echo "[+] Generating new private key."
PRIVATE_KEY="$(wg genkey)"
fi
echo "[+] Contacting Mullvad API."
RESPONSE="$(curl -sSL https://api.mullvad.net/wg/ -d account="$ACCOUNT" --data-urlencode pubkey="$(wg pubkey <<<"$PRIVATE_KEY")")" || die "Could not talk to Mullvad API."
[[ $RESPONSE =~ ^[0-9a-f:/.,]+$ ]] || die "$RESPONSE"
ADDRESS="$RESPONSE"
DNS="193.138.219.228"
echo "[+] Writing WriteGuard configuration files."
for CODE in "${SERVER_CODES[@]}"; do
CONFIGURATION_FILE_KS="/etc/wireguard/killswitch/mullvad-$CODE.conf"
CONFIGURATION_FILE="/etc/wireguard/mullvad-$CODE.conf"
umask 077
mkdir -p /etc/wireguard/
mkdir -p /etc/wireguard/killswitch/
rm -f "$CONFIGURATION_FILE.tmp"
cat > "$CONFIGURATION_FILE.tmp" <<-_EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = $ADDRESS
DNS = $DNS
PostUp = pfctl -e -Fa -f /etc/wireguard/killswitch/mullvad-$CODE.conf
PostDown = pfctl -Fa -f /etc/pf.conf
[Peer]
PublicKey = ${SERVER_PUBLIC_KEYS["$CODE"]}
Endpoint = ${SERVER_ENDPOINTS["$CODE"]}
AllowedIPs = 0.0.0.0/0, ::/0
_EOF
mv "$CONFIGURATION_FILE.tmp" "$CONFIGURATION_FILE"
rm -f "$CONFIGURATION_FILE_KS.tmp"
cat > "$CONFIGURATION_FILE_KS.tmp" <<-_EOF
set block-policy drop
set ruleset-optimization basic
set skip on lo0
block out all
block in all
pass out on $WIFI proto {tcp, udp} from any to ${SERVER_ENDPOINTS_IPV4["$CODE"]}
pass out on $VPN all
_EOF
mv "$CONFIGURATION_FILE_KS.tmp" "$CONFIGURATION_FILE_KS"
done
echo "[+] Success. The following commands may be run for connecting to Mullvad:"
for CODE in "${SERVER_CODES[@]}"; do
echo "- ${SERVER_LOCATIONS["$CODE"]}:"
echo " \$ wg-quick up mullvad-$CODE"
done
echo "Please wait up to 60 seconds for your public key to be added to the servers."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment