IP 表可以允许基于域名的特定 DNS 查询吗?

IP 表可以允许基于域名的特定 DNS 查询吗?

我目前已让 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没有成功。

如果有人知道该怎么做或者知道我哪里做错了?

答案1

DNS 查询中的点“.”不表示为字符,而是表示后面字符串的长度。例如,www.google.com 的查询方式为

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

您可以通过将域名与 --hex-string 匹配来轻松允许/阻止 DNS 查询。对于您的情况:

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

将接受每个包含“ .google.com”的 DNS 数据包。

我经常使用这种技术来对抗DNS查询放大攻击。

来源:DNS RFC 1035

答案2

为了补充 nrc 的答案,这里有一个将域转换为十六进制字符串的快速命令:

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

答案3

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

相关内容