Merge branch 'master' into emergency
authorMark Wooding <mdw@distorted.org.uk>
Tue, 6 Mar 2012 00:01:11 +0000 (00:01 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 6 Mar 2012 00:02:33 +0000 (00:02 +0000)
* master:
  functions.m4: Write the netclass ids to the trace output.
  bookends.m4: If debugging, dump the final tables.
  Determine forwarding and reverse-path filtering from host definitions.
  Overhaul address classification.
  local.m4: Promote the NTP server configuration to a proper variable.
  Renumber the diversions.
  fixup! WIP on emergency: 7a108d1 Makefile: New target for tracking diversions.
  Makefile: New target for tracking diversions.
  Makefile, base.m4: Inject the target hostname into the generated script.

Semantic conflict: The variable `if_dmz' is no longer set, so just
hardwire the interface name.

17 files changed:
.gitignore
Makefile
artist.m4
base.m4
bookends.m4
classify.m4
config.m4
fender.m4
functions.m4
gibson.m4
ibanez.m4
jem.m4
local.m4
numbers.m4
radius.m4
roadstar.m4
vampire.m4

index 7ba5f27..8bca642 100644 (file)
@@ -1,2 +1,3 @@
 *.sh
 cruft
+divs
index 8f918e5..b0f4612 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -102,7 +102,8 @@ TARGETS                      = $(addsuffix .sh,$(HOSTS))
 
 TARGETS                        += dummy.sh
 dummy.sh: base.m4 prologue.m4 dummy-payload.m4
-       $(V_M4) $^ >$@.new && chmod +x $@.new && mv $@.new $@
+       $(V_M4)-DFWHOST=testing $^ >$@.new
+       $(V_AT)chmod +x $@.new && mv $@.new $@
 
 TARGETS                        += dummy-inst.sh
 dummy-inst.sh: dummy.sh
@@ -110,16 +111,26 @@ dummy-inst.sh: dummy.sh
        $(V_AT)chmod +x $@.new && mv $@.new $@
 
 ###--------------------------------------------------------------------------
+### Other utilities.
+
+## A list of diversions in ascending numerical order.
+CLEANFILES             += divs
+divs: $(M4_SOURCES) $(addsuffix .m4,$(HOSTS))
+       $(V_GEN)grep -n m4_divert $^ | \
+               grep -v 'm4_divert(-1)' | \
+               sort -t\( -k2n >$@
+
+###--------------------------------------------------------------------------
 ### Building.
 
 all: $(TARGETS)
 .PHONY: all
 
 %.sh: %.m4 $(M4_SOURCES)
-       $(V_M4)base.m4 $*.m4 $(MAIN_M4_SOURCES) >$@.new
+       $(V_M4)-DFWHOST=$* base.m4 $*.m4 $(MAIN_M4_SOURCES) >$@.new
        $(V_AT)chmod +x $@.new && mv $@.new $@
 
-clean:; rm -f $(TARGETS) *.new
+clean:; rm -f $(TARGETS) *.new $(CLEANFILES)
 .PHONY: clean
 
 ###--------------------------------------------------------------------------
index 1f97e73..a04cc9c 100644 (file)
--- a/artist.m4
+++ b/artist.m4
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### artist-specific rules.
 
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        ssh \
diff --git a/base.m4 b/base.m4
index 5170531..8968025 100644 (file)
--- a/base.m4
+++ b/base.m4
@@ -29,24 +29,29 @@ m4_changecom(<:##:>)
 ### Overall structure.
 ###
 ###  0 File header: shebang, do-not-edit warning.              [base]
-###  5 Configuration.                                          [config]
+###  4 Configuration.                                          [config]
+###  6   Local settings.                                       [local]
 ### 10 Prologue: command-line parsing and failsafe.            [prologue]
 ### 20 Function definitions.                                   [functions]
-### 25 Port numbers etc.                                       [numbers]
+### 24 Port numbers etc.                                       [numbers]
+### 26 Networks, hosts and interfaces.                         [local]
 ### 30 Initialization.                                         [bookends]
 ### 30   Clear existing rules.                                 [bookends]
 ### 32   Set safe IP options.                                  [bookends]
 ### 34   Error chains.                                         [bookends]
-### 36   Give loopback traffic a free pass.                    [bookends]
 ### 38   Utility chains.                                       [functions]
 ### 40 Address classification.                                 [classify]
 ### 42   Definition of address class policies.                 [local]
 ### 44   Definition of interfaces and addresses.               [local]
 ### 46   Handling of default interface.                        [classify]
-### 50 ICMP filtering.                                         [icmp]
-### 52   Local configuration.                                  [local]
-### 58   Finally accept ICMP, hook onto INPUT and FORWARD.     [icmp]
-### 60 Local configuration.                                    [local]
+### 50 Packet filter.                                          [bookends]
+### 60 ICMP filtering.                                         [icmp]
+### 62   Local configuration.                                  [local]
+### 68   Finally accept ICMP, hook onto INPUT and FORWARD.     [icmp]
+### 80 Local configuration.                                    [local]
+### 84   Locally bound packet inspection.                      [local]
+### 86   Per-host configuration.                               [HOST]
+### 88   Final filtering.                                      [local]
 ### 90 Finishing touches.                                      [bookends]
 ### 94   Set final policies.                                   [bookends]
 ### 99 File footer: do-not-edit warning.                       [base]
@@ -56,6 +61,10 @@ m4_changecom(<:##:>)
 
 m4_divert(0)m4_dnl
 #! /bin/sh
+<:###:> Firewall script for FWHOST
+###
+### *** GENERATED FILE: DO NOT EDIT ***
+
 ### BEGIN INIT INFO
 # Provides:            firewall
 # Required-Start:      mountkernfs
@@ -66,10 +75,10 @@ m4_divert(0)m4_dnl
 # Default-Stop:                0 6
 # Description:         Provides customized packet filter rules.
 ### END INIT INFO
-### *** GENERATED FILE: DO NOT EDIT ***
 
 set -e
 PATH=/bin:/sbin:/usr/bin:/usr/sbin; export PATH
+fwhost=FWHOST
 
 m4_divert(99)m4_dnl
 ### *** GENERATED FILE: DO NOT EDIT ***
index b29047b..69a721e 100644 (file)
@@ -105,6 +105,10 @@ m4_divert(32)m4_dnl
 
 ## Set forwarding options.  Apparently setting ip_forward clobbers other
 ## settings, so put this first.
+case $host_type_<::>FWHOST in
+  router) forward=1 ;;
+  *) forward=0 ;;
+esac
 setopt ip_forward $forward
 setdevopt forwarding $forward
 
@@ -129,9 +133,11 @@ if [ -x /sbin/brctl ]; then
   fi
 fi
 
-## Turn on the reverse-path filter, and log weird things.
-setdevopt rp_filter $rp_filter
-setdevopt log_martians $log_martians
+## Turn off the reverse-path filter.  It's basically useless: the filter does
+## nothing at all for single-homed hosts; and multi-homed hosts tend to have
+## routing aysmmetries if there's any kind of cycle.
+setdevopt rp_filter 0
+setdevopt log_martians 0
 
 ## Turn off things which can mess with our routing decisions.
 setdevopt accept_source_route 0
@@ -164,7 +170,7 @@ errorchain bad-destination-address REJECT
 errorchain interesting ACCEPT
 ## Not an error, just log interesting packets.
 
-m4_divert(36)m4_dnl
+m4_divert(50)m4_dnl
 ###--------------------------------------------------------------------------
 ### Standard filtering.
 
@@ -179,26 +185,34 @@ run ip6tables -A INPUT -g bad-destination-address \
        -d ::1
 
 ## We shouldn't be asked to forward things with link-local addresses.
-run iptables -A FORWARD -g bad-source-address \
-       -s 169.254.0.0/16
-run iptables -A FORWARD -g bad-destination-address \
-       -d 169.254.0.0/16
-run ip6tables -A FORWARD -g bad-source-address \
-       -s fe80::/10
-run ip6tables -A FORWARD -g bad-destination-address \
-       -d fe80::/10
+case $forward in
+  1)
+    run iptables -A FORWARD -g bad-source-address \
+           -s 169.254.0.0/16
+    run iptables -A FORWARD -g bad-destination-address \
+           -d 169.254.0.0/16
+    run ip6tables -A FORWARD -g bad-source-address \
+           -s fe80::/10
+    run ip6tables -A FORWARD -g bad-destination-address \
+           -d fe80::/10
+    ;;
+esac
 
 ## Also, don't forward link-local broadcast or multicast.
-run iptables -A FORWARD -g bad-destination-address \
-       -d 255.255.255.255
-run iptables -A FORWARD -g bad-destination-address \
-       -m addrtype --dst-type BROADCAST
-run iptables -A FORWARD -g bad-destination-address \
-       -d 224.0.0.0/24
-for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
-  run ip6tables -A FORWARD -g bad-destination-address \
-       -d fe${x}2::/16
-done
+case $forward in
+  1)
+    run iptables -A FORWARD -g bad-destination-address \
+           -d 255.255.255.255
+    run iptables -A FORWARD -g bad-destination-address \
+           -m addrtype --dst-type BROADCAST
+    run iptables -A FORWARD -g bad-destination-address \
+           -d 224.0.0.0/24
+    for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+      run ip6tables -A FORWARD -g bad-destination-address \
+           -d fe${x}2::/16
+    done
+    ;;
+esac
 
 ## Add a hook for fail2ban.
 clearchain fail2ban
@@ -229,5 +243,17 @@ for ip in ip ip6; do
   done
 done
 
+## Dump the resulting configuration.
+if [ "$FW_DEBUG" ]; then
+  for ip in ip ip6; do
+    for table in mangle filter; do
+      echo "----- $ip $table -----"
+      echo
+      ${ip}tables -t $table -nvL
+      echo
+    done
+  done
+fi
+
 m4_divert(-1)
 ###----- That's all, folks --------------------------------------------------
index 6ad069c..8b6a650 100644 (file)
@@ -115,34 +115,129 @@ m4_divert(42)m4_dnl
 done
 
 m4_divert(46)m4_dnl
-## Mark addresses reachable on non-default interfaces as not reachable on the
-## default interface.
-trace "nets = $allnets $allnets6"
+## Build the input classification chains.  There's one chain `in-IFACE' for
+## each local interface.  This chain does a further dispatch on the source
+## address to the appropriate `mark-from-CLASS' chain for the source network
+## class.
+seen=:
+for iface in $host_ifaces_<::>FWHOST; do
+  ifname=${iface%=*}
+  case $seen in *:$ifname:*) continue ;; esac
+  seen=$seen$ifname:
+  clearchain mangle:in-$ifname
+  run ip46tables -t mangle -A in-classify -i $ifname -g in-$ifname
+done
+
+## Now populate the `in-IFACE' and `out-classify' chains.  We iterate over
+## the available networks and add addresses to the appropriate chains.  Also,
+## build up a map of which interfaces receive from which address ranged so
+## that we can finish the chains off properly later.  This contains entries
+## of the form IFACE=:ADDR:ADDR:...:
+ifnets=""
 for net in $allnets; do
-  defaultp=nil
-  for iface in $defaultifaces; do
-    case $net in $iface:*) defaultp=t ;; esac
+
+  ## Determine the addresses and class for this network, and populate the
+  ## `out-classify' chains.
+  eval addr=\$net_inet_$net addr6=\$net_inet6_$net class=\$net_class_$net
+  case $class in virtual) continue ;; esac
+  trace "$net : $class"
+  for a in $addr; do
+    run iptables -t mangle -A out-classify -g mark-to-$class -d $a
   done
-  case $defaultp in
-    nil)
-      for iface in $defaultifaces; do
-       run iptables -t mangle -A in-$iface \
-             -s ${net#*:} -g bad-source-address
-      done
-      ;;
-  esac
-done
-for net in $allnets6; do
-  defaultp=nil
-  for iface in $defaultifaces; do
-    case $net in $iface:*) defaultp=t ;; esac
+  for a in $addr6; do
+    run ip6tables -t mangle -A out-classify -g mark-to-$class -d $a
   done
-  case $defaultp in
-    nil)
-      for iface in $defaultifaces; do
-       run ip6tables -t mangle -A in-$iface \
-             -s ${net#*:} -g bad-source-address
+
+  ## Now work through the interfaces.
+  for iface in $(net_interfaces FWHOST $net); do
+    nets=""
+    case $iface in
+
+      -)
+       ## A special `no interface' marker: we should not receive packets
+       ## from this network at all.
+       continue
+       ;;
+
+      *-+)
+       ## A special marker indicating a collection of point-to-point
+       ## interfaces.  We should match an address to a particular interface.
+       ## Later, we'll cap this chain off by rejecting all other traffic.
+       eval hosts=\$net_hosts_$net
+       for host in $hosts; do
+         eval ha=\$host_inet_$host ha6=\$host_inet6_$host
+         trace "$host : $class -> $iface"
+         for a in $ha; do
+           run iptables -t mangle -A in-$iface \
+                   -i ${iface%+}$host -s $a -g mark-from-$class
+           nets=$nets$a:
+         done
+         for a in $ha6; do
+           run ip6tables -t mangle -A in-$iface \
+                   -i ${iface%+}$host -s $a -g mark-from-$class
+           nets=$nets$a:
+         done
+       done
+       ;;
+
+      *)
+       ## A normal interface.  Classify incoming traffic according to the
+       ## source address.
+       trace "$net : $class -> $iface"
+       for a in $addr; do
+         run iptables -t mangle -A in-$iface -g mark-from-$class -s $a
+         nets=$nets$a:
+       done
+       for a in $addr6; do
+         run ip6tables -t mangle -A in-$iface -g mark-from-$class -s $a
+         nets=$nets$a:
+       done
+       case $net in default) nets=${nets}default: ;; esac
+       ;;
+    esac
+
+    ## Record that this interface receives traffic from this network.
+    unset nifnets
+    foundp=nil
+    for ifnet in $ifnets; do
+      case $ifnet in
+       $iface=*:$net:*) addword nifnets $ifnet; foundp=t ;;
+       $iface=*) addword nifnets $ifnet$nets; foundp=t ;;
+       *) addword nifnets $ifnet ;;
+      esac
+    done
+    case $foundp in nil) addword nifnets $iface=:$nets ;; esac
+    ifnets=$nifnets
+
+  done
+done
+
+## Wrap up all of the `in-IFACE' chains.  A chain which matches the `default'
+## net should have unmatched but known networks blocked off, and then chain
+## onto `in-default'.  Other chains should just chain onto
+## `bad-source-address'.
+trace "ifnets = $ifnets"
+for ifnet in $ifnets; do
+  iface=${ifnet%%=*} nets=${ifnet#*=}
+  case $nets in
+    *:default:*)
+      for n in $allnets; do
+       eval addr=\$net_inet_$n addr6=\$net_inet6_$n
+       for a in $addr; do
+         case $nets in *:$a:*) continue ;; esac
+         nets=$nets$a
+         run iptables -t mangle -A in-$iface -s $a -g bad-source-address
+       done
+       for a in $addr6; do
+         case $nets in *:$a:*) continue ;; esac
+         nets=$nets$a
+         run ip6tables -t mangle -A in-$iface -s $a -g bad-source-address
+       done
       done
+      run ip46tables -t mangle -A in-$iface -g in-default
+      ;;
+    *)
+      run ip46tables -t mangle -A in-$iface -g bad-source-address
       ;;
   esac
 done
@@ -160,14 +255,15 @@ for addr in \
 do
   run ip6tables -t mangle -A in-default -s $addr -g bad-source-address
 done
+run ip46tables -t mangle -A in-default -g mark-from-$net_class_default
 
 m4_divert(92)m4_dnl
 ## Put the final default decision on the in-default chain, and attach the
 ## classification chains to the PREROUTING hook.
 for iface in $defaultifaces; do
-  run ip46tables -t mangle -A in-$iface -g mark-from-$defaultclass
+  run ip46tables -t mangle -A in-$iface -g in-default
 done
-run ip46tables -t mangle -A out-classify -g mark-to-$defaultclass
+run ip46tables -t mangle -A out-classify -g mark-to-$net_class_default
 run ip46tables -t mangle -A PREROUTING -j in-classify
 run ip46tables -t mangle -A PREROUTING -j out-classify
 
index 6756452..ee9ef90 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -21,7 +21,7 @@
 ### along with this program; if not, write to the Free Software Foundation,
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
-m4_divert(5)m4_dnl
+m4_divert(4)m4_dnl
 ###--------------------------------------------------------------------------
 ### Configuration.
 
@@ -39,14 +39,5 @@ defconf(open_port_max, 54999)
 ## Which chains to preserve.
 defconf(preserve_chains, )
 
-## Whether to permit forwarding.
-defconf(forward, 1)
-
-## Whether to turn on the reverse-path filter.
-defconf(rp_filter, 1)
-
-## Whether to turn on logging of martian packets.
-defconf(log_martians, 1)
-
 m4_divert(-1)
 ###----- That's all, folks --------------------------------------------------
index ea0fb32..05354bd 100644 (file)
--- a/fender.m4
+++ b/fender.m4
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_untrusted=eth0
-if_dmz=$if_untrusted
-if_safe=$if_dmz
-if_trusted=$if_dmz
-if_vpn=$if_dmz
-if_iodine=$if_dmz
-if_its_mz=$if_dmz
-if_its_pi=$if_dmz
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### fender-specific rules.
 
 m4_divert(82)m4_dnl
index 05decbf..d059de6 100644 (file)
@@ -58,11 +58,25 @@ defproto () {
   eval proto_$name=$number
 }
 
+## addword VAR WORD
+##
+## Adds WORD to the value of the shell variable VAR, if it's not there
+## already.  Words are separated by a single space; no leading or trailing
+## spaces are introduced.
+addword () {
+  var=$1 word=$2
+  eval val=\$$var
+  case " $val " in
+    *" $word "*) ;;
+    *) eval "$var=\${$var:+\$val }\$word" ;;
+  esac
+}
+
 m4_divert(38)m4_dnl
 ###--------------------------------------------------------------------------
 ### Utility chains (used by function definitions).
 
-m4_divert(22)m4_dnl
+m4_divert(20)m4_dnl
 ###--------------------------------------------------------------------------
 ### Basic chain constructions.
 
@@ -122,7 +136,7 @@ errorchain () {
   run ip46tables -t $table -A $chain -j DROP
 }
 
-m4_divert(24)m4_dnl
+m4_divert(20)m4_dnl
 ###--------------------------------------------------------------------------
 ### Basic option setting.
 
@@ -178,7 +192,7 @@ setdevopt () {
   done
 }
 
-m4_divert(26)m4_dnl
+m4_divert(20)m4_dnl
 ###--------------------------------------------------------------------------
 ### Packet filter construction.
 
@@ -219,7 +233,7 @@ run ip6tables -A accept-non-init-frag -j RETURN \
        -m frag --fragfirst
 run ip6tables -A accept-non-init-frag -j ACCEPT
 
-m4_divert(26)m4_dnl
+m4_divert(20)m4_dnl
 ## allowservices CHAIN PROTO SERVICE ...
 ##
 ## Add rules to allow the SERVICES on the CHAIN.
@@ -306,9 +320,30 @@ openports () {
   run ip46tables -A $chain -p udp -g interesting --destination-port $1:$2
 }
 
-m4_divert(28)m4_dnl
+m4_divert(20)m4_dnl
 ###--------------------------------------------------------------------------
 ### Packet classification.
+###
+### See `classify.m4' for an explanation of how the firewall machinery for
+### packet classification works.
+###
+### A list of all network names is kept in `allnets'.  For each network NET,
+### shell variables are defined describing their properties.
+###
+### net_class_NET      The class of the network, as defined by
+###                    `defnetclass'.
+### net_inet_NET       List of IPv4 address ranges in the network.
+### net_inet6_NET      List of IPv6 address ranges in the network.
+### net_fwd_NET                List of other networks that this one forwards to.
+### net_hosts_NET      List of hosts known to be in the network.
+### host_inet_HOST     IPv4 address of the named HOST.
+### host_inet6_HOST    IPv6 address of the named HOST.
+###
+### Similarly, a list of hosts is kept in `allhosts', and for each host HOST,
+### a shell variables are defined:
+###
+### host_ifaces_HOST   List of interfaces for this host and the networks
+###                    they attach to, in the form IFACE=NET.
 
 ## defbitfield NAME WIDTH
 ##
@@ -354,6 +389,7 @@ defnetclass () {
 
       ## Pass 1.  Establish the from_NAME and to_NAME constants, and the
       ## netclass's mask bit.
+      trace "netclass $name = $netclassindex"
       eval from_$name=$(( $netclassindex << $BIT_FROM ))
       eval to_$name=$(( $netclassindex << $BIT_TO ))
       eval _mask_$name=$(( 1 << ($netclassindex + $BIT_MASK) ))
@@ -385,91 +421,186 @@ defnetclass () {
   netclassindex=$(( $netclassindex + 1 ))
 }
 
-## defiface NAME[,NAME,...] NETCLASS:NETWORK/MASK...
-##
-## Declares network interfaces with the given NAMEs and associates with them
-## a number of reachable networks.  During source classification, a packet
-## arriving on interface NAME from an address in NETWORK/MASK is classified
-## as coming from to NETCLASS.  During destination classification, all
-## packets going to NETWORK/MASK are classified as going to NETCLASS,
-## regardless of interface (which is good, because the outgoing interface
-## hasn't been determined yet).
-##
-## As a special case, the NETWORK/MASK can be the string `default', which
-## indicates that all addresses not matched elsewhere should be considered.
-ifaces=:
-defaultifaces=""
-allnets= allnets6=
-defiface () {
-  set -e
-  names=$1; shift
-  seen=:
-  for name in $(echo $names | sed 'y/,/ /'); do
-    case $seen in *:"$name":*) continue ;; esac
-    seen=$seen$name:
-    case $ifaces in
-      *:"$name":*) ;;
-      *)
-       clearchain mangle:in-$name
-       run ip46tables -t mangle -A in-classify -i $name -g in-$name
-       ;;
+## defnet NET CLASS
+##
+## Define a network.  Follow by calls to `addr', `forwards', etc. to define
+## properties of the network.  Networks are processed in order, so if their
+## addresses overlap then the more specific addresses should be defined
+## earlier.
+defnet () {
+  net=$1 class=$2
+  addword allnets $net
+  eval net_class_$1=\$class
+}
+
+## addr ADDRESS/LEN ...
+##
+## Define addresses for the network being defined.  ADDRESSes are in
+## colon-separated IPv6 or dotted-quad IPv4 form.
+addr () {
+  for i in "$@"; do
+    case "$i" in
+      *:*) addword net_inet6_$net $i ;;
+      *) addword net_inet_$net $i ;;
     esac
-    ifaces=$ifaces$name:
-    for item; do
-      netclass=${item%:*} addr=${item#*:}
-      case $addr in
-       default)
-         case "$defaultifaces,$defaultclass" in
-           ,* | *,$netclass)
-             defaultifaces="$defaultifaces $name"
-             defaultclass=$netclass
-             ;;
-           *)
-             echo >&2 "$0: inconsistent default netclasses"
-             exit 1
-             ;;
-         esac
-         ;;
-       *:*)
-         run ip6tables -t mangle -A in-$name -g mark-from-$netclass \
-               -s $addr
-         run ip6tables -t mangle -A out-classify -g mark-to-$netclass \
-               -d $addr
-         allnets6="$allnets6 $name:$addr"
-         ;;
-       *)
-         run iptables -t mangle -A in-$name -g mark-from-$netclass \
-               -s $addr
-         run iptables -t mangle -A out-classify -g mark-to-$netclass \
-               -d $addr
-         allnets="$allnets $name:$addr"
-         ;;
-      esac
-    done
   done
 }
 
-## defvpn IFACE CLASS NET HOST:ADDR ...
+## forwards NET ...
 ##
-## Defines a VPN interface.  If the interface has the form `ROOT+' (i.e., a
-## netfilter wildcard) then define a separate interface ROOTHOST routing to
-## ADDR; otherwise just write a blanket rule allowing the whole NET.  All
-## addresses concerned are put in the named CLASS.
-defvpn () {
-  set -e
-  iface=$1 class=$2 net=$3; shift 3
-  case $iface in
-    *-+)
-      root=${iface%+}
-      for host; do
-       name=${host%%:*} addr=${host#*:}
-       defiface $root$name $class:$addr
-      done
-      ;;
-    *)
-      defiface $iface $class:$net
-      ;;
+## Declare that packets from this network are forwarded to the other NETs.
+forwards () {
+  eval "net_fwd_$net=\"$*\""
+}
+
+## noxit NET ...
+##
+## Declare that packets from this network must not be forwarded to the other
+## NETs.
+noxit () {
+  eval "net_noxit_$net=\"$*\""
+}
+
+## host HOST ADDR ...
+##
+## Define the address of an individual host on the current network.  The
+## ADDRs may be full IPv4 or IPv6 addresses, or offsets from the containing
+## network address, which is a simple number for IPv4, or a suffix beginning
+## with `::' for IPv6.  If an IPv6 base address is provided for the network
+## but not for the host then the host's IPv4 address is used as a suffix.
+host () {
+  name=$1; shift
+
+  ## Work out which addresses we've actually been given.
+  unset a6
+  for i in "$@"; do
+    case "$i" in ::*) a6=$i ;; *) a=$i ;; esac
+  done
+  case "${a+t}" in
+    t) ;;
+    *) echo >&2 "$0: no address for $name"; exit 1 ;;
   esac
+  case "${a6+t}" in t) ;; *) a6=::$a ;; esac
+
+  ## Work out the IPv4 address.
+  eval nn=\$net_inet_$net
+  for n in $nn; do
+    addr=${n%/*}
+    base=${addr%.*}
+    offset=${addr##*.}
+    case $a in *.*) aa=$a ;; *) aa=$base.$(( $offset + $a )) ;; esac
+    eval host_inet_$name=$aa
+  done
+
+  ## Work out the IPv6 address.
+  eval nn=\$net_inet6_$net
+  for n in $nn; do
+    addr=${n%/*}
+    base=${addr%::*}
+    case $a in ::*) aa=$addr$a ;; *) aa=$a ;; esac
+    eval host_inet6_$name=$aa
+  done
+
+  ## Remember the host in the list.
+  addword net_hosts_$net $name
+}
+
+## defhost NAME
+##
+## Define a new host.  Follow by calls to `iface' to define the host's
+## interfaces.
+defhost () {
+  host=$1
+  addword allhosts $host
+  eval host_type_$host=endsys
+}
+
+## router
+##
+## Declare the host to be a router, so it should forward packets and so on.
+router () {
+  eval host_type_$host=router
+}
+
+## iface IFACE NET ...
+##
+## Define a host's interfaces.  Specifically, declares that the host has an
+## interface IFACE attached to the listed NETs.
+iface () {
+  name=$1; shift
+  for net in "$@"; do
+    addword host_ifaces_$host $name=$net
+  done
+}
+
+## net_interfaces HOST NET
+##
+## Determine the interfaces on which packets may plausibly arrive from the
+## named NET.  Returns `-' if no such interface exists.
+##
+## This algorithm is not very clever.  It's just about barely good enough to
+## deduce transitivity through a simple routed network; with complicated
+## networks, it will undoubtedly give wrong answers.  Check the results
+## carefully, and, if necessary, list the connectivity explicitly; use the
+## special interface `-' for networks you know shouldn't send packets to a
+## host.
+net_interfaces () {
+  host=$1 startnet=$2
+
+  ## Determine the locally attached networks.
+  targets=:
+  eval ii=\$host_ifaces_$host
+  for i in $ii; do targets=$targets$i:; done
+
+  ## Determine the transitivity.
+  seen=:
+  nets=$startnet
+  while :; do
+
+    ## First pass.  Determine whether any of the networks we're considering
+    ## are in the target set.  If they are, then return the corresponding
+    ## interfaces.
+    found=""
+    for net in $nets; do
+      tg=$targets
+      while :; do
+       any=nil
+       case $tg in
+         *"=$net:"*)
+           n=${tg%=$net:*}; tg=${n%:*}:; n=${n##*:}
+           addword found $n
+           any=t
+           ;;
+       esac
+       case $any in nil) break ;; esac
+      done
+    done
+    case "$found" in ?*) echo $found; return ;; esac
+
+    ## No joy.  Determine the set of networks which (a) these ones can
+    ## forward to, and (b) that we've not considered already.  These are the
+    ## nets we'll consider next time around.
+    nextnets=""
+    any=nil
+    for net in $nets; do
+      eval fwd=\$net_fwd_$net
+      for n in $fwd; do
+       case $seen in *":$n:"*) continue ;; esac
+       seen=$seen$n:
+       eval noxit=\$net_noxit_$n
+       case " $noxit " in *" $startnet "*) continue ;; esac
+       case " $nextnets " in
+         *" $n "*) ;;
+         *) addword nextnets $n; any=t ;;
+       esac
+      done
+    done
+
+    ## If we've run out of networks then there's no reachability.  Return a
+    ## failure.
+    case $any in nil) echo -; return ;; esac
+    nets=$nextnets
+  done
 }
 
 m4_divert(-1)
index 1676153..4416aee 100644 (file)
--- a/gibson.m4
+++ b/gibson.m4
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_trusted=eth0
-if_dmz=$if_trusted
-if_safe=$if_dmz
-if_untrusted=$if_dmz
-if_vpn=$if_dmz
-if_iodine=$if_dmz
-if_its_mz=$if_dmz
-if_its_pi=$if_dmz
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### gibson-specific rules.
 
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        ssh \
index 2ec2c1c..93a816e 100644 (file)
--- a/ibanez.m4
+++ b/ibanez.m4
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=br-dmz
-if_trusted=br-unsafe
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### ibanez-specific rules.
 
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        ssh \
diff --git a/jem.m4 b/jem.m4
index c91a104..7db1ce5 100644 (file)
--- a/jem.m4
+++ b/jem.m4
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### jem-specific rules.
 
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
 ## Set up the SAUCE sinbin.  Unfortunately, ipset is a bit brittle.  This
 ## isn't a completely critical part of the firewall security, so don't make
 ## this fail the entire script.
index 2d880b9..b31b649 100644 (file)
--- a/local.m4
+++ b/local.m4
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
+### Local configuration.
+
+m4_divert(6)m4_dnl
+## Default NTP servers.
+defconf(ntp_servers,
+       "158.152.1.76 158.152.1.204 194.159.253.2 195.173.57.232")
+
+m4_divert(-1)
+###--------------------------------------------------------------------------
 ### Packet classification.
 
 ## Define the available network classes.
@@ -30,81 +39,164 @@ defnetclass untrusted untrusted trusted
 defnetclass trusted untrusted trusted safe noloop
 defnetclass safe trusted safe noloop
 defnetclass noloop trusted safe
-m4_divert(-1)m4_dnl
+m4_divert(-1)
 
+m4_divert(26)m4_dnl
 ###--------------------------------------------------------------------------
 ### Network layout.
 
-m4_divert(46)m4_dnl
-## Networks and routing.
-
-defiface $if_dmz \
-       trusted:62.49.204.144/28 \
-       trusted:172.29.199.0/25 \
-       untrusted:default
-defiface $if_trusted \
-       trusted:172.29.199.0/25 \
-       untrusted:default
-defiface $if_safe safe:172.29.199.192/26
-defiface $if_untrusted \
-       untrusted:172.29.198.0/25
-defvpn $if_vpn safe 172.29.199.128/27 \
-       crybaby:172.29.199.129 \
-       terror:172.29.199.130
-defiface $if_iodine untrusted:172.29.198.128/28
-defiface $if_its_mz safe:172.29.199.160/30
-defiface $if_its_pi safe:192.168.0.0/24
+## House networks.
+defnet dmz trusted
+       addr 62.49.204.144/28
+       forwards unsafe untrusted
+defnet unsafe trusted
+       addr 172.29.199.0/25
+       forwards househub
+defnet safe safe
+       addr 172.29.199.192/28
+       forwards househub
+defnet untrusted untrusted
+       addr 172.29.198.0/25
+       forwards househub
+defnet vpn safe
+       addr 172.29.199.128/27
+       forwards househub
+       host crybaby 1
+       host terror 2
+defnet iodine untrusted
+       addr 172.29.198.128/28
 
-## Default NTP servers.
-ntp_servers="158.152.1.76 158.152.1.204 194.159.253.2 195.173.57.232"
+defnet househub virtual
+       forwards housebdry dmz unsafe safe untrusted
+defnet housebdry virtual
+       forwards househub hub
+       noxit dmz
+
+## House hosts.
+defhost radius
+       router
+       iface eth0 dmz
+       iface eth1 unsafe
+       iface eth2 safe
+       iface eth3 untrusted
+defhost roadstar
+       iface eth0 dmz
+       iface eth1 unsafe
+defhost jem
+       iface eth0 dmz
+       iface eth1 unsafe
+defhost artist
+       iface eth0 dmz
+       iface eth1 unsafe
+defhost vampire
+       router
+       iface eth0.0 dmz
+       iface eth0.1 unsafe
+       iface eth0.3 untrusted
+       iface dns0 dns
+       iface vpn-+ vpn
+       iface vpn-precision colobdry vpn
+defhost ibanez
+       iface br-dmz dmz
+       iface br-unsafe unsafe
+
+defhost gibson
+       iface eth0 unsafe
+
+## Colocated networks.
+defnet jump trusted
+       addr 212.13.198.64/28
+       forwards colohub
+defnet colo trusted
+       addr 172.29.199.176/28
+       forwards colohub
+defnet colohub virtual
+       forwards colobdry jump colo
+defnet colobdry virtual
+       forwards colohub hub
+       noxit jump
 
-m4_divert(60)m4_dnl
+## Colocated hosts.
+defhost fender
+       iface br-jump jump
+       iface br-colo colo
+defhost precision
+       router
+       iface eth0 jump
+       iface eth1 colo
+       iface vpn-+ vpn
+       iface vpn-vampire housebdry vpn
+defhost telecaster
+       iface eth0 jump
+       iface eth1 colo
+defhost stratocaster
+       iface eth0 jump
+       iface eth1 colo
+defhost jazz
+       iface eth0 jump
+       iface eth1 colo
+
+## Other networks.
+defnet hub virtual
+       forwards housebdry colobdry
+defnet default untrusted
+       addr 62.49.204.144/28
+       addr 212.13.198.64/28
+       forwards dmz untrusted unsafe jump colo
+
+m4_divert(80)m4_dnl
 ###--------------------------------------------------------------------------
 ### Special forwarding exemptions.
 
-## Only allow these packets if they're not fragmented.  (Don't trust safe
-## hosts's fragment reassembly to be robust against malicious fragments.)
-## There's a hideous bug in iptables 1.4.11.1 which botches the meaning of
-## `! -f', so we do the negation using early return from a subchain.
-clearchain fwd-spec-nofrag
-run iptables -A fwd-spec-nofrag -j RETURN --fragment
-run ip6tables -A fwd-spec-nofrag -j RETURN \
-       -m ipv6header --soft --header frag
-run iptables -A FORWARD -j fwd-spec-nofrag
-
-## Allow ping from safe/noloop to untrusted networks.
-run iptables -A fwd-spec-nofrag -j ACCEPT \
-       -p icmp --icmp-type echo-request \
-       -m mark --mark $to_untrusted/$MASK_TO
-run iptables -A fwd-spec-nofrag -j ACCEPT \
-       -p icmp --icmp-type echo-reply \
-       -m mark --mark $from_untrusted/$MASK_FROM \
-       -m state --state ESTABLISHED
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
-       -p ipv6-icmp --icmpv6-type echo-request \
-       -m mark --mark $to_untrusted/$MASK_TO
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
-       -p ipv6-icmp --icmpv6-type echo-reply \
-       -m mark --mark $from_untrusted/$MASK_FROM \
-       -m state --state ESTABLISHED
-
-## Allow SSH from safe/noloop to untrusted networks.
-run iptables -A fwd-spec-nofrag -j ACCEPT \
-       -p tcp --destination-port $port_ssh \
-       -m mark --mark $to_untrusted/$MASK_TO
-run iptables -A fwd-spec-nofrag -j ACCEPT \
-       -p tcp --source-port $port_ssh \
-       -m mark --mark $from_untrusted/$MASK_FROM \
-       -m state --state ESTABLISHED
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
-       -p tcp --destination-port $port_ssh \
-       -m mark --mark $to_untrusted/$MASK_TO
-run ip6tables -A fwd-spec-nofrag -j ACCEPT \
-       -p tcp --source-port $port_ssh \
-       -m mark --mark $from_untrusted/$MASK_FROM \
-       -m state --state ESTABLISHED
-
-m4_divert(60)m4_dnl
+case $forward in
+  1)
+
+    ## Only allow these packets if they're not fragmented.  (Don't trust safe
+    ## hosts's fragment reassembly to be robust against malicious fragments.)
+    ## There's a hideous bug in iptables 1.4.11.1 which botches the meaning
+    ## of `! -f', so we do the negation using early return from a subchain.
+    clearchain fwd-spec-nofrag
+    run iptables -A fwd-spec-nofrag -j RETURN --fragment
+    run ip6tables -A fwd-spec-nofrag -j RETURN \
+           -m ipv6header --soft --header frag
+    run iptables -A FORWARD -j fwd-spec-nofrag
+
+    ## Allow ping from safe/noloop to untrusted networks.
+    run iptables -A fwd-spec-nofrag -j ACCEPT \
+           -p icmp --icmp-type echo-request \
+           -m mark --mark $to_untrusted/$MASK_TO
+    run iptables -A fwd-spec-nofrag -j ACCEPT \
+           -p icmp --icmp-type echo-reply \
+           -m mark --mark $from_untrusted/$MASK_FROM \
+           -m state --state ESTABLISHED
+    run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+           -p ipv6-icmp --icmpv6-type echo-request \
+           -m mark --mark $to_untrusted/$MASK_TO
+    run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+           -p ipv6-icmp --icmpv6-type echo-reply \
+           -m mark --mark $from_untrusted/$MASK_FROM \
+           -m state --state ESTABLISHED
+
+    ## Allow SSH from safe/noloop to untrusted networks.
+    run iptables -A fwd-spec-nofrag -j ACCEPT \
+           -p tcp --destination-port $port_ssh \
+           -m mark --mark $to_untrusted/$MASK_TO
+    run iptables -A fwd-spec-nofrag -j ACCEPT \
+           -p tcp --source-port $port_ssh \
+           -m mark --mark $from_untrusted/$MASK_FROM \
+           -m state --state ESTABLISHED
+    run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+           -p tcp --destination-port $port_ssh \
+           -m mark --mark $to_untrusted/$MASK_TO
+    run ip6tables -A fwd-spec-nofrag -j ACCEPT \
+           -p tcp --source-port $port_ssh \
+           -m mark --mark $from_untrusted/$MASK_FROM \
+           -m state --state ESTABLISHED
+
+    ;;
+esac
+
+m4_divert(80)m4_dnl
 ###--------------------------------------------------------------------------
 ### Kill things we don't understand properly.
 ###
@@ -114,12 +206,16 @@ m4_divert(60)m4_dnl
 errorchain poorly-understood REJECT
 
 ## Ban multicast destination addresses in forwarding.
-run iptables -A FORWARD -g poorly-understood \
-       -d 224.0.0.0/4
-run ip6tables -A FORWARD -g poorly-understood \
-       -d ff::/8
+case $forward in
+  1)
+    run iptables -A FORWARD -g poorly-understood \
+           -d 224.0.0.0/4
+    run ip6tables -A FORWARD -g poorly-understood \
+           -d ff::/8
+    ;;
+esac
 
-m4_divert(80)m4_dnl
+m4_divert(84)m4_dnl
 ###--------------------------------------------------------------------------
 ### Locally-bound packet inspection.
 
@@ -166,9 +262,12 @@ run ip46tables -A inbound -j forbidden
 run ip46tables -A INPUT -m mark --mark $from_untrusted/$MASK_FROM -g inbound
 
 ## Otherwise process as indicated by the mark.
-for i in INPUT FORWARD; do
-  run ip46tables -A $i -m mark ! --mark 0/$MASK_MASK -j ACCEPT
-done
+run ip46tables -A INPUT -m mark ! --mark 0/$MASK_MASK -j ACCEPT
+case $forward in
+  1)
+    run ip46tables -A FORWARD -m mark ! --mark 0/$MASK_MASK -j ACCEPT
+    ;;
+esac
 
 m4_divert(-1)
 ###----- That's all, folks --------------------------------------------------
index 4d111da..c94ae5f 100644 (file)
@@ -21,7 +21,7 @@
 ### along with this program; if not, write to the Free Software Foundation,
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
-m4_divert(25)m4_dnl
+m4_divert(24)m4_dnl
 ###--------------------------------------------------------------------------
 ### Magic numbers.
 
index 029d9f1..d698998 100644 (file)
--- a/radius.m4
+++ b/radius.m4
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This router is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=eth2
-if_untrusted=eth3
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### radius-specific rules.
 
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        ident \
index b2e3301..4947a80 100644 (file)
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This host isn't a router.
-setconf(forward, 0)
-
-## This host is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0
-if_trusted=eth1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=$if_dmz,$if_trusted
-if_vpn=$if_dmz,$if_trusted
-if_iodine=$if_dmz,$if_trusted
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### roadstar-specific rules.
 
-m4_divert(82)m4_dnl
+m4_divert(84)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        ssh \
index 2cf1a13..44eef03 100644 (file)
 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ###--------------------------------------------------------------------------
-### Config settings.
-
-## This router is involved in a routing asymmetry.
-setconf(rp_filter, 0)
-setconf(log_martians, 0)
-
-###--------------------------------------------------------------------------
-### Network interfaces.
-
-m4_divert(44)m4_dnl
-## Interface definitions.
-if_dmz=eth0.0
-if_trusted=eth0.1
-if_safe=$if_dmz,$if_trusted
-if_untrusted=eth0.3
-if_vpn=vpn-+
-if_iodine=dns+
-if_its_mz=$if_dmz,$if_trusted
-if_its_pi=$if_dmz,$if_trusted
-
-m4_divert(-1)
-###--------------------------------------------------------------------------
 ### vampire-specific rules.
 
-m4_divert(82)m4_dnl
+m4_divert(86)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        finger ident \
@@ -102,7 +80,7 @@ run iptables -t nat -F
 run iptables -t nat -X
 
 run iptables -t nat -N outbound
-run iptables -t nat -A outbound -j RETURN ! -o $if_dmz
+run iptables -t nat -A outbound -j RETURN ! -o eth0.0
 run iptables -t nat -A outbound -j RETURN ! -s 172.29.198.0/23
 run iptables -t nat -A outbound -j RETURN -d 62.49.204.144/28
 run iptables -t nat -A outbound -j RETURN -d 172.29.198.0/23