Created
April 28, 2016 10:45
-
-
Save isoteemu/a28dee89480e532f1e2256ddc5791a80 to your computer and use it in GitHub Desktop.
NetworkManager dispatcher script for limited VPN connection routing
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/sh | |
# | |
# * Preample | |
# | |
# This script is a NetworkManager script for generating necessary routing tables | |
# when using IPRedator service as a secondary network connection. | |
# | |
# By default, programs will still be using default route, but it becomes possible to | |
# bind them to use ppp0 -interface or IPRedator ip address. | |
# | |
# | |
# * Usage | |
# | |
# First, define IPRedator service in NetworkManager, as documented: | |
# https://ipredator.se/guide/pptp/ubuntu | |
# | |
# Next, modify setting by chaning it to _not_ define default routes, in | |
# "PPTP Settings" -> "Advanced" -> "IPv4 Address" -> Select "Routes" and check | |
# "Ignore automaticly obtained routes" and "Use only for resources on this connection". | |
# Accept, save, whatever. | |
# | |
# Save this script as /etc//etc/NetworkManager/dispatcher.d/90-ipredator, and make | |
# sure it's executable: chmod a+x /etc//etc/NetworkManager/dispatcher.d/90-ipredator | |
# | |
# Define new routing table in /etc/iproute2/rt_tables, by adding line: | |
# 100 <name> | |
# where <name> should either be name you gave for your connection, ie. IPredator, or one you | |
# can define in this file in $RT_TABLE variable. | |
# | |
# Now you're good to go, and in services like KTorrent you can use ppp0 interface for routing | |
# network connections thru IPRedator, or use FoxyProxy with polipo to route just some sites. | |
# | |
# * Variables | |
# | |
# Use Connection ID as Routing table name, or define here same as in /etc/iproute2/rt_tables | |
RT_TABLE="VPNBook" | |
# Firewall marking value. Leave empty to disable. | |
FWMARK="0x50" | |
# If using firewall marking, it becomes possible to route allways some addresses thru vpn | |
VPN_ROUTED_ADDRESSES="thepiratebay.se thepirateybay.org archive.is archive.today" | |
# Name for iptables table | |
VPN_CHAIN_POSTROUTING="VPN-${VPN_IP_IFACE}-POSTROUTING" | |
VPN_CHAIN_OUTPUT="VPN-${VPN_IP_IFACE}-MANGLE" | |
# * Magic | |
[ "${2}" != 'vpn-up' ] && [ "${2}" != 'vpn-down' ] && exit 0 | |
# Check existing routing table | |
if [[ ! `grep "$RT_TABLE" /etc/iproute2/rt_tables` ]]; then | |
logger "Missing routing table $RT_TABLE from /etc/iproute2/rt_tables" | |
exit 0 | |
fi | |
. /etc/rc.status | |
case "${2}" in | |
vpn-up) | |
test -z "$VPN_IP4_NUM_ADDRESSES" && exit 0 | |
# Create new iptables chain | |
iptables -t nat -N "$VPN_CHAIN_POSTROUTING" | |
iptables -t nat -A POSTROUTING -j "$VPN_CHAIN_POSTROUTING" | |
# Add routes to IP's | |
IP_COUNT=0 | |
while [ $IP_COUNT -lt $VPN_IP4_NUM_ADDRESSES ]; do | |
IP_VARIABLE="VPN_IP4_ADDRESS_${IP_COUNT}" | |
VPN_INET_ADDRESS=`echo ${!IP_VARIABLE} | sed -n 's/\([0-9\.]*\).*/\1/p'` | |
# Create routes | |
ip rule add from "$VPN_INET_ADDRESS" lookup "$RT_TABLE" | |
ip route add default dev "$VPN_IP_IFACE" table "$RT_TABLE" | |
# Let nat rewrite return address. | |
iptables -t nat -A "$VPN_CHAIN_POSTROUTING" -o "$VPN_IP_IFACE" -j SNAT --to-source="$VPN_INET_ADDRESS" | |
let IP_COUNT=IP_COUNT+1 | |
done | |
# Add static routes to nameserver, as they can be on other than /24 netmask | |
if [[ ! -z $VPN_IP4_NAMESERVERS ]]; then | |
for NS in $VPN_IP4_NAMESERVERS; do | |
ip rule add to $NS lookup "$RT_TABLE" | |
done | |
fi | |
echo 0 > /proc/sys/net/ipv4/conf/${DEVICE_IP_IFACE}/rp_filter | |
echo 0 > /proc/sys/net/ipv4/conf/${VPN_IP_IFACE}/rp_filter | |
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter | |
if [[ ! -z "$FWMARK" ]]; then | |
ip rule add fwmark "$FWMARK" table "$RT_TABLE" | |
# Iptables rules for mangling | |
iptables -t mangle -N "$VPN_CHAIN_OUTPUT" | |
iptables -t mangle -A OUTPUT -j "$VPN_CHAIN_OUTPUT" | |
# iptables -t mangle -A PREROUTING -i ppp0 -m state --state NEW -j CONNMARK --set-mark 0x50 | |
if [[ ! -z $VPN_ROUTED_ADDRESSES ]]; then | |
for ADDRESS in $VPN_ROUTED_ADDRESSES; do | |
#host "$ADDRESS" > /dev/null || continue | |
iptables -A "$VPN_CHAIN_OUTPUT" -t mangle -d "$ADDRESS" -j MARK --set-mark $FWMARK && logger "Mangling routed address $ADDRESS" || logger "Mangling routed address $ADDRESS FAILED" | |
done | |
fi | |
# If polipo is installed, mangle it too | |
if (/usr/bin/id "polipo" > /dev/null 2>&1 && checkproc /usr/bin/polipo ); then | |
iptables -t mangle -A $VPN_CHAIN_OUTPUT -m owner --uid-owner "polipo" -j MARK --set-mark $FWMARK && logger "Mangling polipo routing" || logger "Mangling polipo routing FAILED" | |
fi | |
fi | |
;; | |
vpn-down) | |
# Drop iptables rules. | |
iptables -t nat -F "$VPN_CHAIN_POSTROUTING" | |
iptables -t nat -D POSTROUTING -j "$VPN_CHAIN_POSTROUTING" | |
iptables -t nat -X "$VPN_CHAIN_POSTROUTING" | |
if [[ ! -z "$FWMARK" ]]; then | |
iptables -t mangle -F "$VPN_CHAIN_OUTPUT" | |
iptables -t mangle -D OUTPUT -j "$VPN_CHAIN_OUTPUT" | |
iptables -t mangle -X "$VPN_CHAIN_OUTPUT" | |
fi | |
# Drop old rules. | |
ip rule | sed -n "s/.*\(from[ \t]*.*\|to[ \t]*.*\) $RT_TABLE/\1 $RT_TABLE/p" | while read RULE; do | |
ip rule del $RULE | |
done | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment