欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

运营商DNS劫持的那些事儿

shiping1 的头像

上来先说一句,其实我对运营商DNS劫持了解不深,这个标题起的有点俏,还请见谅。

什么是DNS劫持

百度百科《DNS劫持》我们可以知道:“ DNS劫持又称域名劫持,是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能反应或访问的是假网址。”

在百科的最后特意建立了“电信DNS劫持”一门。5月12,13日,微博上不断有关于“运营商DNS劫持”的相关微博发出及被转发评论。事实上,各地的运营商或多或少或明或暗的都会做着各种偷鸡摸狗用流量换金钱的事情。

在我前几个月去联通营业厅做宽带包年的时候,北京这里是明确了使用会“弹出广告”ADSL包年要比“不弹广告”的包年便宜一些银两。这是明面上写在协议中的“DNS劫持”弹广告的代表,这些比某些地方不吭不声的弹广告相比,我觉得还算“光明磊落”。上个周末,微博上,尤其是北京的圈中出现越来越多抱怨弹窗的声音,看来是北京这边终于开始间隙性鸡鸣狗盗了。(PS:在我之前按月付宽带费上网时,曾也不定时遇见过弹出广告的行为,所以就我看来,在运营商执行层面上对各种包年的用户,弹与不弹应没有本质区别。所以我建议大家在京包年ADSL的时候选择“弹广告”的那种。但是,但是,这真是一件让人恨恨不平的事情,但这也是国内各运营商的游戏规则,连一线的互联网企业也只能睁一眼闭一眼,有介入但不深。《百度告青岛联通流量劫持案件胜诉 获赔20万元》

微博事件1:http://weibo.com/1486697205/yj2sm4n3a

微博事件2:http://weibo.com/2573758674/yiMRc8yM5

其中微博事件2是某地运营商在360安全网址首页弹出广告,且只在该页弹出。一时使得用户以为360安全网址自己做了恶俗的浮动广告。

运营上劫持域名做了些什么

上面一直在说“弹广告”,其实劫持了域名的运营商是在做这事儿。当然一些小运营商还做了更过分的事情,这个我们稍后会提到。

360导航首页遭遇运营商劫持的一些往事

在2011年6月初,360导航做出一次重大改版之后,接二连三的爆发一些踩坑事件。其中一项是我们突然接到大量的反馈说,新版首页【不可用】,搜索选项不能切换种种现象。初步判断是业务相关的JS代码挂掉了,但原因却百思不得其解。

在之后的一次与用户远程中,抓包看了整个首页数据传输情况,突然发现了两条诡异的请求。http://hub.ad2you.com/re/re.php?src=t0033… 及 http://h.qhimg.com/js/jquery-1.6.1.min.js?tqs=20110616  第一个请求有些莫名,且全页引入jQuery时并未加任何参数,于是看到之上 http://h.qhimg.com/js/jquery-1.6.1.min.js 这个请求,响应的内容居然是:

1
2
document.write("<script language='javascript' src='http://hub.ad2you.com/re/re.php?src=t0033&t="+ encodeURIComponent(document.title)+"'><\/script>");
document.write("<script language='javascript' src='http://h.qhimg.com/js/jquery-1.6.1.min.js?tqs=20110616'><\/script>");

显然首页的核心类库jQuery请求被调包成如上掺杂广告的形式了。由于首页所需的jQuery是在采取Load机制,运营商这么一搞jQuery晚了几个时间片,结果首页的初始化工作就功亏一溃了。全程大略如此,这样的请求被劫持是我方不能避免得(即使更改URL或增加随机数等),那我唯有做些检测机制来辅助重新初始化了。

但是。。。我们是真心不想让运营商轻易得逞。

我们是否可以斗法,如何去斗?

首先定义一下我们,我们是指在各个公司从事互联网产品服务的工程狮们。我们自然希望运营商的DNS劫持对我们产品是无效得,或者至少不干扰产品的正常使用。

至于说斗法?这是天方夜谭,作为永远从他人道路运输产品的服务商们,面对路霸的吃拿卡要我们实在没有“能力”直接对抗。即使借助法律,找衙门去告无良路霸们,也只是杯水车薪之位。所以最后的最后,我们只期待在落后一些的弹窗策略之下,可以有所变通,让广告尽量弹不出。

那么接下来说的做法写较为简单:对document.write进行包装

第一个方案是当前我所采用的简单粗暴的将document.write重写为空函数

1
2
3
4
5
6
7
8
9
var oldDocwrite = document.write,newDocwrite = function(str){};
if(oldDocwrite.apply){
    hao360.docWrite = function(str){
        oldDocwrite.apply(document,arguments);
    }
}else{
    hao360.docWrite = oldDocwrite;
}
document.write = newDocwrite;

显然这种方案有些太不优雅,但却也很有效。

第二个方案是豆瓣 http://www.douban.com/js/do.js 尾部用到的白名单过滤方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// @TODO 临时应对劫持 by dexteryy
 
var _write = _doc.write,
_white_list = {
    'douban.com': 1,
    'douban.fm': 1,
    'google.com': 1,
    'google-analytics.com': 1,
    'googleadservices.com': 1
},
// 统计劫持情况
_hijack_stat = function(reason, env){
    var img = new Image();
    img.onload = function(){};
        + encodeURIComponent(reason)
        "&environment=" + encodeURIComponent(env);
},
 
_RE_SCRIPTS = /<script.*?src\=["']?([^"'\s>]+)/ig,
_RE_DOMAIN = /(.+?)\.([^\/]+).+/;
_doc.write = function(str){
    try {
        var s, safes = [], unkowns = [];
        while (s = _RE_SCRIPTS.exec(str)) {
            if (_white_list[(_RE_DOMAIN.exec(s) || [])[2]]) {
                safes.push(s);
            else {
                unkowns.push(s);
            }
        }
        if (unkowns.length > 0) {
            _hijack_stat([unkowns[0], safes[0] || ""].join("~_~"), location.href);
        }
        try {
          _write.call(this, str);
        catch (ex) {
          _write(str);
        }
    catch (ex) {
        _write(str);
        _hijack_stat(ex.name + ":" + ex.message, location.href);
    }
};

以上两个方案可视项目情况而定,各有利弊。

但是如果运营商换个方案,不采取document.write,那真就要很难斗了。当然如果无耻的DNS劫持始终跟着流量入口页的对策升级方案,那咱们还是洗洗睡吧。

更过分的整站劫持

另外说一句一些地方的小运营商,如四川南充某运营商所管辖的这部分地域,直接将hao.360.cn指向自己的导航页面了,虽然样子还是定期缓存360导航的页面,但其中内容却已被改动多半。对于这些的确的用户反馈,我们只能表示无奈,且也尝试付诸于法律手段。

结语

所以结论就是运营商是用户的“最后一公里”,我们只能尽力而为也就是了。当然期待某个时刻的来临,将这一切是非之事统统扫清。

关于运营商DNS劫持的这些事,我就罗嗦至此。欢迎跟帖补充

来自  http://blogs.360.cn/blog/%E8%BF%90%E8%90%A5%E5%95%86dns%E5%8A%AB%E6%8C%81%E7%9A%84%E9%82%A3%E4%BA%9B...


普通分类: