|
firefox + noscript + adblockplus 可拦截此类广告,但 firefox 仍会连接到劫持站点,接着或者 noscript 给出警告,或者 stopbadware 给出警告。
很久以前,从来没有,最近一两年,两三天出一次,最近一段时间一天能出两三次,尤其是拨号成功第一次使用浏览器时几率比较高。
看不到广告,仍影响心情。
投诉进行中,客服小妹态度很好,之后客服经理(可能是客服小妹上级)及技术人员分别用不录音电话回话过来,磨讥半天,死不承认,故左右而言它,可能是俺太客气,下次下下次凶点。
投诉不是办法,出国还好说,出差在外仍受异地 ISP 推送广告骚扰。
大家知道 dns 劫持好解决,换可信任 dns 能解决大半,或从加密通道访问权威 dns,再有可自己架 dns relay server 或 dnsmasq 什么的。
大家都知道用类似加密通道方法对抗 http 劫持,代价太大。
http 劫持其实也好解决,将 ISP 广告站点加入 /etc/hosts 中指向不存在地址或 127.0.0.1,只是连不到,这样浏览器上仍会有反应,仍影响心情。
另 /etc/hosts 留下不干净东东也挺恶心。
如果 http 劫持每次都发生,早抓包分析去。
今天终于忍不住动手,抓了 50M 多才碰到一回,罪证不展览,简单分析下:
从 IP、MAC 地址看不出问题;
浏览器向目标主机发送 GET 后,进行劫持的机器伪装成目标主机发送一个伪包,设置 TCP 标志 FIN PSH ACK,TTL 值与真实包不同,可近似确定劫持机器物理位置,并包含一个如下框架页面;- <html>
- <!-- 25 -->
- <script language=JScript>
- <!-- function killErrors(){return true;} window.onerror=killErrors; -->
- </script>
- <frameset rows="*,0">
- <frame src="[color=Red]http://isp_http_hijack.site/path/index.htm[/color]" noresize><frame src="" noresize>
- </frameset>
- </html>
复制代码 接着浏览器去连接劫持到的站点 GET 如下;- GET [color=Red]/path/index.htm[/color] HTTP/1.1
- Host: [color=Red]isp_http_hijack.site[/color]
- User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
- Accept-Language: zh-cn,zh;q=0.5
- Accept-Encoding: gzip,deflate
- Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
- Keep-Alive: 115
- Connection: keep-alive
- Referer: [color=Red]http://real_target.site/[/color]
复制代码 劫持到的站点 回应 如下;- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>无标题文档</title>
- </head>
- <body style="margin:0;padding:0;height:100%;overflow:hidden;scroll:no">
- <script type="text/javascript">
- <!--
- function killErrors()
- {return true;}
- window.onerror = killErrors;
- -->
- </script>
- <!--包含公共的脚本代码-->
- <script language="javascript" src="pub.js"></script>
- <!--设置iframe属性-->
- <script language=JavaScript1.2>
- <!--
- var url=encodeURIComponent([color=Red]getReferer()[/color]);
- url="tourl.html?url="+url
- document.write("<iframe id='content' name='content' src='"+url+"' frameborder='0' width='100%' height='100%' scrolling='yes'><\/iframe>")
- -->
- </script>
- <!--底部上升广告设置-->
- <script language=JavaScript1.2>
- <!--
- var page_w,page_h;
- page_w = 326;
- page_h = 200;
- if (getArgs("width")!="" && IsInteger(getArgs("width")))
- page_w = parseInt(getArgs("width"),0);
- if (getArgs("height")!="" && IsInteger(getArgs("height")))
- page_h=parseInt(getArgs("height"),0);
- -->
- </script>
- <!--包含执行的脚本代码-->
- <script language="javascript" src="app.js"></script>
- <!--自动适应高度脚本 解决IE7不能适应问题-->
- <script language=JavaScript1.2>
- <!--
- function autoheight(sid) {
- var gid=document.getElementById(sid);
- gid.height=document.documentElement.offsetHeight-5;
- }
- if(Browser.isIE) window.setInterval("autoheight("content")",100);
- -->
- </script>
- </body>
- </html>
复制代码 进行劫持的机器,不可见,是影子机器,很有可能放置在某个 ISP 能控制的路由器旁路,与劫持到的机器不是同一机器。(一般人没机会这样做,ISP 难逃其责)
PSH 是 TCP 协议中用来主动推送数据的标志。http://www.tcpipguide.com/free/t ... rPushFunction-2.htm
可见 ISP 多么无耻,协议竟然如此滥用。
上面分析结果可能有地方性,同好不妨自己抓包看一下,可使用 wireshark。
针对上面结果,偶决定用 iptables 一了百了封堵推送广告:
用于路由器,请把 INPUT 换 FORWARD 并开启 内核转发。
经一天时间试用,拦截有效,没有明显副作用,可去掉日志部分。- iptables -I INPUT -p tcp --sport 80 --tcp-flags FIN,PSH,ACK FIN,PSH,ACK -j DROP
- iptables -I INPUT -p tcp --sport 80 --tcp-flags FIN,PSH,ACK FIN,PSH,ACK -j LOG --log-level info --log-prefix="illegal_PSH: "
复制代码
FreeBSD ipfw 防火墙 对应 iptables 封 FIN,PSH,ACK tcp 伪包命令:
红色部分请换合适编号,日志可去掉。- ipfw add [color=Red]00001[/color] deny log tcp from any 80 to me in established tcpflags fin,ack,psh
复制代码
对 M$ 不感冒,但查了下 FreeBSD ipfw 防火墙有移植,名曰 wipfw。
所以可以把 M$ 当 FreeBSD 对待。
或者针对 TTL 变化过滤,TCP 建立连接后,TTL 不变是一个合理假设:
用于路由器,请把 INPUT 换 FORWARD 并开启 内核转发。
经测试此规则有效,此规则不适于单独使用,日志部分可去掉。
注:与前面过滤 FIN PSH ACK 规则并用时,此规则要放在前面。- iptables -I INPUT -p tcp --sport 80 -m state --state ESTABLISHED -m recent --set -j ACCEPT
- iptables -I INPUT -p tcp --sport 80 -m state --state ESTABLISHED -m recent --update --seconds 60 -j DROP
- iptables -I INPUT -p tcp --sport 80 -m state --state ESTABLISHED -m recent --update --seconds 60 -j LOG --log-level info --log-prefix="ttl_unmatch: "
- iptables -I INPUT -p tcp --sport 80 -m state --state ESTABLISHED -m recent --update --seconds 60 --rttl -j ACCEPT
复制代码
或者在上面方法基础上多判断一下特征字符串 frame:
经测试确定此法无效。- [color=Silver]iptables -I INPUT -p tcp --sport 80 --tcp-flags FIN,PSH,ACK FIN,PSH,ACK -m string --algo bm --string "frame" -j DROP
- iptables -I INPUT -p tcp --sport 80 --tcp-flags FIN,PSH,ACK FIN,PSH,ACK -m string --algo bm --string "frame" -j LOG[/color]
复制代码 http://netfilter.org/documentation/HOWTO/netfilter-extensions-HOWTO-3.html#ss3.18 指出 string 模块用来传送包包给用户空间程序,如 IDS 程序。
如果您遇到不同类型 http 劫持,请提供抓包结果,希望大家一起努力共建一个全面适用 iptables、ipfw 规则。
如果您有更好方法,请赐教。 |
|