На данный момент у меня есть iptables, блокирующие весь UDP-трафик, однако я хочу разрешить прохождение только определенных DNS-запросов.
В качестве примера возьмем google.com.
Я пытаюсь использовать сопоставление строк, чтобы найти доменное имя в запросе и разрешить его. Вот что я придумал.
iptables -A OUTPUT -o eth0 -p udp --sport 53 -m string --string "google.com" --algo bm -j ACCEPT
Я тоже пробовал --dport 53
вместо того --sport
. Никаких кубиков.
Если кто-нибудь знает, как это можно сделать, или посмотрите, где я ошибся?
точка "." в запросе DNS не представлен как символ, а как длина следующей за ним строки. Например, www.google.com запрашивается как
0x03 w w w 0x06 g o o g l e 0x03 c o m
вы можете легко разрешить / заблокировать DNS-запросы, сопоставив имена доменов с помощью --hex-string. В твоем случае:
-m string --algo bm --hex-string '|06 676f6f676c65 03 636f6d|' -j ACCEPT
примет каждый пакет DNS, содержащий ".google.com".
Я часто использую эту технику против атаки с усилением DNS-запросов.
источник: DNS RFC 1035
В дополнение к nrc anwser, где есть быстрая команда для преобразования доменов в шестнадцатеричную строку:
DOMAIN=google.com
perl -e 'print map {chr(length($_)).$_} split /\./, "'$DOMAIN'" | xxd -p
Итак, в вашем случае:
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
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
Вывод:
|03|www|07|example|03|com|
iptables -I INPUT -p udp --dport 53 -m string --hex-string "$str" --algo bm -j ACCEPT