背景
我一直在努力通过 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
获取消息。