On 27/07/2021 02:43, Tom wrote:
If you run a DNS server you've likely come across lots of requests for
RRSIGs of pizzaseo.com. It's a DDOS attack that's been going on for
years, off and on. Currently it's on, and how! Thousands of requests an
hour for weeks now on all 3 of my DNS servers. Instead of using fail2ban
to block the offending IP addresses, I want to drop the packet before it
gets to the DNS server.
I know there is a way for nftables to examine table header strings of
UDP packets using something called a "raw payload expression". You need
the hex equivalent of the string, and the beginning and end offsets of
the string, for example:
meta l4proto udp udp dport 53 @th,160,120
0x0970726f787970697065036e657400 counter drop comment "block queries for
proxypipe.net"
If I wanted to block pizzaseo.com (and I'm far from alone in this
request!), how do I convert that string to a 0x string? How do I check
that I have the right start and offset? How would I debug such a rule?
Thanks in advance!
Let us begin with `tcpdump -n -s0 -X udp port 53`. Here is the payload
of an offending query, including the encapsulating IPv4 header.
0x0000: 4528 003a bb51 0000 f211 3319 4bad 43f9 E(.:.Q....3.K.C.
0x0010: c422 8657 0035 0035 0026 0000 0001 0100 .".W.5.5.&......
0x0020: 0001 0000 0000 0000 0870 697a 7a61 7365 .........pizzase
0x0030: 6f03 636f 6d00 002e 0001 o.com....
In this case, the IPv4 header is 20 bytes long, with the UDP payload
thus beginning at offset 20, or 0x14 in hex.
$ printf '%x\n' 20 # decimal to hex
14
Note that the first two words following from this offset each have a
value of 0x35, indicating a source and destination port of 53.
$ echo $(( 0x35 )) # hex to decimal
53
At offset 0x28, an interesting payload of 13 bytes worth is observable.
08 70 69 7a 7a 61 73 65 6f 03 63 6f 6d
p i z z a s e o c o m
Note that the first value of this sequence is 0x08, denoting that the 8
characters of "pizzaseo" follow. Likewise, 0x03 for the three letters of
"com".
Knowing that the length of the captured IPv4 header must be subtracted
from the observed offset of 0x28, that the payload to be matched is 13
bytes in length, and that there are 8 bits in a byte, we are now in a
position to perform the necessary calculations.
# printf '@th,%d,%d\n' $(( (0x28 - 20) * 8 )) $(( 13 * 8 ))
@th,160,104
All that remains is to incorporate this into a rule, along with the
necessary hex sequence to be matched.
udp dport 53 @th,160,104 0x0870697a7a6173656f03636f6d counter drop
Ideally, you would debug such a rule by having your DNS server log the
manner in which it is responding to these requests. For example, I
operate an authoritative BIND server that does not honour recursive
queries issued by the general public. In the case that a query is
refused, BIND logs a message to that effect. After adding the rule, I
could see that no new messages pertaining to pizzaseo.com were being logged.
--
Kerin Millar