如何使用 iptables 过滤 DNS 请求

如何使用 iptables 过滤 DNS 请求

我正在尝试过滤来自本地网络的 DNS 请求。仅授权对特定 DNS 的请求并拒绝其余的请求,但这对我来说不起作用。这是我的规则(以 dns google 为例):

internal=enp2s1
external=enp2s0

iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

echo 1 > /proc/sys/net/ipv4/ip_forward # default 0
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6 # default 0
echo 1 > /proc/sys/net/ipv6/conf/default/disable_ipv6 # default 0
echo 1 > /proc/sys/net/ipv6/conf/lo/disable_ipv6 # default 0

iptables -A INPUT -p all -i lo -j ACCEPT
iptables -A INPUT -s 192.168.0.10 -j ACCEPT
iptables -A OUTPUT -p all -o lo -j ACCEPT
iptables -A OUTPUT -p all -s 127.0.0.1 -j ACCEPT
iptables -t mangle -A PREROUTING -p all -i lo -j ACCEPT
iptables -t mangle -A PREROUTING -p all -s 127.0.0.1 -j ACCEPT
iptables -t nat -A PREROUTING -p all -i lo -j ACCEPT
iptables -t mangle -A PREROUTING -i lo -s 127.0.0.0/8 -j ACCEPT
iptables -t mangle -A PREROUTING -i lo -d 127.0.0.0/8 -j ACCEPT

iptables -t mangle -A PREROUTING -i $internal -s 255.255.255.0/32 -j ACCEPT
iptables -t mangle -A PREROUTING -i $internal -d 255.255.255.0/32 -j ACCEPT

iptables -t mangle -A PREROUTING -i $internal -s 192.168.0.0/24 -j ACCEPT
iptables -t mangle -A PREROUTING -i $internal -d 192.168.0.0/24 -j ACCEPT

iptables -t mangle -A PREROUTING -p udp --dport 853 -j DROP
iptables -t mangle -A PREROUTING -p tcp --dport 853 -j DROP

dns="8.8.8.8 8.8.4.4"
for ip in $dns; do
   iptables -A INPUT -s $ip -p udp --sport 53 -m state --state RELATED,ESTABLISHED -j ACCEPT
   iptables -A OUTPUT -d $ip -p udp --dport 53 -m state --state RELATED,ESTABLISHED -j ACCEPT
   iptables -A FORWARD -d $ip -p udp --dport 53 -m state --state RELATED,ESTABLISHED -j ACCEPT
done
iptables -A FORWARD -p udp --dport 53 -j REJECT

例如,如果我在本地网络 (1.1.1.1 1.0.0.1) 上的 PC 上手动设置 cloudflare dns,则该 PC 可以访问互联网

PD:

  1. 规则“-m state --state RELATED,ESTABLISHED”位于这个问题被选为正确的
  2. 阻止规则位于这个问题被选为正确的
  3. 我尝试在所有链(INPUT、Mangle、OUTPUT、FORWARD)上使用相同的阻止规则,并将 REJECT 更改为 DROP,但并没有阻止
  4. 我为 src 添加了额外的阻止规则,它也没有阻止。例如:
iptables -A FORWARD -s $ip -p udp --sport 53 -m state --state RELATED,ESTABLISHED -j ACCEPT
# and block
iptables -A FORWARD -p udp --sport 53 -j DROP

笔记:这些规则也适用于 TCP(但为了不重复,我就不放了)

更新:

我将 DNS 规则更改为:

dns="8.8.8.8 8.8.4.4"
for ip in $dns; do
   iptables -A INPUT -s $ip -p udp --sport 53 -j ACCEPT
   iptables -A OUTPUT -d $ip -p udp --dport 53 -j ACCEPT
   iptables -A FORWARD -d $ip -p udp --dport 53 -j ACCEPT
done
iptables -A INPUT -p udp --sport 53 -j DROP
iptables -A OUTPUT -p udp --dport 53 -j DROP
iptables -A FORWARD -p udp --dport 53 -j DROP

但它也没有正确地进行阻止

笔记:输入规则是否带有“-m state --state RELATED,ESTABLISHED -j ACCEPT”无关紧要,因为我感兴趣的是阻止连接,而这并没有发生

谢谢

答案1

简短的摘要

iptables -A OUTPUT -d $ip -p udp --dport 53 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -d $ip -p udp --dport 53 -m state --state RELATED,ESTABLISHED -j ACCEPT

规则应该是:

iptables -A OUTPUT -d $ip -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -d $ip -p udp --dport 53 -j ACCEPT

解释

我将使用客户端 IP192.168.100.100和端口12345作为示例。

当您网络中的客户端(192.168.100.100)发送 DNS 请求时,它会从端口 12345 发送一个 UDP 数据包到 DNS 服务器的端口 53。

当数据包通过 Linux 路由器时,路由器会为 DNS 查询创建一个连接跟踪条目。此连接跟踪条目有多个状态,其中之一就是ESTABLISHED

现在,在您的原始规则中,您需要ESTABLISHED第一个传出的 DNS 查询数据包的状态。在示例中,客户端从端口向端口192.168.100.100发送 UDP 数据包,没有该五元组的条目。因此防火墙会丢弃该数据包。123458.8.8.853ESTABLISHED

当从传出规则中删除匹配状态​​时,则所有到 DNS 服务器端口 53 的传出数据包都将被批准,并且连接跟踪条目将被正确创建。

然后您可以使用 匹配返回方向-m state --state ESTABLISHED,因为连接跟踪条目存在。

相关内容