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与https代理中的差异及细节


有区别的地方我用红框标出来了,第一个红框不难理解,先解释第二个红框吧

代理服务多种多样,有聪明的即能完整做到http协议的,也有笨的只能做到一部分http协议的,我们称之为盲中继。

在http协议中,代理层是不允许转发connection首部,而盲中继则会转发connection首部

如果转发了connection首部,意味着客户端可以控制代理层与server之间的连接,让我们来看看问题


http与https代理中的差异及细节

以上图为例,盲中继会将connection首部进行转发,并且往往在响应和请求时都只支持http1.0

带来的结果是:服务器认为自己在进行长连接,客户端也认为自己在进行长连接,但代理层根本不知道什么长连接

于是代理层认为server应该关闭连接,于是该连接挂起。与此同时客户端认为自己在进行长连接,于是继续发送http事物给代理,代理层则忽略客户端发来的任何请求,于是一直在打圈,在超时后,连接断开。

这种问题我们是不想看到的,虽然我们规定了代理层不允许转发connection首部,但我们又不能要求所有人都不使用盲中继,于是就有了上面的那种解决方案:

当代理层理解http事物时,他将请求头改成了connection:keep-alive发送给Server。


http与https代理中的差异及细节

盲中继则是继续无脑转发,而proxy-connection只被服务器当成了一个普通首部而不会影响


http与https代理中的差异及细节


注意上面几张图http协议版本号的转化

最后说说第三个框,squid代理中,响应请求使用的是http1.0,发送请求时使用的是http1.1,具体为什么,可能是因为我的squid版本比较老造成的,我们要知道,发请求远比处理请求简单的多。据说squid3.0可以完美支持http1.1响应了。

最后我们在命令行中证明一下上面的结论。

不经过代理


http与https代理中的差异及细节

使用squid代理


http与https代理中的差异及细节

HTTPS代理

HTTPS只是在http与tcp之间加了一个ssl层,

重要的是,在客户端与代理建立连接后,客户端发往代理的http事务数据是经过加密的,请看下图

注意加密的只是http事务数据,tcp/ip的数据包是不会被加密的,否则路由器理解不了,这一点在之后理解长连接短连接非常重要。


http与https代理中的差异及细节

在http中通过代理时,应将数据发往谁,是在http首部中定义的,如


http与https代理中的差异及细节


而在https中,代理收到的http请求全是加密的,因此代理不知道该发往谁


http与https代理中的差异及细节

所以代理层是这么处理的:客户端在发送真正数据包之前,以明文方式告诉代理应将报文发往谁即可,请看下图。


http与https代理中的差异及细节

也就是说,客户端先使用connect方法让代理与server事先建立好一个连接,代理收到同一客户端的后续请求,只需使用事先建立好的连接即可。

因此https代理必须支持connect方法

最后在命令行中验证一下


http与https代理中的差异及细节

telnet 实现

http与https代理中的差异及细节

由于代理层收到的都是加密的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代理中的差异及细节的主要内容,如果未能解决你的问题,请参考以下文章

设计模式系列——代理模式

Atitit.HTTP 代理原理及实现 正向代理与反向代理attilax总结

通过 Java 中的 SOCKS 代理进行 SOAP 调用

Nginx配置详解

ClientDataSet中撤消与恢复操作及执行细节

差异代理URL /代理IP