User:Jchdel: Difference between revisions
(Created page with "After live migrating a fleet of (~150) embedded devices from Debian 8 to Alpine 3.6, it is now time to refactor the disk layout (i.e. reinstalling remotely and live) and migra...") |
(how to select fastest uplink on a router) |
||
Line 1: | Line 1: | ||
to be run periodically (I do it every minutes for a 3 ISP setup) | |||
<pre> | |||
#!/bin/bash | |||
# This script configure the router to use fastest available gateway | |||
# as default one. It uses some bashism... | |||
[ -f /tmp/router.order ] && logger "Already running" && exit 1 | |||
NICS=($(ip -br link|awk '{print $1}')) # index 0 is loopback (lo) | |||
NNICS=$((${#NICS[@]}-1)) | |||
GWS=() | |||
IPS=() | |||
iptables -t mangle -F | |||
iptables -t nat -F | |||
iptables -F INPUT | |||
iptables -F OUTPUT | |||
# Did we lost all of our gateways? | |||
ip route | grep -q default || \ | |||
for ((i=1; i<=$NNICS; i++)) | |||
do | |||
ifdown ${NICS[$i]} | |||
ifup ${NICS[$i]} && \ | |||
logger "${NICS[$i]} restarted." || \ | |||
logger "Unable to restart ${NICS[$i]}." | |||
done | |||
# Prepare routing tables for each gateway | |||
for ((i=1; i<=$NNICS; i++)) | |||
do | |||
IPS[$i]="$(ip a s ${NICS[$i]}|awk '/inet/{print $2}'|cut -d/ -f1)" | |||
[ -z "${IPS[$i]}" ] && GWS[$i]="" && continue | |||
GWS[$i]="$(ip r | grep default | grep -v dead | grep ${NICS[$i]} | cut -d\ -f3)" | |||
[ -z "${GWS[$i]}" ] && continue | |||
# duplicate main routing table for each live default gateway | |||
ip route flush table $i | |||
ip route show table main | grep -Ev ^default | while read ROUTE ; do | |||
ip route add table $i $ROUTE | |||
done | |||
# add default gateway | |||
ip route add table $i default via ${GWS[$i]} dev ${NICS[$i]} | |||
# mark packets from localhost | |||
iptables -t mangle -A OUTPUT -s ${IPS[$i]} -j MARK --set-mark $i | |||
# activate alternate routing | |||
while $(ip rule del fwmark $i table $i);do .;done 2>/dev/null | |||
ip rule add fwmark $i table $i prio ${i}0 | |||
# disable kernel filtering of "unwanted" packets | |||
echo 0 > /proc/sys/net/ipv4/conf/${NICS[$i]}/rp_filter | |||
done | |||
# activate changes in policy routing | |||
ip route flush cache | |||
# ping same target via each gateway | |||
for ((i=1; i<=$NNICS; i++)) | |||
do | |||
[ -z "${GWS[$i]}" ] && continue | |||
( ping -n -c 5 -q -I ${IPS[$i]} 1.1 >/dev/null \ | |||
&& logger "1.1 responded for ${IPS[$i]} dev ${NICS[$i]}" \ | |||
|| logger "No response from 1.1 for ${IPS[$i]} dev ${NICS[$i]}" ; \ | |||
echo $i >> /tmp/router.order ) & | |||
done | |||
wait -n # first gateway to complete | |||
INDEX=$(head -1 /tmp/router.order) | |||
# set default router for FORWARDED packets | |||
iptables -t mangle -A FORWARD -j MARK --set-mark $INDEX | |||
# MASQUERADE or SNAT ? | |||
iptables -t nat -I POSTROUTING -o ${NICS[$INDEX]} -j MASQUERADE #SNAT --to-source ${IPS[$INDEX]} | |||
ip route flush cache # not sure this one is needed? | |||
logger "Default route set via ${GWS[$INDEX]} dev ${NICS[$INDEX]}." | |||
wait # other gateways to complete | |||
rm -f /tmp/router.order | |||
exit 0 | |||
</pre> |
Revision as of 10:31, 16 October 2021
to be run periodically (I do it every minutes for a 3 ISP setup)
#!/bin/bash # This script configure the router to use fastest available gateway # as default one. It uses some bashism... [ -f /tmp/router.order ] && logger "Already running" && exit 1 NICS=($(ip -br link|awk '{print $1}')) # index 0 is loopback (lo) NNICS=$((${#NICS[@]}-1)) GWS=() IPS=() iptables -t mangle -F iptables -t nat -F iptables -F INPUT iptables -F OUTPUT # Did we lost all of our gateways? ip route | grep -q default || \ for ((i=1; i<=$NNICS; i++)) do ifdown ${NICS[$i]} ifup ${NICS[$i]} && \ logger "${NICS[$i]} restarted." || \ logger "Unable to restart ${NICS[$i]}." done # Prepare routing tables for each gateway for ((i=1; i<=$NNICS; i++)) do IPS[$i]="$(ip a s ${NICS[$i]}|awk '/inet/{print $2}'|cut -d/ -f1)" [ -z "${IPS[$i]}" ] && GWS[$i]="" && continue GWS[$i]="$(ip r | grep default | grep -v dead | grep ${NICS[$i]} | cut -d\ -f3)" [ -z "${GWS[$i]}" ] && continue # duplicate main routing table for each live default gateway ip route flush table $i ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table $i $ROUTE done # add default gateway ip route add table $i default via ${GWS[$i]} dev ${NICS[$i]} # mark packets from localhost iptables -t mangle -A OUTPUT -s ${IPS[$i]} -j MARK --set-mark $i # activate alternate routing while $(ip rule del fwmark $i table $i);do .;done 2>/dev/null ip rule add fwmark $i table $i prio ${i}0 # disable kernel filtering of "unwanted" packets echo 0 > /proc/sys/net/ipv4/conf/${NICS[$i]}/rp_filter done # activate changes in policy routing ip route flush cache # ping same target via each gateway for ((i=1; i<=$NNICS; i++)) do [ -z "${GWS[$i]}" ] && continue ( ping -n -c 5 -q -I ${IPS[$i]} 1.1 >/dev/null \ && logger "1.1 responded for ${IPS[$i]} dev ${NICS[$i]}" \ || logger "No response from 1.1 for ${IPS[$i]} dev ${NICS[$i]}" ; \ echo $i >> /tmp/router.order ) & done wait -n # first gateway to complete INDEX=$(head -1 /tmp/router.order) # set default router for FORWARDED packets iptables -t mangle -A FORWARD -j MARK --set-mark $INDEX # MASQUERADE or SNAT ? iptables -t nat -I POSTROUTING -o ${NICS[$INDEX]} -j MASQUERADE #SNAT --to-source ${IPS[$INDEX]} ip route flush cache # not sure this one is needed? logger "Default route set via ${GWS[$INDEX]} dev ${NICS[$INDEX]}." wait # other gateways to complete rm -f /tmp/router.order exit 0