理解HTTP CONNECT通道

2018年08月12日

为了确保数据通信的安全,HTTPS已广泛应用于互联网,浏览器与服务器之间的HTTPS通信都是加密的。然而当浏览器需要通过代理服务器发起HTTPS请求时,由于请求的站点地址和端口号都是加密保存于HTTPS请求头中的,代理服务器是如何既确保通信是加密的(代理服务器自身也无法读取通信内容)又知道该往哪里发送请求呢?为了解决这个问题,浏览器需要先通过明文HTTP形式向代理服务器发送一个CONNECT请求告诉它目标站点地址及端口号。当代理服务器收到这个请求后,会在对应的端口上与目标站点建立一个TCP连接,连接建立成功后返回一个HTTP 200状态码告诉浏览器与该站点的加密通道已建成。接下来代理服务器仅仅是来回传输浏览器与该服务器之间的加密数据包,代理服务器并不需要解析这些内容以保证HTTPS的安全性。

什么时候会用到CONNECT方法?

只有当浏览器配置为使用代理服务器时才会用到CONNECT方法。

CONNECT通道建立流程

这里我们以Fiddler作为代理服务器,浏览器访问https://www.microsoft.com/作为例子:

  1. 首先浏览器向代理服务器发送CONNECT请求:

     CONNECT www.microsoft.com:443 HTTP/1.0
     User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
     Host: www.microsoft.com
     Content-Length: 0
     DNT: 1
     Connection: Keep-Alive
     Pragma: no-cache
    
  2. 代理服务器返回HTTP 200状态台码表示连接已建立:

     HTTP/1.0 200 Connection Established
     FiddlerGateway: Direct
     StartTime: 11:56:22.008
     Connection: close
     EndTime: 11:56:22.538
     ClientToServerBytes: 1416
     ServerToClientBytes: 1358
    
  3. 之后浏览器和服务器开始HTTPS握手并交换加密数据,Fiddler作为代理服务器只负责传输彼此的数据包,并不能读取具体数据内容(除非开启了Fiddler的解密HTTPS的功能并安装Fiddler根证书)。从Wireshark抓包中可以看出,在第12贞HTTP/1.0 200返回后,浏览器就开始建立TLS连接了。

如何处理服务器错误5xx?

如果代理服务器在连接目标站点时发生了错误如:DNS主机解析失败、连接超时,那么该如何处理CONNECT请求呢?由于这些错误会导致代理服务器无法与站点建立起TCP连接,那么代理服务器理应返回相应的状态码给浏览器。

  • 502: Bad Gateway
  • 504: Gateway timeout

是否可以返回重定向3xx?

实践中有一些代理服务器会在发生服务器无法连接后会针对CONNECT请求返回一个302重定向至一个定制过的错误页面来更好地告诉用户为什么无法显示该页面。虽然 HTTP 1.1 RFC 并没有规定CONNECT不能返回3xx重定向,但根据 302 RFC定义:请求的资源暂时被移动到另一个路径,对一个无法连接的站点返回302是不合适的,该资源其实并不是被移至另一个路径,而是目标服务器根本无法连接。如果一个资源真的被移至另一个路径的话,那么只应该由站点亲自通过HTTPS加密数据来告诉浏览器,而不是通过代理服务器以明文形式在CONNECT请求中返回。

并且,对于CONNECT请求返回302,多数现代浏览器并不会执行重定向命令,而是直接返回浏览器内置的错误页面。使用Fiddler的Auto responder功能可以模拟针对CONNECT请求返回302。

HTTP CONNECT请求:

CONNECT www.nonexistingwebsite.com:443 HTTP/1.1
Host: www.nonexistingwebsite.com:443
Proxy-Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36

Fiddler HTTP Response:

HTTP/1.1 302 Redirect
FiddlerTemplate: True
Date: Fri, 25 Jan 2013 16:49:29 GMT
Location: http://www.fiddler2.com/sandbox/FormAndCookie.asp
Content-Length: 0

可以看出Chrome、Firefox和IE都不会执行这个302重定向,而是直接显示错误信息。

参考资料