Skip to content

网络(2): 域名劫持

clarkehe edited this page Nov 4, 2016 · 13 revisions

案例一

最近遇到一个问题:有一个功能是通过http的post方法上传本地图片到服务器,有上海移动宽带的用户反馈说会上传失败。

考虑到上个版本有上报一些图片上传失败的情况,这个版本加了重试机制。从用户那里取了日志,http请求的返回码是404,重试也是404。

服务器是正常的,自己测也正常,怎么会404呢?想起之前也遇到过移动网络用户通过域名连接服务器因为域名解析不正确导致失败的情况。同样是移动网络的用户,还是怀疑是域名解析的问题。看了下代码,确定是HardCode的域名地址进行的请求。

找后台开发要来了这个域名对应的2个ip地址。修改代码,在上传失败重试时,切换ip进行请求。编了包发给用户验证,用户反馈说上传成功了。取日志确认,第一次用域名请求,失败了(404),第二次用ip,上传成功。

    private final static String [] SERVER_URL = {
            "http://xx.xx.qq.com/cgi-bin/pic_upload",
            "http://112.xx.xx.xx:80/cgi-bin/pic_upload",
            "http://14.xx.xx.xx:80/cgi-bin/pic_upload"
    };
2016-07-25 12:18:45.855(114) I/UploadThumUtil: post: serverUrl=http://xx.xx.qq.com/cgi-bin/pic_upload
2016-07-25 12:18:47.053(115) I/UploadThumUtil: responeCode:404, contentLength=38210
2016-07-25 12:18:48.056(116) E/VideoUploadTask: uploadVideoThumnail重试,mUploadThumbRetryTime=1
2016-07-25 12:18:48.419(116) I/UploadThumUtil: post: serverUrl=http://112.xx.xx.xx:80/cgi-bin/pic_upload
2016-07-25 12:18:49.198(117) I/UploadThumUtil: responeCode:200, contentLength=10441

初步可以确定是域名解析的问题了。分析了一下,域名解析出问题,可能有三种情况:

  • 域名解析不出ip,解析失败
  • 域名解析出了ip,但ip不是这个域名的
  • 域名解析出了ip,ip是正确的,但调度不是最优的

为了确认是那种可能性,写了一段测试代码,让用户帮忙验证,并取回日志。

    static {
        lookupIP("xx.xx.qq.com");
    }

    public static void lookupIP(String host){
        String ip;
        try {
            InetAddress address = InetAddress.getByName(host);
            ip = address.getHostAddress();
            ALog.i(TAG, "lookup address: " + host + ", ip: " + ip);
        } catch (Exception e) {
            ALog.e(TAG, "lookup exception: " + e.toString());
        }
    }
2016-07-25 12:18:45.844(114) I/UploadThumUtil: lookup address: xx.xx.qq.com, ip: 117.135.175.19

从日志可以看出域名解析成功了,但ip是错误的,不是我们真实服务器的ip。使用移动宽带的用户经常会用到这种情况。

案例二

两年前也是域名解析的问题被运营商坑了,主要还是自己对网络这块经验不足。问题是这样的:PC客户端通过webkit用到了内嵌webview,在 webview里加载一个页面。但测试发现webview首次加载会比较慢,第二次加载会快很多,主要原因是webview首次加载页面时初始化要花较长时间。

于是想到了预加载的方法,但预加载也需要一个url地址。开始想把实际的地址进行预加载,但考虑到用户的量比较大(DAU过千万),会给服务器造成不必要的压力。于就是相随便写个不存在的地址,可不曾想到,这个地址也会进行域名解决析。在用户实际的网络环境中,运营商在解析一个不存的域名地址时,不是返回失败,而是返回一个他作推广的ip地址。结果用户反馈启动应用时,就是有广告的声音,必须要退出应用才行,就是因为预加载了运营商的广告页面。其实预加载的地址用"about:blank"或"127.0.0.1"就行。

什么是域名劫持?

域名访问网络时会先解析成ip,在域名解析成ip的过程中,发生了问题,最常见的问题就是域名劫持了。域名劫持大多是因为网络运营商的问题导致的。我们通过网络运营商(电信、联通、移动等)接入互联网时,也会使用运营商的域名服务器(Local DNS)。通过域名访问网络时,首先要访问运营商的域名服务器,域名服务器上记录着域名到ip映射表,如果这张表记录有误(有意或无意),我们就是得到错误的ip。这种现象就是域名劫持了。

在实际项目经验过程中,使用移动宽带的用户会遇到这种问题会比较多。当问题比较普通时,我们查出是那个地区的用户时,会让运营人员联系这个地区移动公司来更新域名表。有时一个地区改好了,另一个地区的又不行,用户量大,使用的域名多时,联系移动公司更新域名的工作时太大,且效率也非常低。

域名劫持解决

当出现域名劫持时,一种解决方案是域名+备用ip。当使用域名请求失败时,使用备用ip进行访问。但这要在代码中HardCode备用ip,ip不能变。现在业界的比较广泛的解决方案是HttpDNS,各个大的互联网公司都有自己的HttpDNS实现。HttpDNS就是使用ip来进行http请求来获取域名对应ip,不使用移动运营商的Local DNS。

腾讯HttpDNS
移动解析HttpDNS基于Http协议向腾讯云的DNS服务器发送域名解析请求,替代了基于DNS协议向运营商Local DNS发起解析请求的传统方式,可以避免Local DNS造成的域名劫持和跨网访问问题,解决移动互联网服务中域名解析异常带来的困扰。

阿里云
HttpDNS是面向移动开发者推出的一款域名解析产品,具有域名防劫持、精准调度的特性。

新浪微博
开源的HttpDNS实现,GitHub地址。

参考资料:
扫盲 DNS 原理,兼谈“域名劫持”和“域名欺骗/域名污染”
【鹅厂网事】全局精确流量调度新思路-HttpDNS服务详解
关于互联网流量劫持分析及可选的解决方案
如何利用HTTPDNS降低DNS解析开销

Clone this wiki locally