## Ensure that the named chains exist and are empty.
clearchain () {
set -e
- for chain; do
- case $chain in
- *:*) table=${chain%:*} chain=${chain#*:} ;;
+ for _chain; do
+ case $_chain in
+ *:*) table=${_chain%:*} _chain=${_chain#*:} ;;
*) table=filter ;;
esac
- run ip46tables -t $table -N $chain 2>/dev/null || :
+ run ip46tables -t $table -N $_chain 2>/dev/null || :
done
}
done
}
+## dnsserver CHAIN
+##
+## Add rules to allow CHAIN to be a DNS server.
+dnsserver () {
+ set -e
+ chain=$1
+
+ ## Allow TCP access. Hitting us with SYNs will make us deploy SYN cookies,
+ ## but that's tolerable.
+ run ip46tables -A $chain -j ACCEPT -p tcp --destination-port 53
+
+ ## Avoid being a DDoS amplifier by rate-limiting incoming DNS queries.
+ clearchain $chain-udp-dns
+ run ip46tables -A $chain-udp-dns -j ACCEPT \
+ -m limit --limit 20/second --limit-burst 300
+ run ip46tables -A $chain-udp-dns -g dns-rate-limit
+ run ip46tables -A $chain -j $chain-udp-dns \
+ -p udp --destination-port 53
+}
+
## openports CHAIN [MIN MAX]
##
## Add rules to CHAIN to allow the open ports.