Rate limiting for incoming DNS queries over UDP.
[firewall] / functions.m4
index c3609a5..03f6af5 100644 (file)
@@ -94,12 +94,12 @@ ip46tables () {
 ## 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
 }
 
@@ -310,6 +310,26 @@ dnsresolver () {
   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.