makeset () {
set -e
name=$1; shift
- if ipset -nL | grep -q "^Name: $name$"; then
- :
- else
- ipset -N "$name" "$@"
- fi
+ v=$(ipset --version)
+ createp=t
+ case "$v" in
+ "ipset v4"*)
+ if ipset -nL | grep -q "^Name: $name\$"; then createp=nil; fi
+ ;;
+ *)
+ if ipset -n -L | grep -q "^$name\$"; then createp=nil; fi
+ ;;
+ esac
+ case $createp in
+ t) ipset -N "$name" "$@" ;;
+ esac
}
## errorchain CHAIN ACTION ARGS ...
clearchain $table:$chain
run ip46tables -t $table -A $chain -j LOG \
-m limit --limit 3/minute --limit-burst 10 \
- --log-prefix "fw: $chain " --log-level notice
+ --log-prefix "fw: $chain " --log-level notice || :
run ip46tables -t $table -A $chain -j "$@" \
-m limit --limit 20/second --limit-burst 100
run ip46tables -t $table -A $chain -j DROP
run ip6tables -N accept-non-init-frag
run ip6tables -A accept-non-init-frag -j RETURN \
-m frag --fragfirst
-run ip6tables -A accept-non-init-frag -j ACCEPT
+run ip6tables -A accept-non-init-frag -j ACCEPT \
+ -m ipv6header --header frag
m4_divert(20)m4_dnl
## allowservices CHAIN PROTO SERVICE ...
ntpchain=$1; shift
clearchain ntp-servers
- for ntp; do run iptables -A ntp-servers -j ACCEPT -s $ntp; done
- run iptables -A $ntpchain -j ntp-servers \
+ for ntp; do
+ case $ntp in *:*) ipt=ip6tables ;; *) ipt=iptables ;; esac
+ run $ipt -A ntp-servers -j ACCEPT -s $ntp;
+ done
+ run ip46tables -A $ntpchain -j ntp-servers \
-p udp --source-port 123 --destination-port 123
}
run ip46tables -A $chain -p udp -g interesting --destination-port $1:$2
}
+bcp38_setup=:
+bcp38 () {
+ ipv=$1 ifname=$2; shift 2
+ ## Add rules for BCP38 egress filtering for IP version IPV (either 4 or 6).
+ ## IFNAME is the outgoing interface; the remaining arguments are network
+ ## prefixes.
+
+ ## Sort out which command we're using
+ case $ipv in
+ 4) ipt=iptables ;;
+ 6) ipt=ip6tables ;;
+ *) echo >&2 "Unknown IP version $ipv"; exit 1 ;;
+ esac
+
+ ## If we've not set up the error chain then do that.
+ case $bcp38_setup in
+ :)
+ errorchain bcp38 DROP
+ clearchain bcp38-check
+ ip46tables -A bcp38-check -g bcp38
+ ;;
+ esac
+
+ ## Stitch our egress filter into the outbound chains if we haven't done
+ ## that yet. Do this for both IP versions: if we're only ever given
+ ## IPv6 addresses for a particular interface then we assume that IPv4
+ ## packets aren't allowed on it at all.
+ case $bcp38_setup in
+ *:$ifname:*) ;;
+ *)
+ run ip46tables -A OUTPUT -j bcp38-check -o $ifname
+ case $forward in
+ 1) run ip46tables -A FORWARD -j bcp38-check -o $ifname ;;
+ esac
+ bcp38_setup=$bcp38_setup$ifname:
+ ;;
+ esac
+
+ ## Finally, add in our allowed networks.
+ for i in "$@"; do
+ run $ipt -I bcp38-check -j RETURN -s $i
+ done
+}
+
m4_divert(20)m4_dnl
###--------------------------------------------------------------------------
### Packet classification.
### `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_via_NET List of other networks that this one forwards via.
### 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.
from=$(( $from + $bit ))
done
to=$(( ($netclassindex << $BIT_TO) ))
- tomask=$(( $MASK_MASK ^ (1 << ($netclassindex + $BIT_MASK)) ))
+ tomask=$(( $MASK_TO | $MASK_MASK ^ (1 << ($netclassindex + $BIT_MASK)) ))
trace "from $name --> set $(printf %08x/%08x $from $frommask)"
- trace " to $name --> and $(printf %08x/%08x $to $tomask)"
+ trace " to $name --> set $(printf %08x/%08x $to $tomask)"
## Now establish the mark-from-NAME and mark-to-NAME chains.
clearchain mangle:mark-from-$name mangle:mark-to-$name
## defnet NET CLASS
##
-## Define a network. Follow by calls to `addr', `forwards', etc. to define
+## Define a network. Follow by calls to `addr', `via', 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.
done
}
-## forwards NET ...
+## via NET ...
##
## Declare that packets from this network are forwarded to the other NETs.
-forwards () {
- eval "net_fwd_$net=\"$*\""
+via () {
+ eval "net_via_$net=\"$*\""
}
## noxit NET ...
done
}
+## matchnets OPT WIN FLAGS PREPARE BASE SUFFIX NEXT NET [NET ...]
+##
## Build rules which match a particular collection of networks.
+##
## Specifically, use the address-comparison operator OPT (typically `-s' or
-## `-d') to match the addresses of NOT, writing the rules to the chain
-## BASESUFFIX. If we find a match, dispatch to WIN-CLASS, where CLASS is
-## the class of the matching network. In order to deal with networks
-## containing negative address ranges, more chains may need to be
-## constructed; they will be named BASE#Q for sequence numbers Q starting
-## with NEXT. All of this happens on the `mangle' table, and there isn't
-## (currently) a way to tweak this.
+## `-d') to match the addresses of each NET, writing the rules to the chain
+## BASESUFFIX. If we find a match, dispatch to WIN-CLASS, where CLASS is the
+## class of the matching network. In order to deal with networks containing
+## negative address ranges, more chains may need to be constructed; they will
+## be named BASE#Q for sequence numbers Q starting with NEXT. All of this
+## happens on the `mangle' table, and there isn't (currently) a way to tweak
+## this.
##
## The FLAGS gather additional interesting information about the job,
## separated by colons. The only flag currently is :default: which means
nextnets=""
any=nil
for net in $nets; do
- eval fwd=\$net_fwd_$net
- for n in $fwd; do
+ eval via=\$net_via_$net
+ for n in $via; do
case $seen in *":$n:"*) continue ;; esac
seen=$seen$n:
eval noxit=\$net_noxit_$n