zoukankan      html  css  js  c++  java
  • 不同寻常的浏览器请求无响应错误

    背景

    公司的服务器托管在上海漕宝机房,服务器上除了公司网站外,还安装了几套公司自有产品的试用系统(B/S架构的),一直以来运行正常。

    灵异现象

    最近发现自有产品的试用系统有些页面在提交时无反应,等了很久之后显示“Internet Explorer 无法显示该网页”错误;类似的还有一些链接点击之后无反应,等了很久之后显示“Internet Explorer 无法显示该网页”错误。更为离奇的是:

    1. 这个错误无法在开发电脑上重现,试用完全相同的程序和数据,在开发电脑上就完全不会出现错误。
    2. 使用IE8访问出错,使用IE6或IE7访问时偶尔出现错误,而使用Firefox和Chrome则完全不出错。

    牛刀小试

    尝试一:是不是IE浏览器脚本兼容性问题?

    错误只发生在使用IE浏览器的情况下,是不是IE浏览器和页面上的脚本不兼容造成的?在开发电脑上无法重现错误,可能是因为局域网内使用IE8访问,实际是运行在IE7模式下,在IE7只偶尔出现错误,因此无法重现。基于这个假设,开始尝试找出是什么脚本导致错误,首先怀疑IE8的XSS过滤机制,手工关掉IE8的XSS过滤,错误依旧。仍然不死心,也许XSS很顽固,没有真正关掉。所以又将QueryString传递的参数进行编码解码,避免被浏览器误认为存在XSS攻击,还是没解决。

    尝试二:是不是IE浏览器无法处理长路径?

    老是怀疑IE浏览器也是有原因的,因为使用Firefox和Chrome时完全不出错,各种证据下IE的嫌疑最大。出错的页面和链接都有一个共同的特点就是页面的路径比较长,大都在500字符以上,因此怀疑IE8浏览器处理长路径是不是有问题。通过调整程序缩短了页面路径后,错误暂时解决,但仍然有几个疑点尚未弄明白:

    1. 为什么IE8必然出错,而IE6和IE7只是偶尔出现错误?
    2. 为什么在开发电脑上无法重现错误?同样是使用IE8浏览器访问,页面路径长度相同。为了尽可能模拟访问外部服务器的情况,特地修改了本机hosts文件,采用与外部服务器完全一致的域名来访问,仍然不会出现错误,为什么会这样?

    重新分析问题的真正原因

    上面虽然没有找出问题的真正原因,但也还是有两个收获:通过尝试一可以排除XSS方面原因,而通过尝试二发现了这个错误与页面路径长度有一定的联系。

    这个错误仅出现在IE浏览器上,是否是IE浏览器发生错误,导致请求没有发出?通过Fiddler侦听发现,请求其实是发送出去了,但一直没有收到服务器的响应,因此将怀疑的目标转移到服务器上。

    在服务器上通过分析IIS日志,发现IIS并没有收到请求,反复测试确认,在服务器上确实没有收到请求。

    浏览器发出了请求但服务器端没有收到请求,那么问题一定就出在传输环节,这时突然想起机房前段时间搞了一个白名单过滤系统,问题是不是就出在这个白名单系统上。如果真的是机房的白名单系统出了问题,那么之前的很多疑团就可以解释清楚了。比如:本地无法重现,是因为本地并没有白名单系统;浏览器发出了请求,而服务器端没有收到,是因为白名单过滤系统将请求过滤掉了;白名单过滤系统有BUG,导致IE浏览器的长路径请求无法正确处理,而被错误过滤等等。

    分析了这么多,疑点都集中到机房白名单过滤系统(以下简称白系统)上,但终归只是猜测而已,还需要更确切的证据来证实。机房不会配合我来调查,更不会透露关于白系统的任何细节(这种系统见不得光),唯一的办法就是找到白系统出错的规律,通过反证的方式来找出证据。

    黑盒分析白名单过滤系统

    设想一下,如果让我来写一个白系统的话,应该这样来实现:过滤所有的HTTP请求头,分析请求头中的Host属性值(主机头+端口),如果该主机头在白名单里,则允许通过,否则不允许通过。HTTP请求头可能很长,白系统不需要全部读完请求,只要读取到Host属性值即可。为了提高过滤效率,当HTTP请求头很长时,白系统可能只读取分析开始的N个字节长度内容,剩下的内容就被丢弃,不进行分析。在这种情况下,如果开始的N个字节长度内没有找到Host属性值,则该请求就会被白系统过滤掉。

    所以白系统是根据HTTP请求头中的Host属性值来进行过滤的,IE浏览器的HTTP请求头格式与Chrome的Http请求头格式不同,特别是Host属性的位置不同。IE浏览器中Host属性的位置靠后,大约在第七位;而Firefox和Chrome中Host属性的位置靠前,大约在第二位。当页面路径很长时,Http请求头就会变得很大,这时候如果Host属性在Http请求头中的位置比较靠后,就可能超出了白系统的固定读取的N个字节的范围,导致该请求被忽略。下面列出几个浏览器的Http请求头内容,供参考:

    Chrome的Http请求(Host在第2行

    GET /jxc/Libra.Web.Answer.Frames.FilterWindow.Do.aspx HTTP/1.1
    Host: a.unigc.com
    Connection: keep-alive
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.55 Safari/533.4
    Referer: http://a.unigc.com/jxc/Libra.Web.Answer.Frames.SingleWindow.Do.aspx
    Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: zh-CN,zh;q=0.8
    Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
    Cookie: __utmz=50212982.1286891934.38.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)

    Firefox的Http请求(Host在第2行

    GET /jxc/Libra.Web.Answer.Frames.FilterWindow.Do.aspx HTTP/1.1
    Host: a.unigc.com
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 (.NET CLR 3.5.30729)
    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
    Referer: http://a.unigc.com/jxc/Libra.Web.Answer.Frames.SingleWindow.Do.aspx
    Keep-Alive: 115
    Connection: keep-alive
    Cookie: __utma=91684958.649235843.1287212349.1287212349.1287212349.1; __utmz=91684958.1287212349.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)

    IE的Http请求(Host在第7行

    GET /jxc/Libra.Web.Answer.Frames.FilterWindow.Do.aspx HTTP/1.1
    Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
    Referer: http://a.unigc.com/jxc/Libra.Web.Answer.Frames.SingleWindow.Do.aspx
    Accept-Language: zh-cn
    User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; GTB6.5; EmbeddedWB 14.52 from: http://www.bsalsa.com/ EmbeddedWB 14.52; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1)
    Accept-Encoding: gzip, deflate
    Host: a.unigc.com
    Connection: Keep-Alive
    Cookie: __utmz=50212982.1286891934.38.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)

    用Fiddler生成Http请求头来测试,并不断调整Host的位置,最终测试出漕宝机房白系统的读取长度为1470字节。如果Http请求头开始的1470字节内没有包含Host属性的话,白系统会丢弃掉该请求,造成服务器端收不到该请求,客户端也因为收不到服务器端的响应而显示“Internet Explorer 无法显示该网页”的错误。

    一般来说,网页的Http请求头都不会太大,有些也只是最后的Cookie内容多一点,不会影响白系统的运行。但我们开发的这套企业管理软件的某些页面使用QueryString方式在页面间传递参数,这样可能导致页面的url地址很长,虽然我们控制了url地址的最大长度(小于1024),但没有想到这个长度已经超过了机房白系统的处理范围。

    特别是页面回发的情况下,请求头中会包含两次Url地址(请求地址和Referer分别一次)。假设url地址有1000字节,Firefox和Chrome的Host属性在第二位,从开始读取1470字节的话,一定可以读取到Host属性值。而IE则不行,Host属性前面还有Referer属性(长度1000字节),加上页面路径本身有1000字节长度,Host属性前至少有2000多字节,所以白系统只读取开始的1470字节,是不可能读取到Host属性,因此请求被白系统过滤,造成客户端点击按钮提交后长时间收不到响应,最后显示“Internet Explorer 无法显示该网页”的错误。

    题外话-关于白名单过滤系统

    为了提高过滤效率,机房的白名单过滤系统大都采用监听加干扰的方式,一旦发现某客户端有非法请求,就先于服务器给该客户端一个错误的响应,这种情况下,客户端会很快显示错误信息。但这次的白系统似乎是采用水闸大坝的方式实现(这种方式很低效,以后要考虑换机房),发现非法请求后就丢弃该请求,导致客户端长期等待响应,最后等待超时,才显示错误。正是这种长时间的等待,才误导我一开始就怀疑是浏览器的问题。

  • 相关阅读:
    (转)【web前端培训之前后端的配合(中)】继续昨日的故事
    ural(Timus) 1136. Parliament
    scau Josephus Problem
    ACMICPC Live Archive 6204 Poker End Games
    uva 10391 Compound Words
    ACMICPC Live Archive 3222 Joke with Turtles
    uva 10132 File Fragmentation
    uva 270 Lining Up
    【转】各种字符串哈希函数比较
    uva 10905 Children's Game
  • 原文地址:https://www.cnblogs.com/rrooyy/p/1901304.html
Copyright © 2011-2022 走看看