Last active
February 15, 2022 19:42
-
-
Save mhabedinpour/53cda88effbd997e2e271ae48cf9c143 to your computer and use it in GitHub Desktop.
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
#!/bin/bash | |
set -e | |
# !!!ONLY FOR MACOS!!! | |
# This script helps you to bypass VPN for specific CIDRs and domain names by adding a direct route to the default gateway for them. | |
# It also can be used to setup a killswitch. When killswitch is enabled, Only IP traffic to the VPN server (and other bypassed CIDRs) is allowed, All other packets would be dropped. | |
# Killswitch is powered by MacOS internal packet filter (PF) firewall. | |
# How to use? | |
# Download and save the script. | |
# Make it executable: sudo chmod +x /path/to/script.sh | |
# Update configuration parameters below. | |
# Either password-less sudo or run-as-root is required. | |
# Run the script: /path/to/script.sh | |
# If you want to remove all added routes and disable killswitch: /path/to/script.sh -c | |
# If you want to manually disable killswitch: sudo pfctl -d | |
# Configuration | |
default_interface="en0" # Update your default interface here, Use ifconfig to find your default interface. If using WiFi, It's usually "en0". | |
vpn_interfaces=("utun0" "utun1" "utun2" "utun3" "utun4" "utun5" "utun6" "utun7" "utun8" "utun9" "utun10" "ipsec0" "ipsec1") # List of interfaces used by your VPN service. Use ifconfig to find them. (Important only when using killswitch.) | |
dns_resolver="1.1.1.1" # DNS resolver for mapping domain names to IP addresses. | |
websites=("lahzenegar.com" "stdn.iau.ac.ir") # Domains to bypass VPN. | |
ip_addresses=("192.168.1.0/24" "192.168.0.0/24" "192.168.8.0/24") # CIDRs to bypass VPN. If you want to use killswitch, Add VPN server IP address here as well. | |
enable_ks=true # Whether to enable killswitch or not. Use "true" to enable it, Anything else to disable it. | |
clean_only=false | |
if getopts "c" arg; then | |
clean_only=true | |
fi | |
gateway=$(netstat -nr | grep default | grep ${default_interface} | awk '{print $2}' | head -1) | |
echo -e "Gateway: ${gateway}\n----------" | |
echo -e "Resolving Domains...\n----------" | |
for website in "${websites[@]}"; do | |
for ip_address in $(dig @${dns_resolver} +short "${website}" | grep '^[.0-9]*$'); do | |
if ! (printf '%s\n' "${ip_addresses[@]}" | grep -q "${ip_address}"); then | |
ip_addresses+=("${ip_address}/32") | |
fi | |
done | |
done | |
for ip_address in "${ip_addresses[@]}"; do | |
sudo route delete "${ip_address}" || true | |
if [ "$clean_only" = false ]; then | |
sudo route -n add -net "${ip_address}" "${gateway}" | |
fi | |
echo "----------" | |
done | |
if [ "$enable_ks" = true ] && [ "$clean_only" = false ]; then | |
pf_conf=$(cat <<-END | |
set block-policy drop | |
set ruleset-optimization basic | |
set skip on lo0 | |
block all | |
block out quick inet6 all | |
pass from any to 255.255.255.255 keep state | |
pass from 255.255.255.255 to any keep state | |
pass proto udp from any to 224.0.0.0/4 keep state | |
pass proto udp from 224.0.0.0/4 to any keep state | |
pass on ${default_interface} proto {tcp,udp} from any port 67:68 to any port 67:68 keep state | |
pass from any to ${dns_resolver} | |
END | |
) | |
for vpn_interface in "${vpn_interfaces[@]}"; do | |
pf_conf="${pf_conf}\n pass on ${vpn_interface} all" | |
done | |
for ip_address in "${ip_addresses[@]}"; do | |
pf_conf="${pf_conf}\n pass from any to ${ip_address}" | |
done | |
echo -e "Starting Killswitch...\n----------" | |
echo -e "${pf_conf}" > ~/pf_ks.conf | |
sudo pfctl -Fa -f ~/pf_ks.conf -e || true | |
else | |
sudo pfctl -d || true | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment