102 views

HTTP/2标准的发展 4 – SPDY事实标准

image

 

HTTP/2候选协议们,可以用迪斯尼动画片的名字描述:“白雪公主和七个小矮人”。公主是一枝独秀的Google SPDY,先于标准实现了,大量部署,被多个大厂商和主流浏览器支持,NGINX, Apache,IIS齐活。HTTP/2最早的draft也是照搬SPDY(The initial draft of HTTP 2.0 was published in November 2012 and is based on a straight copy of SPDY【SPDY WIKI】)。

小矮人就是其它几个不是同量级的候选协议。其实也没有七个那么多,有的仅是SPDY的补充。

 

1.SPDY (Speedy)

 

image_thumb10

【SPDY Home】是项目主页,当前最新版本是3.1。

 

image

安装火狐插件spdy-indicator(chrome有类似插件)后,访问google,可以在地址栏看到绿色的SPDY闪电标志。上图表示当前网站基于SPDY 3.1。SPDY协议文档并不长,且不少是frame格式描述等内容。这里关注SPDY如何应对前文提到的HTTP1.X协议缺陷。

1.1应对HOL – “Tunnel”化

image

这里这张图很清晰的表现了SPDY应对HOL问题的方案,它已经演化成了“tunnel”。SPDY的Session中可以跑HTTP会话,也可以跑websocket会话(?存疑)。这些会话有独立的内部Stream承载,彼此隔离,没有HOL时序限制。“tunnel”是浏览器发起的长连接,生命直到浏览器关闭页面。

1.1.1 Stream信令的设计

SPDY Stream信令模仿TCP,有FIN, SYN, RST等概念,使用窗口机制做流控,但都不相同,例如:

1.TCP是带内信令,SYN等传输在带内。SPDY有SYN这样的带内信令,也有SETTINGS(配置整个Session配置项)这样的带外信令。有些信令stream和session各有一份。

例如对于Stream的RST和对于Session的GOAWAY。

2.窗口通告没有随着报文携带,并不是TCP的滑动窗口。

3.Stream有单双向之分,例如Server Push就是单向发送的。

4.引入了Steam Priority这样的QOS概念

对于Ping等控制报文分配最高的Priority,保证Ping的使命必达。

 

总之在设计上没有什么束缚,随意发挥了。

image

上图是一个只有一个stream的最简SPDY。

Client发送SETTINGS信令设定全局参数,然后发起SYN报文

Server发起SETTINGS确定参数,回应SYN,传回数据。

 

另,Wireshare默认会自动解压被压缩部分,显示明文。

1.2 Server Push

1.2.1 概念以及和WebSocket的关系?

从SPDY协议来看,SPDY Server Push的引入和前文HTTP只能单向发起通讯的缺陷无关:

“SPDY enables a server to send multiple replies to a client for a single request. The rationale for this feature is that sometimes a server knows that it will need to send multiple resources in response to a single request. Without server push features, the client must first download the primary resource, then discover the secondary resource(s), and request them. ”

SPDY的Server Push目的是,client需要获得一组资源时仅仅发送一次请求即可。SPDY Server Push一个可以想到的例子是:Server产生了一个页面,页面上有多个本站的GIF图片链接。当Client下载页面的时候,server预先知道这些图片一并被下载,因此通过Server Push一次发送。

看来Google只想加快网页加载速度,一切为了主营业务:广告费。SPDY的Server Push无法替代websocket以及已有的HTTP1.X Server Push功能,没有这个设计意图。

1.2.2 实现过程

Server Push在SPDY内部是一个和request stream不同的独立的Stream,有独立的Stream ID。用Associated-To-Stream-ID和Request所在的Stream进行关联。

image

上面是【SPDY Protocol】给出了一个Server Push的时序图。注意我圈红的地方其实有race condition。浏览器可能在Server Push的同时已经发送了对于资源的Request。

 

1.2.3 安全问题

Server Push可能会引入不少安全问题,协议中提到几个:

1.Server Push的时候,可能Client同时在请求该资源,有race contition。

2.恶意server可能会push其他网站的恶意资源,这个需要浏览器端做同源策略的检查。

3.Server可以通过无限的Push流量来对Client进行DOS攻击。

4.【mod_spdy】提到了Server Push可能造成请求的无限循环,即被Push的内容反过来get原有内容。

5.【Innovating with HTTP 2.0 Server Push】中还描述了Server Push的创新应用,不限于传response,还可以用于控制Cache,做redirect等等。

这里蕴藏着安全问题的小宝藏,无论对黑客还是安全厂商。

1.2.4 Server Push能否对已有应用透明?

这是我看了SPDY server push实现后的一个疑问,我的理解是:

1.针对浏览器来说应该可以做到透明

正如【Innovating with HTTP 2.0 Server Push】提到的“Resources delivered via HTTP 2.0 server push are processed by the browser but do not bubble up to the application code – there is no JavaScript API to get notifications for these events.”

对于Web应用,Server Push只是浏览器和Server可以感知的行为,我的理解是已有的旧应用不会调用为Server Push定义API,相当于没有Server Push的SPDY。即使Server有做Server Push动作,Push的结果被浏览器缓存在Cache之中,下一次访问自动命中,也不会有问题。

2.针对Web Service这样非页面浏览应用,前端不是浏览器,如果有Server Push,前端应用需要感知处理

1.3 其他

1.3.1 SPDY的协商

抓包可以看到,SPDY的TLS的Server Hello携带了NPN(Next Protocol Negotiation)扩展,使得浏览器在协商阶段就可以知道Web Server支持SPDY,从而选择SPDY通话。

image

 

1.3.2 流控控制

同TCP类比,我总结如下区别:

1.流量控制有两个层次

SPDY stream层和整个connection层分别有流量控制

2.SPDY使用独立的flow control的控制报文,而不是随着每个数据报文携带的

3.目前流量控制仅仅控制Data Frame。

4.窗口是固定大小的,并不滑动。

 

1.3.3 压缩 – 压缩那里,怎样压缩?

SPDY的压缩关注与HTTP的header压缩。body部分因为HTTP层面可以进行压缩,SPDY再次压缩是做无用功。但SPDY并没有简单的将HTTP的header字段完全压缩,而是提取出来,重新编码,放到了STREAM_SYN Frame之中。

image

 

1.3.4 Server Hint

Server Hint并没有包括在SPDY的3.1协议文本内,而是单列在【Server Hint】。

Server Hint is a mechanism where the server can notify the client of a resource that will be needed before the client can discover it.  The server does not send the entire contents of the resource, but rather just the URL as an early part of a response. The client can then validate its cache (potentially even eliminating the need for a GET-if-modified-since), and will formally request the resource only if needed.

【SPDY Protocol】里面给出了Server Hint的一个时序例子:

image

我的理解,可能场景之一类似于现在的浏览器搜索框,当你键入几个关键词,浏览器会列出一组可能的结果供你选择。或者一些即使通信应用的通知消息等。当然,这是一种具体应用,Server Hint功能不限于此。

1.3.5 一些思考

如果中间SSL Forwarding Proxy设备不支持NPN这样的扩展转发,是否SPDY会被自动降级为HTTPS?

 

1.4 SPDY的实验1 – 抓包

1.4.1抓包是个难题

看不到报文,协议分析就是隔靴搔痒,在SPDY上偏偏遇到了难题。本地可以搭建SPDY全套环境,但我更希望看到实际业务报文。SPDY现实部署都是基于SSL,想看业务报文有两种途径:浏览器插件或者安装SPDY forwarding代理,折腾了一段暂时放弃了,仅总结一下。

A).浏览器插件:

常用的火狐浏览器下的HTTP Fox插件对于SPDY网站只能抓到HTTP报文没有实现SPDY分析的功能。

Win8.1下的IE11支持SPDY,但HTTPWatch插件不支持IE这一特性。HTTPWatch的火狐插件可以显示SPDY内容。如果有SPDY流量,结果栏会显示如下SPDY Stream栏目,但是内容完全乱码,没有解析,也无法转存PCAP。这就是需要四五百美刀的插件的效果。

image

 

Chrome浏览器访问chrome://net-internals/#requests可以看到SPDY连接的概况,无法看到具体内容。

B).SPDY proxy

有一些网文,通过VPS搭建SPDY代理翻墙。因为不愿意让自己的博客被墙,没有尝试。

C).其它工具

不出所料,手头的BPS不支持SPDY,没有现成的报文。

Fiddler:按照这个帖子的说法, Windows的SSL lib没有把TLS扩展信息的控制权交给Client,原理上Fiddler无法代理抓SPDY报文。(存疑?IE和IIS使用什么TLSlib实现SPDY功能的呢)

1.4.2 本地抓包环境搭建

【Node-spdy server push 】是一个3.0版本的SPDY服务器的SPDY例子,参照搭建运行成功。抓包之中有不少tricky的事情,逼着我熬夜几个小时。【Ubuntu 12.04 LTS 下配置 apache支持SPDY, 使用wireshark 抓包分析SPDY 协议】这篇文档不错,提前看可以节省不少时间。

a)Wireshark的SSL解密密钥配置中一定要配置两条一样的私钥,一条用于HTTP,另一条用于SPDY,而且顺序不能反,必须http在spdy前面,不明觉厉(悲伤

image

b)必须要抓到整个session,否则缺少握手时的信息,wireshark不可能解密报文。因为SPDY是永不断开的长连接,这里容易出错。

c)不能用DH(Diffie–Hellman)私钥算法(我没试过,宁可信其有吧)。

 

1.5 SPDY实验2 – Server Push

这里有一个基于node.js的node-spdy模块(支持SPDY3)的server push例子,代码很简单,对于任何访问请求,通过Server push推送页面需要的几个js文件,再推送最后的HTML页面。

 

 

代码值得一提的就是server push在先,推送HTML在后,这是为何?

回看一下前面提到Server push的第一个安全问题:Server push和client请求之间会有race condition。我的理解是先发送server push可以保证server push的stream的SYN先于body内容之前到达client,可以避免race condition。这应该算是server push对于应用开发的一个影响了。

 

image

抓包证明,Server push是单向stream,内部携带request对应的associated stream ID。

另外这个例子还显示并发特性,很好的证明SPDY可以应对HOL。代码中第一个被push的文件backbone.js,因为个头最大,最后一个发送完成。

 

【参考】

1.Ubuntu 12.04 LTS 下配置 apache支持SPDY, 使用wireshark 抓包分析SPDY 协议,http://www.cnblogs.com/diegodu/p/4134936.html

2.SPDY WIKI – http://en.wikipedia.org/wiki/HTTP/2

3.SPDY Home http://www.chromium.org/spdy

4.Innovating with HTTP 2.0 Server Push – https://www.igvita.com/2013/06/12/innovating-with-http-2.0-server-push/

5.Node-spdy server push – https://github.com/ericallam/spdy-with-server-push-tutorial

6.Mod_spdy – https://code.google.com/p/mod-spdy/wiki/OptimizingForSpdy

7.Server Hint – http://www.chromium.org/spdy/link-headers-and-server-hint

8.SPDY protocol – By Jory Cohen Made for CISC856, Spring 2010 Thanks to Dr. Amer, Mike Belshe(Google), Jon Leighton

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">