在互联网早期,一方面组织内部能上网的计算机比较少,另一方面是网络比较慢且流量比较贵,还有一方面是为了管控组织内能上网的计算机身份和数量,所以有了 proxy 这种组件。
我们常说的 http 代理工作在 80 端口,工作过程如下图:
<img src="https://pic4.zhimg.com/v2-bc7387952c7cec15803b27ddadced7a1_b.jpg" data-size="normal" data-rawwidth="900" data-rawheight="420" data-default-watermark-src="https://pic4.zhimg.com/v2-b117a565fe4214376ffeb85d99aca85d_b.jpg" class="origin_image zh-lightbox-thumb" width="900" data-original="https://pic4.zhimg.com/v2-bc7387952c7cec15803b27ddadced7a1_r.jpg">
http 代理工作过程,来源:https://www.privateproxyreviews.com/what-are-http-proxies/
如果内网计算机的浏览器访问的是明文 http 请求,那这个请求会直接发给中间的代理。代理收到后根据目标域名或IP地址连接服务器并将浏览器的请求转发给服务器,最后将服务器的响应转发给浏览器。整个过程都是通过明文 tpc
后来,https 出现了。如果浏览器想通过 https 访问网页,会先建立加密通道,然后将 http 请求加密之后发给服务器。如果个时候想在中间加个代理,代理也没法解密浏览器的加密请求,从而没法代理。为了解决这个问题,人们引入了一种叫 CONNECT 的 http 请求方法,工作过程如下:
<img src="https://pic3.zhimg.com/v2-7289a84e498a7b7f70bc81e0b7824704_b.jpg" data-size="normal" data-rawwidth="484" data-rawheight="509" data-default-watermark-src="https://picx.zhimg.com/v2-c63c8bf3c0e2a0e9e61b7eb1b6533dd9_b.jpg" class="origin_image zh-lightbox-thumb" width="484" data-original="https://pic3.zhimg.com/v2-7289a84e498a7b7f70bc81e0b7824704_r.jpg">
http connect 请求过程,来源:https://medium.com/swlh/writing-a-modern-http-s-tunnel-in-rust-56e70d898700
浏览器先跟代理建议 tcp 连接。如果它想访问 https://google.com
,就需要先发一个这样的请求:
CONNECT google.com:443 HTTP/1.1
代理收到后会主动连接google.com:443
对应的服务器,两边 tcp 连接都建好了,代理会自动双向转发数据。也就是说,这个时候浏览器的加密数据就会被转发到服务器,服务器的加密数据也会转发给浏览器。但代理并不知道加密数据的明文。
但不论是明文 http 请求还是加密的 https 请求,从浏览器到代理这一段的通信都是通过明文 tcp 传输的。也就是说不论是浏览器发出的 GET 请求还是 CONNECT 请求,在浏览器到代理的链路上的所有节点都是能监控的。也就是说这些节点知道你要访问哪个网站,这会导致隐私泄漏。而且有的代理需要登录,用户名和密码也是通过明文传输的,根本没有安全性可言。
为了解决这个问题,人们引入了所谓的 Secure Web Proxy,也就是所谓的 https 代理。核心思路就是使用 https/tls 对浏览器到代理这一段的通信进行加密,这样中间节点就不能监听数据。
https 代理的工作过程跟 http 很像,只不过浏览器在跟 proxy 建议 tcp 连接之后还需要再协商 tls 会话。tls