显示标签为“socat”的博文。显示所有博文
显示标签为“socat”的博文。显示所有博文

2015年5月26日星期二

HTTP请求中,IF-MODIFIED-SINCE造成的问题

有个调查,要搞清楚为什么IE8访问特别慢,IE11和别的Browser都没问题。
环境是Apache+WebLogic做的一个Login网页,瞬间就完了的事儿,IE8却耗费30秒才出来,就算是从本地访问都是。

简单的调查例如IE兼容模式,IE cache,检查server配置等都有人做过了,没有明显的线索。

用IE8的developer tool抓不到网页的第一个请求内容,apache那边的Access Log也没有配置成现实响应耗费时间。

也没多想,还是老方法,socat神器登场,做个假server做转接,打印出来往内容,就可以知道更多,比抓包的好看。(不过windows下的socat似乎不怎么方便安装,我还是安装cygwin里在net分类里选择的socat和netcat(nc))。

Run:
socat -D -v -tcp-listen:localhost:8000 tcp-connect:RealServerIP:80

(-D选项是为了现实新出现的连接,为了保险起见看看)

Browser:
http://localhost:8000/

于是socat现实一大堆HTTP request header:
GET / HTTP1.1 ......
.......
IF-MODIFIED-SINCE: .....某个诡异的2010年的日期.....   //这个意思就是问server这个网页在这个日期之后又无更新


而Response呢,三十秒后才来说:
HTTP 304
.....

这个就更诡异了,304就是说没有更新。那你早回答啊,需要这么长时间???

当然,一开始并没有觉察到IF-MODIFIED-SINCE有什么诡异。

后来用firefox和chrome都做了一下,对比一看,人家没有问IF-MODIFIED-SINCE啊。

于是做个验证,

另一个老牌工具netcat登场 (不过后来又nmap公司新出品的ncat更强,但是不容易安装到),当时机器里么有telnet,所以我也只能用这个了,Windows发神经把telnet从默认安装选项里去掉了,几年了还不响应呼声加进来,太不自觉了。

Run:
nc localhost 8000

然后输入HTTP request header..... 最后是个空回车,才会被server接受,
的确是一旦有了IF-MODIFIED-SINCE,就很慢。

暂时到这儿了,至于为啥慢那就是apache那边犯傻了,该咋改就咋改。

话说好奇为啥IE8要问IF-MODIFIED-SINCE啊,其他的Browser都不问?不可能,肯定是server那边第一次返回response时指出了LAST-MODIFIED-DATE才让browser误解的,

看了看response内容的确如此。

那最后推断,如果把browser的cache都清除,肯定第一次会快,第二次就会慢。

Chrome:  推论正确
IE:  推论正确
   但是,不是那么简单的就能够清除的,首先要把IE彻底关掉,然后从Control pannel的Internet Option里,清除cache。和Browser里的清除的方法一样。
   另外,为了保险起见,还是动用了Process Monitor神器来过滤找到cache的文件在什么目录,现在忘了,反正就是AppData下的什么一个Content.IE5目录下,把这个目录干掉就万无一失了。

Firefox: 版本特殊无法证实。安装上的firefox是强制被设定成不保存cache的,甚至访问履历都没有,一旦关闭就什么都没了。这也许是管理上的policy。没做多研究。
但是从另一个反面得到证实:这个版本的firefox从来不发IF-MODIFIED-SINCE,不管是第几次访问。






WebSocket在HTTP Proxy下是可以,可是有点小笨拙之处给人造成不便

从规格说明上看,WebSocket毋庸置疑是可以通过HTTP Proxy Server代理访问出去的,不论是非加密的ws://,还是加密的wss://,都应该可以。当然有个通常都满足的前提:HTTP Proxy Server提供socket连接级别的无过滤转接,是所谓的CONNECT命令(而不光是HTTP整体请求响应的转接和过滤)。现实因为如果不提供这个CONNECT命令支持,那么HTTPS网站就用不了(原因一句话说不清,当然通过伪造SSL证书等手段也是可以的,只是需要browser机器这边配合)。总之,HTTP Proxy Server从原理上看,一旦支持了CONNECT命令,那么他后来就对连接中发生的加密内容基本上就是干瞪眼,无法区分到底是不是HTTPS了,从某种意义来说,这是HTTP Proxy Server设计上的一种漏洞。

事实上的确我使用WebSocket一段时间,和http proxy配合也正常,wss(加密)和ws(不加密)两种协议都行,

可有一天在一个http proxy环境下发生问题了!

经过一番疑神疑鬼的调查,最终确定是自动配置script里没有对wss类型提供proxy server ip和port,而只是回答了一个direct (就是不经过proxy server直接连接),所以失败了。

对策很简单,修改pac或者配置一个固定的proxy的ip,port。

memo一下调查经过:

所用工具:socat

在Firefox/Chrome/IE里,使用加密型WebSocket: new WebSocket('wss://x.y.z/test'),爆出错误说timeout, 而非加密型 new WebSocket('ws://x.y.z/test') 也报错。

Proxy 配置:

自动: http://proxyserver/config.pac

调查开始:

先搞清楚这个config.pac干什么的,其实是个根据url, host来回答该用什么proxy server的东西,而且是个javascript。例如:

function FindProxyForURL(url, host) {
  if (url.substring(0, 5) == "http:") {
  return "PROXY proxy:80";
} else if (url.substring(0, 6) == "https:") {
  return "PROXY secproxy:8080";
} else {
  return "DIRECT";
}
}

那看了一下就是用secproxy:8080了啊,https都正常访问了,为啥wss出毛病?

当时绕了个弯子,想要看看http proxy内部发生了什么,于是就拿socat工具来做个中转来分析,这是个神器,以后在写一些活用法。

Run:
socat -v tcp-listen:8080,reuseaddr,fork  tcp-connect:secproxy:8080

就是用来做一个假的proxy server,本地的。其中的动作都转接到真的proxy server里去,
然后设定Browser通过这个假的Proxy server访问,于是可以看到其中的来往数据,

内容就省略了。着么折腾了一下也忘了抓取屏幕,忘了是怎么搞的,似乎是server对Websocket的握手请求作出回答后,browser就没有继续请求了,反正意识到自签名的证书会导致问题:WebSocket Server那边的server ssl证书是自签名的,那么可能这边不承认,嗯,的确有人说是,那好,我把证书给作为[可信赖的顶级证书发型者]来加入到系统,哦,https访问网站时的叉号消失了。

着么搞一下,的确wss可以了。

但是回到真环境,发现还是不行,最后用Sysinternal's Process Monitor工具追踪网络调用,发现browser居然不通过proxy就直接出去,于是出错了。

去掉自动配置选项,改成固定的proxy的ip,port就好了。


最终,我觉得websocket在选择Proxy server的方法上做的有点傻?居然直接傻乎乎问wss://somesite 该用什么proxy server,而不是聪明的问https://somesite该用什么网站。