Last active
September 8, 2021 09:13
-
-
Save p3nj/226dd609a76d89d496bdb1e809a674c5 to your computer and use it in GitHub Desktop.
Mullvad-WireGuard Script with macOS pfctl killswitch implant
This file contains 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 | |
# 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