我目前已让 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