Hijack DnsPod HttpDNS



劫持DNS是个很简单的工作,家用路由器基本都自带dnsmasq,直接加解析就行。

之前某次尝试劫持某视频App的广告接口解析到一个空的本地服务器上,发现该App使用了DnsPod的HttpDNS服务,所以传统的DNS劫持方案不好用。而EdgeRouter的DPI功能也没有对外开放墙一般的高级接口,所以这次用NAT来实现。

首先,原有的App广告流程如下:

图中的流程很传统,12为HttpDNS请求过程,34为广告资源拉取。没有画路由器,因为这里没有用到路由器的DNS转发功能,所以路由器不重要。

针对这个场景,如果想劫持HttpDNS Server的解析,就需要在终端和HttpDNS Server之间加上一个代理,图就变成了:

这里Hijack Server存在的前提是使用了非ssl/tls的传输协议。在HttpDNS的常规逻辑上,也不太好加常用的SSL,因为不会有CA给IP颁发证书。DnsPod的HttpDNS的一个参考地址是 http://119.29.29.29/d?dn=sskaje.me 。当然企业级自己预置证书这种玩法我就管不了了。应该不会有人问为什么HttpDNS不用域名来设置目标服务器地址吧。

从实际角度来说,图应该变成下边这个样子,我没有刻意地画路由、防火墙设备,只是拿个方框区分出所谓的LAN和WAN。

又回到常识性的逻辑上,1/4这个链路其实是不可能成立的,因为App这边的IP是写死的。在不修改App的前提下,图其实应该是这样的:

从路由/防火墙上配置规则,将App的HttpDNS Server的请求,转发到Hijack Server上。

所以在EdgeRouter上,我们要做的第一件事情是,DNAT。我的Hijack Server IP是192.168.1.13,路由器IP是192.168.1.1,待劫持的设备IP是192.168.1.151。我定义了两个组,一个是DnsPod HttpDNS的所有IP,一个是需要劫持的LAN IP。所以参考的配置如下。

不出意料的,挂了。请求发出去一致没有响应,开日志发现,只有SYN包到了192.168.1.13上。原因是:在LAN里直接做DNAT,只是修改了目的地址,源地址没改,导致在同一个局域网下,1.13这台机器看到源IP是同网段,所以把ACK直接发给了源IP的机器,于是出现了下图:

解决方案就是再开一个MASQUERADE。配置如下:

1.13上,我用php写了一个简单的HttpDNS查询接口,预留了一个读配置文件的地方:

配置文件就是同目录下的 hijack_config.php,内容如下

nginx配置也很简单



Hijack DnsPod HttpDNS by @sskaje: https://sskaje.me/2019/04/hijack-dnspod-httpdns/

Incoming search terms: