HTTP 代理 - 图1

首先需要明确本文要介绍的HTTP代理和类似Nginx的反向代理并不相同,本文所介绍的HTTP代理是指用户主动使用的代理,而Nginx反向代理一般来说是网站管理者会主动使用,但是一个网站是否使用了反向代理对于用户来说并没有什么区别。 一般用户使用HTTP代理主要出于以下几个原因:
  1. 无法直连目标网站,使用HTTP代理做中转站,比如:科学上网,访问某些内网等
  2. 优化网络体验,比如国内直连http://github.com一般很慢,有一些HTTP代理对此做了优化
  3. 隐藏自己的真实IP

如何使用 HTTP 代理访问 HTTP 网站?

HTTP代理应该是所有代理中最简单的一类代理,它的工作原理非常简单,就是用户将原本打算发送给网站服务器的文本原封不动地发送给代理服务器,代理服务器再将这个文本转发给网站服务器并接收网站服务器的返回的数据,再由代理服务器转发给用户。 在这个过程中,对于用户来说代理服务器扮演了和网站服务器完全相同的角色,因此对于用户来说使用HTTP代理是非常简单的一件事情。 而代理服务器所做的工作则是进行必要的数据转发,最大的难点在于从用户发来的请求当中识别出网站服务器地址和维护TCP连接具体代理服务器的实现方法超出了本文所讨论的内容,之后有机会再做分享。 接下来依然通过实验来说明。 首先我们需要在电脑上搭建一个HTTP代理服务器,在Ubuntu系统下可以直接使用tinyproxy,运行以下命令即可:
  1. sudo apt install tinyproxy
上面这个命令会自动在电脑上搭建一个HTTP代理服务器,默认的端口号是8888,并且默认只允许本机使用代理,如果想要在其他电脑使用这个代理,需要修改/etc/tinyproxy/tinyproxy.conf文件。 我们将之前准备的send.txt文件发送给tinyproxy,如下:

HTTP 代理 - 图2

可以看到通过代理服务器,我们也成功收到了百度返回的数据,同时注意到返回的数据中多了一行Via: 1.1 tinyproxy (tinyproxy/1.8.4),这一行就是tinyproxy自己添加的,在实际使用中完全可以忽略。 通过代理服务器,整个流程如下:

HTTP 代理 - 图3

如何使用 HTTP 代理访问 HTTPS 网站?

我们在访问HTTPS网站的时候,第一步并不是准备好请求的文本,而是先与网站服务器进行HTTPS握手。这个握手过程必须有HTTPS网站服务器的私钥参与,而代理服务器并不拥有这个私钥,因此这个握手无法由代理服务器代为建立。 在通过代理服务器访问HTTPS网站的过程中,代理服务器所扮演的角色仅仅是转发TCP数据(在访问HTTP网站的时候,代理服务器转发的是HTTP数据)。 在使用代理服务器的情况下,一个完整HTTPS请求要经历如下几个步骤:
  1. 首先用户向代理服务器发起CONNECT请求
  2. 代理服务器解析CONNECT请求,向网站服务器建立TCP连接,但是并不发送任何数据
  3. 代理服务器向用户返回数据,表示TCP连接已经建立了,此后代理服务器就只负责数据的转发,代理服务器看到的数据是加密之后的,无法查看原始数据或者对数据进行修改
  4. 然后用户和网站服务器建立HTTPS握手
  5. 之后用户和网站服务器之间的流程与一般的HTTP请求流程完全相同
用图片来描述的话如下:

HTTP 代理 - 图4

我们可以做个实验来验证代理服务器的CONNECT阶段。 首先准备一个connect.txt文件,里面的内容是:
  1. CONNECT www.baidu.com:443 HTTP/1.1
  2. Host: www.baidu.com:443

依然要注意文件的最后有一个空白行。

然后使用nc命令将这些内容发送给tinyproxy

HTTP 代理 - 图5

可以看到,tinyproxy在和百度建立了TCP连接之后,向我们返回了Connection established信息,这表示我们可以进行HTTPS握手了。