prologue.m4: Use iptables-{save,restore} for the molly-guard.
[firewall] / functions.m4
index 680df6d..523c42a 100644 (file)
@@ -1,4 +1,4 @@
-### -*-m4-*-
+### -*-sh-*-
 ###
 ### Utility functions for firewall scripts
 ###
@@ -54,6 +54,15 @@ m4_divert(22)m4_dnl
 ###--------------------------------------------------------------------------
 ### Basic chain constructions.
 
+## ip46tables ARGS ...
+##
+## Do the same thing for `iptables' and `ip6tables'.
+ip46tables () {
+  set -e
+  iptables "$@"
+  ip6tables "$@"
+}
+
 ## clearchain CHAIN CHAIN ...
 ##
 ## Ensure that the named chains exist and are empty.
@@ -64,7 +73,7 @@ clearchain () {
       *:*) table=${chain%:*} chain=${chain#*:} ;;
       *) table=filter ;;
     esac
-    run iptables -t $table -N $chain
+    run ip46tables -t $table -N $chain
   done
 }
 
@@ -80,10 +89,10 @@ errorchain () {
     *) table=filter ;;
   esac
   clearchain $table:$chain
-  run iptables -t $table -A $chain -j LOG \
+  run ip46tables -t $table -A $chain -j LOG \
          -m limit --limit 3/minute --limit-burst 10 \
          --log-prefix "fw: $chain " --log-level notice
-  run iptables -t $table -A $chain -j "$@"
+  run ip46tables -t $table -A $chain -j "$@"
 }
 
 m4_divert(24)m4_dnl
@@ -121,9 +130,9 @@ m4_divert(26)m4_dnl
 conntrack () {
   set -e
   chain=$1
-  run iptables -A $chain -p tcp -m state \
+  run ip46tables -A $chain -p tcp -m state \
          --state ESTABLISHED,RELATED -j ACCEPT
-  run iptables -A $chain -p tcp ! --syn -g bad-tcp
+  run ip46tables -A $chain -p tcp ! --syn -g bad-tcp
 }
 
 ## commonrules CHAIN
@@ -138,6 +147,10 @@ commonrules () {
   ## fragmented.
   run iptables -A $chain -p tcp -f -g tcp-fragment
   run iptables -A $chain -f -j ACCEPT
+  run ip6tables -A $chain -p tcp -g tcp-fragment \
+         -m ipv6header --soft --header frag
+  run ip6tables -A $chain -j ACCEPT \
+         -m frag ! --fragfirst
 }
 
 ## allowservices CHAIN PROTO SERVICE ...
@@ -170,7 +183,7 @@ allowservices () {
     esac
     count=$(( $count + $n ))
     if [ $count -gt 15 ]; then
-      run iptables -A $chain -p $proto -m multiport -j ACCEPT \
+      run ip46tables -A $chain -p $proto -m multiport -j ACCEPT \
             --destination-ports ${list#,}
       list= count=$n
     fi
@@ -180,11 +193,11 @@ allowservices () {
     "")
       ;;
     ,*,*)
-      run iptables -A $chain -p $proto -m multiport -j ACCEPT \
+      run ip46tables -A $chain -p $proto -m multiport -j ACCEPT \
              --destination-ports ${list#,}
       ;;
     *)
-      run iptables -A $chain -p $proto -j ACCEPT \
+      run ip46tables -A $chain -p $proto -j ACCEPT \
              --destination-port ${list#,}
       ;;
   esac
@@ -209,7 +222,7 @@ dnsresolver () {
   set -e
   chain=$1
   for p in tcp udp; do
-    run iptables -A $chain -j ACCEPT \
+    run ip46tables -A $chain -j ACCEPT \
             -m state --state ESTABLISHED \
             -p $p --source-port 53
   done
@@ -222,8 +235,8 @@ openports () {
   set -e
   chain=$1; shift
   [ $# -eq 0 ] && set -- $open_port_min $open_port_max
-  run iptables -A $chain -p tcp -g interesting --destination-port $1:$2
-  run iptables -A $chain -p udp -g interesting --destination-port $1:$2
+  run ip46tables -A $chain -p tcp -g interesting --destination-port $1:$2
+  run ip46tables -A $chain -p udp -g interesting --destination-port $1:$2
 }
 
 m4_divert(28)m4_dnl
@@ -298,8 +311,8 @@ defnetclass () {
 
       ## Now establish the mark-from-NAME and mark-to-NAME chains.
       clearchain mangle:mark-from-$name mangle:mark-to-$name
-      run iptables -t mangle -A mark-from-$name -j MARK --set-mark $from
-      run iptables -t mangle -A mark-to-$name -j MARK --and-mark $to
+      run ip46tables -t mangle -A mark-from-$name -j MARK --set-mark $from
+      run ip46tables -t mangle -A mark-to-$name -j MARK --and-mark $to
       ;;
   esac
   netclassindex=$(( $netclassindex + 1 ))
@@ -319,7 +332,7 @@ defnetclass () {
 ## indicates that all addresses not matched elsewhere should be considered.
 ifaces=:
 defaultiface=none
-allnets=
+allnets= allnets6=
 defiface () {
   set -e
   name=$1; shift
@@ -327,7 +340,7 @@ defiface () {
     *:"$name":*) ;;
     *)
       clearchain mangle:in-$name
-      run iptables -t mangle -A in-classify -i $name -g in-$name
+      run ip46tables -t mangle -A in-classify -i $name -g in-$name
       ;;
   esac
   ifaces=$ifaces$name:
@@ -337,7 +350,12 @@ defiface () {
       default)
        defaultiface=$name
        defaultclass=$netclass
-       run iptables -t mangle -A out-classify -g mark-to-$netclass
+       run ip46tables -t mangle -A out-classify -g mark-to-$netclass
+       ;;
+      *:*)
+       run ip6tables -t mangle -A in-$name -s $addr -g mark-from-$netclass
+       run ip6tables -t mangle -A out-classify -d $addr -g mark-to-$netclass
+       allnets6="$allnets6 $name:$addr"
        ;;
       *)
        run iptables -t mangle -A in-$name -s $addr -g mark-from-$netclass
@@ -361,7 +379,7 @@ defvpn () {
     *-+)
       root=${iface%+}
       for host; do
-       name=${host%:*} addr=${host#*:}
+       name=${host%%:*} addr=${host#*:}
        defiface $root$name $class:$addr
       done
       ;;