通过 iptables 重定向 DNS

通过 iptables 重定向 DNS

背景

我一直在努力通过 iptables 实现重定向 - 这是 DD-WRT 上的软件版本的限制功能和(更可能是)我的劣质脚本的组合。

我们在相关网络上的互联网带宽非常有限,因此我部署了许多措施来提高利用率,例如广告拦截和替换技术、流量过滤、QoS 优先级

我有 ISP 提供的路由器作为外部路由器,还有一个内部路由器运行 WiFi、LAN 和 VPN 连接到互联网。

具体问题

增强功能包括专用服务器节点上的 DNS 缓存,以及将所有 DNS 请求重定向到此服务器。大部分功能都是通过 dhcp 服务器中的网络设置完成的,但一些移动和桌面应用程序会覆盖此功能。

我使用 DNS 上游服务器作为 LAN DNS 服务器的目标,我知道这些服务器是值得信赖的。内部路由器有一个防火墙脚本,旨在应用 VPN 终止开关并允许粘性 IP 在 VPN 之外访问/直接通过我们的 ISP 访问(非常感谢 Netflix)。

然而,我很难让 DNS 流量重定向在 DD-WRT 上运行 - 我使用dig和在服务器和台式机组合上对其进行了测试tcpdump,模拟向服务器 A 发出请求,重定向到服务器 B,客户端相应地获得 DNS 响应。这似乎按预期工作,但是当我将相同的配置应用于内部路由器时,它不起作用。当我向公共解析器(例如 Cloudflare)发出请求时,我看不到任何流量到达 DNS 服务器。

事实上该请求仍然被阻止。

lanDns="dns server IP"

iptables -I FORWARD -s ! $lanDns -p tcp --dport 53 -j ACCEPT
iptables -I FORWARD -s ! $lanDns -p udp --dport 53 -j ACCEPT
iptables -t nat -A PREROUTING -s ! $lanDns -p tcp --dport 53 -j DNAT --to $lanDns:53
iptables -t nat -A PREROUTING -s ! $lanDns -p udp --dport 53 -j DNAT --to $lanDns:53

iptables -I FORWARD -s ! $lanDns -p tcp --dport 5353 -j ACCEPT
iptables -I FORWARD -s ! $lanDns -p udp --dport 5353 -j ACCEPT
iptables -t nat -A PREROUTING -s ! $lanDns -p tcp --dport 5353 -j DNAT --to $lanDns:53
iptables -t nat -A PREROUTING -s ! $lanDns -p udp --dport 5353 -j DNAT --to $lanDns:53

# secure DNS - TODO letsencrypt certificate for <servername>
iptables -t nat -A PREROUTING -s ! $lanDns -p tcp --dport 853 -j DNAT --to $lanDns:853
# allow direct DNS traffic from the LAN DNS server, don't need to drop as well as this will only interfere
iptables -A FORWARD -p tcp --dport 53 -s $lanDns -j ACCEPT
iptables -A FORWARD -p udp --dport 53 -s $lanDns -j ACCEPT

iptables 输出看起来不错,但我遗漏了什么?它是否像排序一样简单,还是只是我的 iptables 使用不当?:)

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:53 to:[DNS server ip] 
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:53 to:[DNS server ip] 
DNAT       tcp  -- ![DNS server ip]       0.0.0.0/0           tcp dpt:53 to:[DNS server ip]:53 
DNAT       udp  -- ![DNS server ip]       0.0.0.0/0           udp dpt:53 to:[DNS server ip]:53 
DNAT       tcp  -- ![DNS server ip]       0.0.0.0/0           tcp dpt:5353 to:[DNS server ip]:53 
DNAT       udp  -- ![DNS server ip]       0.0.0.0/0           udp dpt:5353 to:[DNS server ip]:53 

DD-WRT(Kong Ac)上的 iptables 版本:1.3.7

更新

感谢 davidgo 的评论,看来请求被正确重定向了,但响应到达了路由器(但没有被发送回请求者)。将对规则排序进行更多试验,并在有进展时进行更新 - 如果这能让问题更容易识别,欢迎支持

替代解决方案不适用于此

我承认以下是好的解决方案,但不适合这种特定的场景:

  • PiHole——其他节点也提供类似的功能
  • 更换路由器
  • 使用其他固件发行版替换 DD-WRT 固件
  • 非 Linux 解决方案
  • 闭源解决方案

答案1

感谢 davidgo 提供的解决此问题的正确方法。我之前没有发现的是,请求被重定向到正确的端点,但响应没有传回给请求者。

为了解决这个问题,我使用了 postrouting 命令,并且还更改了顺序,从附加改为插入。下面的代码摘录也成功用于通过 853 (sDNS) 重定向 tcp 请求,它也是减少代码重复的循环的一部分。

# declarations to make the excerpt make more sense    
lanDns="LAN server IP"
dnsPorts="53 5353"

for dnsPort in $dnsPorts; do
    iptables -t nat -I POSTROUTING -s ! $lanDns -p udp --dport $dnsPort -d $lanDns -j MASQUERADE
done

你不一定想尝试重定向所有可以因为经常使用异常失败的 DNS 请求来跟踪网络上的恶意软件。拥有自己的本地 DNS 确实有助于发现不受欢迎的活动。

额外的

|| logger -p daemon.error "Error code $? for 4"我发现使用每个 iptables 命令末尾的某个唯一行指示符来查找我的粗制滥造的编码很有用4。DD-WRT 使它变得更加困难,因为这些记录的项目不会通过远程日志分流,因此您无法在日志服务器上查看它们。

您仍然需要通过 SSH 连接到路由器并grep获取消息。

相关内容