Skip to content

Instantly share code, notes, and snippets.

@isoteemu
Created April 28, 2016 10:45
Show Gist options
  • Save isoteemu/a28dee89480e532f1e2256ddc5791a80 to your computer and use it in GitHub Desktop.
Save isoteemu/a28dee89480e532f1e2256ddc5791a80 to your computer and use it in GitHub Desktop.
NetworkManager dispatcher script for limited VPN connection routing
#!/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