Rate limiting for incoming DNS queries over UDP.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 8 Jun 2012 00:51:05 +0000 (01:51 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 8 Jun 2012 00:51:05 +0000 (01:51 +0100)
We provide DNSsec-signed responses, and could be used as a DDoS
amplifier.  Apply rate-limiting to incoming traffic to mitigate this
effect.

This should be removed if and when BIND acquires its own more
intelligent rate-limiting.

bookends.m4
functions.m4
precision.m4
radius.m4
vampire.m4

index 807e8d9..699a966 100644 (file)
@@ -177,6 +177,10 @@ errorchain bad-source-address DROP
 ## Packet arrived on wrong interface for its source address.  Drops the
 ## packet, since there's nowhere sensible to send an error.
 
+errorchain dns-rate-limit DROP
+## Dropped incoming DNS query due to rate limiting.  The source address is
+## suspicious, so don't produce ICMP.
+
 errorchain bad-destination-address REJECT
 ## Packet arrived on non-loopback interface with loopback destination.
 
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.
index f5c07ac..598a990 100644 (file)
@@ -28,14 +28,13 @@ m4_divert(86)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        ident \
-       dns \
        ssh
 allowservices inbound udp \
-       dns \
        tripe
 
 ## Other interesting things.
 dnsresolver inbound
+dnsserver inbound
 
 m4_divert(-1)
 ###----- That's all, folks --------------------------------------------------
index ecf64b7..180b8ac 100644 (file)
--- a/radius.m4
+++ b/radius.m4
@@ -28,19 +28,10 @@ m4_divert(86)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        ident \
-       dns iodine \
        ssh
 allowservices inbound udp \
-       dns iodine \
        tripe
 
-## Provide DNS resolution to local untrusted hosts.
-for p in tcp udp; do
-  run iptables -A inbound -j ACCEPT \
-         -s 172.29.198.0/24 \
-         -p $p --destination-port $port_dns
-done
-
 ## Provide syslog for evolution.
 run iptables -A inbound -j ACCEPT \
        -s 172.29.198.2 \
@@ -48,6 +39,7 @@ run iptables -A inbound -j ACCEPT \
 
 ## Other interesting things.
 dnsresolver inbound
+dnsserver inbound
 
 ## IPv6 6-in-4 tunnel.
 run iptables -A inbound -j ACCEPT \
index b3257c7..3fb9595 100644 (file)
@@ -28,7 +28,6 @@ m4_divert(86)m4_dnl
 ## Externally visible services.
 allowservices inbound tcp \
        finger ident \
-       dns iodine \
        ssh \
        smtp submission \
        gnutella_svc \
@@ -40,7 +39,6 @@ allowservices inbound tcp \
        git \
        tor_public tor_directory i2p
 allowservices inbound udp \
-       dns iodine \
        tripe \
        gnutella_svc \
        i2p
@@ -68,6 +66,7 @@ run iptables -A OUTPUT -m multiport \
 
 ## Other interesting things.
 dnsresolver inbound
+dnsserver inbound
 ntpclient inbound $ntp_servers
 
 m4_divert(-1)