Skip to content

Instantly share code, notes, and snippets.

@oskar456
Last active June 14, 2023 22:19
  • Star 10 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save oskar456/7264828 to your computer and use it in GitHub Desktop.
A simple script to set up policy routing on linux. It's stateless and detects everything automatically, so all you have to do is to run it after every network subsystem change. I run it in postup and postdown hooks in Gentoo network configuration file.
#!/bin/bash
IP="/bin/ip"
function prepare_rt_table() {
local rttables=/etc/iproute2/rt_tables
local iface=$1
[[ "${iface}" = 'lo' ]] && return
if ! egrep -q "\s${iface}\s*"\$ $rttables; then
idx=$(wc -l <$rttables)
echo -e "$(( 300 + ${idx} ))\t${iface}" >> $rttables
fi
}
function get_ipv4_addressses() {
local iface=$1
$IP -4 addr show dev ${iface} | sed -rn '/inet / s_^.*inet ([0-9.]*)/.*$_\1_p'
}
function get_ipv6_addressses() {
local iface=$1
$IP -6 addr show dev ${iface} | sed -rn '/inet6 / s_^.*inet6 ([0-9a-f:]*)/.*$_\1_p'
}
function transfer_routes_ipv4() {
local iface=$1
$IP -4 route flush table ${iface}
while read line; do
[[ -z "$line" ]] && continue
$IP -4 route add ${line} table ${iface}
done <<-EOF
$($IP -4 rou show table main | grep "dev ${iface}" |\
sed -r 's_expires [^ ]*__' | sed -r 's_proto [^ ]*__' )
EOF
}
function transfer_routes_ipv6() {
local iface=$1
$IP -6 route flush table ${iface}
while read line; do
[[ -z "$line" ]] && continue
$IP -6 route add ${line} table ${iface}
done <<-EOF
$($IP -6 rou show table main | grep "dev ${iface}" |\
sed -r 's_expires [^ ]*__' | sed -r 's_proto [^ ]*__' )
EOF
}
function get_table_id() {
local rttables=/etc/iproute2/rt_tables
local table=$1
sed -rn "/^\s*[0-9]*\s*${table}/ s_^\s*([0-9]+)\s.*_\1_p" $rttables
}
function replace_rules_ipv4 {
local iface=$1
local tableid=$(get_table_id $iface)
while $IP -4 rule show | egrep -q ^${tableid}; do
$IP -4 rule del prio ${tableid}
done
for ipaddr in $(get_ipv4_addressses ${iface}); do
$IP -4 rule add prio ${tableid} from ${ipaddr} table ${iface}
done
}
function replace_rules_ipv6 {
local iface=$1
local tableid=$(get_table_id $iface)
while $IP -6 rule show | egrep -q ^${tableid}; do
$IP -6 rule del prio ${tableid}
done
for ipaddr in $(get_ipv6_addressses ${iface}); do
echo $ipaddr | egrep -q '^fe80:' && continue
$IP -6 rule add prio ${tableid} from ${ipaddr} table ${iface}
done
}
for ifpath in /sys/class/net/*; do
iface=${ifpath##*/}
[[ "${iface}" = 'lo' ]] && continue
prepare_rt_table ${iface}
transfer_routes_ipv4 ${iface}
replace_rules_ipv4 ${iface}
transfer_routes_ipv6 ${iface}
replace_rules_ipv6 ${iface}
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment