#!/bin/bash INTERFACE=wg0 METRIC=31 TIMEOUT=180 INTERVAL=2 readarray -t ROUTES < <(echo "$WG_ROUTES" | tr , '\n') netenclose () { local o1 o2 o3 o4 p1 p2 p3 p4 m1 m2 ip1 ip2 min IFS=./ read o1 o2 o3 o4 m1 <<< "$1" IFS=./ read p1 p2 p3 p4 m2 <<< "$2" ((min = m1 > m2 ? m2 : m1)) ip1=$(((o1 << 24) + (o2 << 16) + (o3 << 8) + o4)) ip2=$(((p1 << 24) + (p2 << 16) + (p3 << 8) + p4)) if (( (ip1 >> (32 - min)) == (ip2 >> (32 - min)) )); then if ((m1 > m2)); then echo "$2" else echo "$1" fi else echo "0.0.0.0/0" fi } while true do current_time=`date +%s` readarray -t peers < <(wg show wg0 dump) for peer in "${peers[@]}" do args=($(echo $peer)) public_key=${args[0]} private_key=${args[1]} endpoint=${args[2]} route_list=${args[3]} handshake=${args[4]} bytes_recv=${args[5]} bytes_sent=${args[6]} keep_alive=${args[7]} # If it's a remote peer, the private key should be '(none)' # Otherwise, it's us if [ "$private_key" != "(none)" ]; then continue fi # The following checks ensure this peer is reachable and set the 'up' # flag accordingly if [ "$endpoint" == "(none)" ]; then up=false elif [ "$handshake" == "0" ]; then up=false else delta="$((current_time - handshake))" if [ $delta -gt $TIMEOUT ]; then up=false else up=true fi fi readarray -t routes < <(echo "$route_list" | tr , '\n') for route in "${routes[@]}" do in_network=false for ROUTE in "${ROUTES[@]}" do parent_route=`netenclose $route $ROUTE` if [ "$parent_route" == "$ROUTE" ]; then in_network=true break fi done # Only manipulate routes that are in the global WG_ROUTES variable if [ $in_network == false ]; then continue fi if [ "$up" == "true" ]; then ip route add $route dev $INTERFACE metric $METRIC 2> /dev/null && echo "Added route $route from peer $public_key ($endpoint)" else ip route delete $route dev $INTERFACE 2> /dev/null && echo "Removed route $route from peer $public_key" fi done done sleep $INTERVAL done