Took a while to figure out how to mitigate the 53 DDoS.
Basically my situation was I could not stop the incoming flood traffic, well guess what …? iptables string-match rules can be used as a last resort. Keep in mind that string matching is resource-intensive and may slow down your network speed and your servers btw… however if you need to shut out an attack, this option is better than letting your server continue to answer the abusive queries to port 53
so the first thing I did was get a hex-dump of the packets I wished to block. tcpdumping them out
tcp6dump -c10 -pntxi eth0 not udp src port 53 and udp dst port 53
The option -c10 specifies that you only want to dump out 10 packets at a time from port 53 only looking at input.
I was seeing this bullshit
IP [05e9:3aa4:3230:86b9:0737:5c22:13ff:f2ad].59174 > [2600:3c04:0:0:f03c:92ff:fec6:2030].53: 92732+ [1au] ANY? . (28)
0x0000: 4500 0038 a48c 0000 f111 4e02 4509 64f2
0x0010: d857 54d3 e2f4 0035 0024 0000 aa3d 0100
0x0020: 0001 0000 0000 0001 0000 66ff 0432 1189
0x0030: 5348 0000 0000 0000
IP [05e9:3aa4:3230:86b9:0737:5c22:13ff:f2ad].16326 > [2600:3c04:0:0:f03c:92ff:fec6:2030].53: 92733+ [1au] ANY? . (28)
0x0000: 4500 0038 d50a 0000 f111 2220 636c 41f3
0x0010: d857 54d3 4700 0035 0024 0000 9f8b 0100
0x0020: 0001 0000 0000 0001 0000 66ff 0432 1189
0x0030: 5348 0000 0000 0000
Guess what theres a common conseutive set of bytes here… 0000 0001 0000 66ff 0432 1189 5348 0000
so the iptables rule, you want to remove all the spaces between bytes, and drop the results into a rule like this:
iptables -I INPUT -p udp -m string --hex-string "|0000000000066ff0432118953480000|" --algo bm --dport 53 -j DROP
BINGO Running this rule will immediately shut out all matching queries, preventing your server from wasting time and bandwidth trying to answer them.
The next steps were basic
Establish throttling:
iptables -A INPUT -p udp -m hashlimit --hashlimit-srcmask 24 --hashlimit-mode srcip --hashlimit-upto 120/m --hashlimit-burst 30 --hashlimit-name DNSTHROTTLE --dport 53 -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 53 -j DROP
iptables -A INPUT -p udp -m string --hex-string "|00000000000103697363036f726700|" --algo bm --to 65535 --dport 53 -j DROP
iptables -A INPUT -p udp -m string --hex-string "|0000000000010472697065036e6574|" --algo bm --to 65535 --dport 53 -j DROP
iptables -I INPUT -p udp -m string --hex-string "|0000000000066ff0432118953480000|" --algo bm --dport 53 -j DROP
iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --set --name dnsanyquery
iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --rcheck --seconds 60 --hitcount 4 -j DROP
Disclaimer: *You should always apply to INPUT before FORWARD or OUTPUT
Floods BTFOd
Specific series updated: Infrastructure Series -- Taking DNS One Step Further - Full DNS Server infrastructure - #2 by PhaseLockedLoop