http与https代理中的差异及细节
Posted 进击的大杂烩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了http与https代理中的差异及细节相关的知识,希望对你有一定的参考价值。
前提:
HTTP/1.1中,默认开启长连接,如客户端不需要,需要加上请求首部connection:close告知服务器。如服务器不支持长连接,则需要加上响应首部connection:close告知客户端,否则需要加上响应首部connection:keep-alive
HTTP/1.0中,默认不开启长连接,如客户端需要,需要加上请求首部connection:keep-alive告知服务器。如服务器不支持长连接,则需要加上响应首部connection:close告知客户端,否则需要加上响应首部connection:keep-alive
所谓连接并不是一个水管连接起来,而是人们想象出来的东西。
传统的短连接只是在发送真正的数据包前,加了一个发送握手数据包的过程。而在发送完数据包之后,加了一个挥手数据包的过程。
而长连接也只是在发送完数据包后,不着急发送挥手数据包,继续发送数据包。
请注意,长连接是tcp/ip层面的东西,http应用只是根据connection首部去控制tcp/ip层数据包而已,这一点非常重要。
在HTTP中代理要用什么方式去连接server,代理说了算。客户端能控制的只是自己与代理之间的连接。
HTTP代理
首先看普通的CS模型
然后来看一下中间有代理的
有区别的地方我用红框标出来了,第一个红框不难理解,先解释第二个红框吧
代理服务多种多样,有聪明的即能完整做到http协议的,也有笨的只能做到一部分http协议的,我们称之为盲中继。
在http协议中,代理层是不允许转发connection首部,而盲中继则会转发connection首部
如果转发了connection首部,意味着客户端可以控制代理层与server之间的连接,让我们来看看问题
以上图为例,盲中继会将connection首部进行转发,并且往往在响应和请求时都只支持http1.0
带来的结果是:服务器认为自己在进行长连接,客户端也认为自己在进行长连接,但代理层根本不知道什么长连接
于是代理层认为server应该关闭连接,于是该连接挂起。与此同时客户端认为自己在进行长连接,于是继续发送http事物给代理,代理层则忽略客户端发来的任何请求,于是一直在打圈,在超时后,连接断开。
这种问题我们是不想看到的,虽然我们规定了代理层不允许转发connection首部,但我们又不能要求所有人都不使用盲中继,于是就有了上面的那种解决方案:
当代理层理解http事物时,他将请求头改成了connection:keep-alive发送给Server。
盲中继则是继续无脑转发,而proxy-connection只被服务器当成了一个普通首部而不会影响
注意上面几张图http协议版本号的转化
最后说说第三个框,squid代理中,响应请求使用的是http1.0,发送请求时使用的是http1.1,具体为什么,可能是因为我的squid版本比较老造成的,我们要知道,发请求远比处理请求简单的多。据说squid3.0可以完美支持http1.1响应了。
最后我们在命令行中证明一下上面的结论。
不经过代理
使用squid代理
HTTPS代理
HTTPS只是在http与tcp之间加了一个ssl层,
重要的是,在客户端与代理建立连接后,客户端发往代理的http事务数据是经过加密的,请看下图
注意加密的只是http事务数据,tcp/ip的数据包是不会被加密的,否则路由器理解不了,这一点在之后理解长连接短连接非常重要。
在http中通过代理时,应将数据发往谁,是在http首部中定义的,如
而在https中,代理收到的http请求全是加密的,因此代理不知道该发往谁
所以代理层是这么处理的:客户端在发送真正数据包之前,以明文方式告诉代理应将报文发往谁即可,请看下图。
也就是说,客户端先使用connect方法让代理与server事先建立好一个连接,代理收到同一客户端的后续请求,只需使用事先建立好的连接即可。
因此https代理必须支持connect方法
最后在命令行中验证一下
telnet 实现
由于代理层收到的都是加密的http报文,因此代理能做到的仅仅是无脑转发http报文,这种行为我们叫做隧道。
但是注意只是http报文被加密了,tcp/ip报文依然是明文的,如果连tcp/ip报文都被加密,路由器就无法理解了,也就无法传递了。
而tcp长短连接,是在tcp/ip报文中控制的。
在http中,client和server可以根据connection首部来判断后发送相应的tcp/ip报文。
由于代理无法理解http行为,因此也无法在http层面上根据connection头来控制长连接。
因此长短连接均由cilent和server的connection控制,这点是与http有决定性不同的
因此如果一条连接发生了断开请求,另一端一定会立刻开始断开,可以说,https中代理的两侧连接是同步的,来看一下。
HTTP代理:由于代理层可以理解http报文,则可能出现客户端与代理通信是短连接,而代理与服务器间通信是长连接的情况。
HTTPS代理:由于代理词只能收到加密的http报文,无法根据connection首部判断发送相应的tcp/ip报文,只能根据client或者server的tcp/ip报文来转发,因此两侧的连接状态是相同的。
最后,同样由于https代理是无法添加http首部的,所以server无法获得client的ip,而http中是可以的。
以上是关于http与https代理中的差异及细节的主要内容,如果未能解决你的问题,请参考以下文章