iptables劫持并拦截DNS查询53端口实现转向(Redirect)
提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!
企业内网中经常会有这样的需求,比如说业务服务器的IP地址为
192.168.6.25
,大家也就习惯于访问这个地址了,运维也很厚道的将某个域名解析到这个IP地址,这样大家也就不必记住繁琐的IP地址,同时运维也很方便的将业务服务器由
192.168.6.25
的主机迁移到
192.168.6.26
的主机而无需通知客户端更改地址,这也是域名发挥的作用,好了,现在问题来了:-)
客户说我们企业很小,不想另外购买域名,好吧,每年五十几块也是一笔费用,而且购买域名后还需要有人维护,比如要记得续费什么的,略麻烦。同样的还觉得将内网地址公布到外网上不是安全的行为。
经过我的询问得知该企业拥有一台自建的DNS服务器,为全网提供DNS查询,那这事情就好办多了,对DNS服务器软件硬绑定指定的域名到IP地址的记录(由于是我们自己的DNS服务器,这里的域名可以任意设置,当然最好设置为公网上没有的域名地址以避免冲突)。
对于DNSMASQ,直接在
/etc/dnsmasq.d
路径下建立一个conf文件,比如
server.conf
,内容如下:
address=/business.server/192.168.6.25
这里
business.server
为我们任意设置的域名,而
192.168.6.25
为指向的IP地址。
由于这里局域网上网的路由DHCP自动分配DNS服务器为我们的内网服务器,所以对于自动获取IP和DNS的客户端则不需要我们多操心,但是问题远远没有解决,如果有人自己指派了DNS服务器呢?
好吧,运维人员可不希望一个一个去通知用户修改DNS服务器为指定的内网服务器,但是通过强大的
iptables
我们可以神不知鬼不觉地劫持用户的所有DNS查询。
当然这里的iptables是在路由上设置的(这里局域网的路由是一台小型的服务器,运行着Linux系统),众所周知,DNS使用53端口,并通过TCP或者UDP协议传输,那么我们就需要劫持这两个协议传输通过53端口的查询流量到我们指派的DNS服务器上。
iptables -t nat -A PREROUTING -i ethX -p udp --dport 53 -j DNAT --to $(get lan_ipaddr)
iptables -t nat -A PREROUTING -i ethX -p tcp --dport 53 -j DNAT --to $(get lan_ipaddr)
这里
ethX
为局域网的LAN口,而
$(get lan_ipaddr)
指示的是我们自己的DNS服务器(一般在内网),比如我们的LAN口为
eth1
,而DNS服务器位于
192.168.6.10
,则上述规则更改为:
iptables -t nat -A PREROUTING -i eth1 -p udp --dport 53 -j DNAT --to 192.168.6.10
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 53 -j DNAT --to 192.168.6.10
好了,到这里我要介绍的也就完了,但是这种办法有个前提是在局域网内,所有的流量必须走路由器,也就是这个路由器为网关型路由(所有流量进出口),否则此办法无效,但对于特殊情况可以考虑采取类似的DNS投毒方式进行,我也没试过,这边也不介绍了。这种方法还有问题,应用上述防火墙规则会导致所有发往53端口的udp或者tcp数据流量被截获,如果某外网服务器53端口做其他用处则会异常,同时在一定程度上也加重了自建DNS服务器的负担,如果自建服务器崩溃,则所有的DNS解析将会失效。
当然,我今天讲的这个技巧还有一个应用场景,比如在网络环境比较恶劣的情况下,DNS被攻击或者遭到投毒,自建服务器可以通过多种手段避免这些安全问题,这样为了局域网安全,转移DNS查询流量则是必须的了。
那么windows有这样的工具吗?
一般这种是网络防火墙提供的功能,大部分完备的防火墙软件均可以提供端口拦截和转发,对于Windows下企业级防火墙可以考虑采用ISA或者TMG实现。
很有趣,但是我的不成功。 我是在学着你的文章http://wangye.org/blog/archives/845/假设了Raspberry pi 路由器,在路由器上输入 iptables -t nat -A PREROUTING -i wlan0 -p udp --dport 53 -j DNAT --to 192.168.6.10 iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 53 -j DNAT --to 192.168.6.10 无法做到劫持,希望得到你的解答,谢谢
很凑巧,我也在树莓派上做过这个实验,结果是成功的,最终的效果是无论查询的DNS服务器是否存在,响应结果的服务器必定是指定的。 我不太明白你的相关配置,值得注意的是确保命令是正确的,比如dport前面是两个短横线等等,还有就是192.168.6.10这个DNS服务器是否存在并正常运行DNS服务:
成功了,谢谢。 我试了下这样劫持DNS的话,DNS服务器返回DNS包的dest_ip是路由器的地址,而非客户端ip地址,客户端会把这样的DNS包丢掉。 还有奇怪你的博客的评论没有email提醒机制,我以为你一直没有回复呢orz
不客气,这种拦截只有在查询DNS经过拦截网关服务器时才能生效,如果本地客户端的话会直接进入回环而不经过拦截服务器。 Email主要考虑到博客服务器的资源消耗所以没有开,毕竟垃圾评论太多,带来不便还请见谅。