6

I have been working on building a rule set to detect and block a DNS amplification attack.

I got stuck and am hoping to find help here.

I'll post here what I have (bash scripting, the portions that concern DNS):

IPTABLES='/sbin/iptables -v' 
SERVERIP=a.b.c.d

echo '################ Previously initiated and accepted exchanges bypass rule checking #'
$IPTABLES --append INPUT  -m state --state ESTABLISHED,RELATED     --jump ACCEPT
echo '################################################ Allow unlimited outbound traffic #'
$IPTABLES --append OUTPUT -m state --state NEW,ESTABLISHED,RELATED --jump ACCEPT

echo '################################################################## Rules for DNS #'
# DIG ANY ISC.ORG attack preventer.
# QUESTION1: this one does not work, why!?!?
$IPTABLES --append INPUT --proto udp --dport 53 -m string --string "isc.org" --algo bm --to 65535 --jump LOG --log-prefix "iptables: UDP ISC0 "

$IPTABLES --append INPUT --proto udp --dport 53 -m string --hex-string "|03697363036f726700|" --algo bm --to 65535 --jump LOG --log-prefix "iptables: UDP ISC "
$IPTABLES --append INPUT --proto udp --dport 53 -m string --hex-string "|03697363036f726700|" --algo bm --to 65535 --jump DROP

# DNS DNSIPSOK list
$IPTABLES --new DNSFLOODRULES
$IPTABLES --append DNSFLOODRULES --source 127.0.0.1 --jump RETURN
$IPTABLES --append DNSFLOODRULES --source $SERVERIP --jump RETURN
$IPTABLES --append DNSFLOODRULES --jump LOG --log-prefix "iptables: UDP BLOCK "
$IPTABLES --append DNSFLOODRULES --jump ACCEPT
#$IPTABLES --append DNSFLOODRULES --jump DROP
# I have it turned off right now, because 

echo '# S & D port rules'
# DNS limit rule for standard acceptance
# QUESTION2: can't get the connbytes to work properly :(
$IPTABLES --append INPUT --proto udp --source 0/0 --dport 53 \
    -m state --state NEW \
    -m connbytes --connbytes 75 --connbytes-dir reply --connbytes-mode bytes
    -m limit --limit 1/s --limit-burst 10 --jump ACCEPT 
# DNS log / drop the abusers EXEPT the whitelisted IP numbers
$IPTABLES --append INPUT --proto udp --source 0/0 --dport 53 -m state --state NEW --jump DNSFLOODRULES
$IPTABLES --append INPUT --proto udp --source 0/0 --sport 53 -m state --state NEW --jump DNSFLOODRULES
# DNS allow the whitelisted IP numbers
$IPTABLES --append INPUT --proto udp --source 0/0 --dport 53 -m state --state NEW --jump ACCEPT
$IPTABLES --append INPUT --proto udp --source 0/0 --sport 53 -m state --state NEW --jump ACCEPT

QUESTION1: Why does it need to be the hex-string, the plain one would be easier to maintain, but that one won't byte, can you tell my why?

QUESTION2: Via TCPdump I can see that most of the answers are quite small, thus they need to be whitelisted. Also localhost (and a few of my own servers my query the name server extensively (DNSFLOODRULES). The DNS amplification attack is a continuous surge of "large" answers, those I want to limit. The problem is I can't get the 'connbytes' part to work. I've been fumbling around with it quite a bit, also thinking it should be art of OUTPUT, since it is about the size of the answer, not the question. I also experimented with the 'Allow unlimited outbound traffic' part, but that went horribly wrong.

Your thoughts and help are much appreciated.

3
  • 4
    Any Netfilter module with state is very dangerous when there is a DoS attack because the attacker can eat all your memory. I suggest instead that you see lists.dns-oarc.net/pipermail/dns-operations/2012-October/…
    – bortzmeyer
    Feb 5, 2013 at 21:32
  • @bortzmeyer, when there's a DoS attack it's worth remembering it's named "an attack" due to it hurts, in a way. ;-P
    – poige
    Mar 24, 2013 at 14:51
  • If your doing only authoritative resolution just set your dns to recursion no
    – Marcel
    Apr 5, 2013 at 22:08

1 Answer 1

1

Question 1:

The string does not match because the the "." is not included in the packet. A DNS packet does not contain a "hostname" as such but "labels". In the packet, every part of the domain name is a label, prefixed by the number of bytes for the label.

So "isc.org" translates to:

isc: 03 69 73 63
org: 03 6f 72 67

Or in the packet:

03697363036f7267

Every label is limited to 63 bytes, the whole name is limited to 255 bytes.

It's explained in the DNS RFC:

https://www.rfc-editor.org/rfc/rfc1035#section-2.3.4

https://www.rfc-editor.org/rfc/rfc1035#section-4.1.2

Question 2:

You need to enable the net.netfilter.nf_conntrack_acct flag to use the conntrack option (see iptables manpage). But I don't think it's wise to use it like that. There will always be legitimate answers that are large packets.

Perhaps you're better off using the hashlimit extension. It was already mentioned:

https://lists.dns-oarc.net/pipermail/dns-operations/2012-October/009321.html

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .