3

I have iptables blocking all UDP traffic at the moment, however I want to allow only certain DNS queries to get through.

Let's use google.com as an example.

I am trying to use string matching to find the domain name in the request, and allow it. This is what I came up with.

iptables -A OUTPUT -o eth0 -p udp --sport 53 -m string --string "google.com" --algo bm -j ACCEPT

I have also tried --dport 53 instead of --sport. No dice.

If anyone knows how this can be done or see's where I went wrong?

Khaled
  • 36,533
  • 8
  • 72
  • 99
Jarred Kenny
  • 31
  • 1
  • 2
  • Post the output of iptables -L -n -v – dmourati Dec 31 '12 at 06:43
  • @Jarred Kenny: This usage of string matching in iptables is not accurate. Why do you need to do this? Are you trying to block some websites? – Khaled Dec 31 '12 at 08:14
  • Why dont you give access to only required authoritative DNS servers ?? i.e. ns[1-4].google.com in this case – Garfield Carneiro Dec 31 '12 at 07:11
  • @Khaled The server connects to a VPN at book. I am writing these rules to prevent any DNS queries being sent over the regular eth0. This rule is an attempt to only allow the DNS queries related to the VPN provider. For example, I only want DNS queries to resolve for *.vpncompany.com domain names. Once the VPN is connected, DNS queries get piped via the tun- interface and the rule is not relevant. It is just a precaution. – Jarred Kenny Dec 31 '12 at 12:20
  • 3
    You'd probably be better off installing a local DNS server on the machine with selective forwarding. E.g. disable recursion _except_ for zone vpncompany.com. – James O'Gorman Dec 31 '12 at 18:59

3 Answers3

2

the dot "." in a DNS query is not represented as a character, but as the length of the string that follows. For example www.google.com is queried as

0x03 w w w 0x06 g o o g l e 0x03 c o m

you can easily allow/block DNS queries by matching the domain names with --hex-string. In your case:

-m string --algo bm --hex-string '|06 676f6f676c65 03 636f6d|' -j ACCEPT

will accept every DNS packet containing ".google.com".

I often use this technique against the DNS query amplification attack.

source: DNS RFC 1035

nrc
  • 1,161
  • 8
  • 8
2

To complement nrc's anwser, where is a quick command to convert domains to the hexadecimal string:

DOMAIN=google.com
perl -e 'print map {chr(length($_)).$_} split /\./, "'$DOMAIN'" | xxd -p

So, in your case:

DOMAIN=google.com
HEX=$(perl -e 'print map {chr(length($_)).$_} split /\./, "'$DOMAIN'"' | xxd -p)

iptables -A OUTPUT -o eth0 -p udp --sport 53 \
  -m string --hex-string "|$HEX|" --algo bm -j ACCEPT
Romuald Brunet
  • 181
  • 1
  • 4
0
DOMAIN=www.example.com
str=$(perl -e 'print "|".join("|", map { sprintf("%02X", length($_))."|".$_ }  split(/\./, "'$DOMAIN'") )."|"')
echo $str
iptables -I INPUT -p udp --dport 53 -m string --hex-string "$str" --algo bm -j ACCEPT

Output:

|03|www|07|example|03|com|
iptables -I INPUT -p udp --dport 53 -m string --hex-string "$str" --algo bm -j ACCEPT
Iceberg
  • 141
  • 2