From 9be711a48e9ddff5e95987abe1c9bfc3c393a62a Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sun, 28 Aug 2016 10:01:01 +0200 Subject: misc: setup_routing.sh : less crude, english comments --- misc/setup_routing.sh | 251 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 160 insertions(+), 91 deletions(-) diff --git a/misc/setup_routing.sh b/misc/setup_routing.sh index 730e036..7d86541 100755 --- a/misc/setup_routing.sh +++ b/misc/setup_routing.sh @@ -1,64 +1,88 @@ #!/bin/bash -CONFFILE=/root/config_adt.bkp.sh -if [ $# -gt 0 ] -then export DRY=echo -fi - -function nettoyage_nat() { - ip4_public=$1 - - ip addr show dev lo | grep -q "$ip4_public/32" && $DRY ip addr del $ip4_public/32 dev lo - - deleted=0 - ruleno_pre=$(iptables -t nat -L PREROUTING -n --line-numbers | grep " $ip4_public " | cut -d' ' -f1 | head -n1) - if [ -n "$ruleno_pre" ] - then $DRY iptables -t nat -D PREROUTING $ruleno_pre - deleted=1 - fi - ruleno_post=$(iptables -t nat -L POSTROUTING -n --line-numbers | grep -E "to:$ip4_public$" | cut -d' ' -f1 | head -n1) - if [ -n "$ruleno_post" ] - then $DRY iptables -t nat -D POSTROUTING $ruleno_post - deleted=1 - fi - if [ $deleted -eq 1 ] - then $DRY conntrack -L -q $ip4_public - fi -} - -function activation_nat() { - ip4_nexthop=$1 - ip4_public=$2 - - ip addr show dev lo | grep -q "$ip4_public/32" || $DRY ip addr add $ip4_public/32 dev lo +CONF_FILE=/root/config_adt.sh # (.sh is backward compat) +#CONF_FILE=/root/config_svc_test.conf +export DRY=echo # Dummy mode +#export DRY=echo_log_run # Real mode + +# Copyright 2016 Ludovic Pouzenc +# +# This file is part of CHD Gestion. +# +# CHD Gestion is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# CHD Gestion is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with CHD Gestion. If not, see . + +function main() { + # Init globals and work files + PROGNAME=$(basename $0) + BOOTTIME_TS=$(date +%s -d "$(uptime -s)") + > /etc/hosts.svc + > /etc/ethers.adt - iptables -t nat -L PREROUTING -n --line-numbers | grep -E "to:$ip4_nexthop$" -q \ - || $DRY iptables -t nat -A PREROUTING -d $ip4_public -j DNAT --to-destination $ip4_nexthop + # Apply each config line from CONF_FILE + while read line; do do_conf $line; done <$CONF_FILE - iptables -t nat -L POSTROUTING -n --line-numbers | grep " $ip4_nexthop " -q \ - || $DRY iptables -t nat -A POSTROUTING -s $ip4_nexthop -j SNAT --to-source $ip4_public + # Finalize setup + cat /etc/hosts.system /etc/hosts.svc > /etc/hosts + cat /etc/ethers.system /etc/ethers.adt > /etc/ethers + $DRY ip route flush cache + $DRY arp -f /etc/ethers } -# Appelé pour chaque service à router +# do_conf is called for each internet access service to (un)route function do_conf() { + shift # do_conf keyword (backward compat from time we "source $CONF_FILE") + svc_etat=$1 # Mandatory + svc_id=$2 # Mandatory + ip4_nexthop=$3 # Optionnal (if set, NAT will be used, else direct routing will be used to ip4_public) + ip4_public=$4 # Mandatory + ip6_nexthop=$5 # Optionnal + ip6_prefix=$6 # Optionnal + mac_nexthop=${7:--} # Optionnal + modified_ts=${8:--} # Optionnal (but important for cancel|suspend) + + # FIXME sanity checks, code injection here + + shift dev=eth1 - svc_etat=$1 - svc_id=$2 - ip4_nexthop=$3 - ip4_public=$4 - ip6_nexthop=$5 - ip6_prefix=$6 - mac_nexthop=$7 - - # Référencer les IP du service en cours de configuration dans le fichiers hosts (résolutions DNS locales) + case $svc_etat in + actif|active) # actif = backward compat + do_conf_enable $dev "$@" ;; + cancel|suspend) + do_conf_disable $dev "$@" ;; + esac +} + +function do_conf_enable() { + dev=$1 # Mandatory (interface to join the user's router) + svc_id=$2 # Mandatory + ip4_nexthop=$3 # Optionnal (if set, NAT will be used, else direct routing will be used to ip4_public) + ip4_public=$4 # Mandatory + ip6_nexthop=$5 # Optionnal + ip6_prefix=$6 # Optionnal + mac_nexthop=${7:--} # Optionnal + modified_ts=${8:--} # Unused + + # Keep track of all configured IP in hosts file for local DNS reverse resolutions ( [ "$ip4_nexthop" != "-" ] && printf '%-22s %s\n' ${ip4_nexthop} ${svc_id}.nh4 [ "$ip6_nexthop" != "-" ] && printf '%-22s %s\n' ${ip6_nexthop} ${svc_id}.nh6 [ "$ip4_public" != "-" ] && printf '%-22s %s\n' ${ip4_public} ${svc_id}.ip4 [ "$ip6_prefix" != "-" ] && printf '%-22s %s\n' ${ip6_prefix}1 ${svc_id}.ip6 - ) >> /etc/hosts.adt + ) >> /etc/hosts.svc - # Ajouter des entrées statiques dans /etc/ethers pour la table ARP (économie broadcast + changements IP WAN) - if [ "$mac_nexthop" != "-" -a "$mac_nexthop" != "" ] + # Keep track of all routers MAC in ethers file to add static ARP entries on them + # This save broadcasts and helps about stolen or misconfigured WAN IPv4 + if [ "$mac_nexthop" != "-" ] then if [ "$ip4_nexthop" != "-" ] then echo $mac_nexthop $ip4_nexthop >> /etc/ethers.adt else if [ "$ip4_public" != "-" ] @@ -67,57 +91,102 @@ function do_conf() { fi fi - case $svc_etat in - actif) - # Cas CHD OpenWRT sans NAT - if [ ${ip4_nexthop} = "-" ] - then - echo $svc_id CHD no NAT - # Nettoyage NAT éventuel - nettoyage_nat $ip4_public - - # CHD IPv4 Internet -> ADT - $DRY ip -4 route replace $ip4_public/32 dev $dev - - # CHD IPv6 Internet -> ADT - if [ $ip6_prefix != "-" -a $ip6_nexthop != "-" ] - then $DRY ip -6 route replace $ip6_prefix/56 via $ip6_nexthop dev $dev - fi - else - # Cas CHD avec NAT (OpenWRT natté ou firmware TP-Link) - echo $svc_id CHD with NAT + # IPv4 Internet -> adherent's router + if [ ${ip4_nexthop} = "-" ] + then # No NAT case + + # Clean up nat in case we change from "with NAT" to "without NAT" situation + nat_cleanup $ip4_public - # CHD IPv4 NAT Internet <-> ADT - activation_nat $ip4_nexthop $ip4_public + #IPv4 route setup + exists=$(ip route show $ip4_public/32 dev $dev | wc -l) + if [ "$exists" -ne 1 ] + then $DRY ip -4 route add $ip4_public/32 dev $dev + fi + + else # With NAT case + nat_setup $ip4_nexthop $ip4_public + fi - # CHD IPv6 Internet -> ADT - if [ $ip6_prefix != "-" -a $ip6_nexthop != "-" ] - then $DRY ip -6 route replace $ip6_prefix/56 via $ip6_nexthop dev $dev + # IPv6 Internet -> adherent's router + if [ $ip6_prefix != "-" -a $ip6_nexthop != "-" ] + then exists=$(ip -6 route show $ip6_prefix/56 dev $dev | wc -l) + if [ "$exists" -ne 1 ] + then $DRY ip -6 route replace $ip6_prefix/56 via $ip6_nexthop dev $dev + fi + fi +} + +function do_conf_disable() { + dev=$1 # Mandatory (interface to join the user's router) + svc_id=$2 # Unused + ip4_nexthop=$3 # Unused + ip4_public=$4 # Mandatory + ip6_nexthop=$5 # Unused + ip6_prefix=$6 # Optionnal + mac_nexthop=${7:--} # Unused + modified_ts=${8:--} # Mandatory + + # Defensive code even on madatory fields here, because of legacy data + if [ "$modified_ts" != "-" ] + then # system reboot flush all live routing config. Skip cleanup of older config entries + if [ $modified_ts -ge $BOOTTIME_TS ] + then + if [ "$ip4_public" != "-" ] + then nat_cleanup $ip4_public + exists=$(ip route show $ip4_public/32 dev $dev | wc -l) + if [ "$exists" -eq 1 ] + then $DRY ip -4 route delete $ip4_public/32 dev $dev + fi + fi + if [ $ip6_prefix != "-" ] + then exists=$(ip -6 route show $ip6_prefix/56 dev $dev | wc -l) + if [ "$exists" -eq 1 ] + then $DRY ip -6 route delete $ip6_prefix/56 dev $dev fi fi + fi + fi +} - ;; - resilie) - echo "Attention, durant la migration les resilies sont a decabler manuellement" - echo "-> $*" - ;; - esac +function nat_setup() { + ip4_nexthop=$1 + ip4_public=$2 + + ip addr show dev lo | grep -q "$ip4_public/32" || $DRY ip addr add $ip4_public/32 dev lo + + iptables -t nat -L PREROUTING -n --line-numbers | grep -E "to:$ip4_nexthop$" -q \ + || $DRY iptables -t nat -A PREROUTING -d $ip4_public -j DNAT --to-destination $ip4_nexthop + + iptables -t nat -L POSTROUTING -n --line-numbers | grep " $ip4_nexthop " -q \ + || $DRY iptables -t nat -A POSTROUTING -s $ip4_nexthop -j SNAT --to-source $ip4_public } -#function main() { +function nat_cleanup() { + ip4_public=$1 - # Initialise - > /etc/hosts.adt - > /etc/ethers.adt + ip addr show dev lo | grep -q "$ip4_public/32" && $DRY ip addr del $ip4_public/32 dev lo - # Met en place la conf de chaque adherent - source $CONFFILE + deleted=0 + ruleno_pre=$(iptables -t nat -L PREROUTING -n --line-numbers | grep " $ip4_public " | cut -d' ' -f1 | head -n1) + if [ -n "$ruleno_pre" ] + then $DRY iptables -t nat -D PREROUTING $ruleno_pre + deleted=1 + fi + ruleno_post=$(iptables -t nat -L POSTROUTING -n --line-numbers | grep -E "to:$ip4_public$" | cut -d' ' -f1 | head -n1) + if [ -n "$ruleno_post" ] + then $DRY iptables -t nat -D POSTROUTING $ruleno_post + deleted=1 + fi + if [ $deleted -eq 1 ] + then $DRY conntrack -D -q $ip4_public || true + fi +} - # Finalise - cat /etc/hosts.system /etc/hosts.adt > /etc/hosts - cat /etc/ethers.system /etc/ethers.adt > /etc/ethers - $DRY ip route flush cache - $DRY arp -f /etc/ethers - exit 0 -#} +function echo_log_run() { + echo $@ + logger -t "$PROGNAME" -- $@ + $@ +} +main -- cgit v1.1