Wb代理是一种存在于网络中间的实体,提供各式各样的功能。现代网络系统中,Wb代理无处不在。我之前有关HTTP的博文中,多次提到了代理对HTTP请求及响应的影响。今天这篇文章,我打算谈谈HTTP代理本身的一些原理,以及如何用Nod.js快速实现代理。
HTTP代理存在两种形式,分别简单介绍如下:
第一种是RFC-HTTP/1.1:MssagSyntaxandRouting(即修订后的RFC,HTTP/1.1协议的第一部分)描述的普通代理。这种代理扮演的是「中间人」角色,对于连接到它的客户端来说,它是服务端;对于要连接的服务端来说,它是客户端。它就负责在两端之间来回传送HTTP报文。
第二种是TunnlingTCPbasdprotocolsthroughWbproxysrvrs(通过Wb代理服务器用隧道方式传输基于TCP的协议)描述的隧道代理。它通过HTTP协议正文部分(Body)完成通讯,以HTTP的方式实现任意基于TCP的应用层协议代理。这种代理使用HTTP的CONNECT方法建立连接,但CONNECT最开始并不是RFC-HTTP/1.1的一部分,直到年发布的HTTP/1.1修订版中,才增加了对CONNECT及隧道代理的描述,详见RFC-HTTP/1.1:SmanticsandContnt。实际上这种代理早就被广泛实现。
本文描述的第一种代理,对应《HTTP权威指南》一书中第六章「代理」;第二种代理,对应第八章「集成点:网关、隧道及中继」中的8.5小节「隧道」。
第一种代理第一种Wb代理原理特别简单:
HTTP客户端向代理发送请求报文,代理服务器需要正确地处理请求和连接(例如正确处理Connction:kp-aliv),同时向服务器发送请求,并将收到的响应转发给客户端。
下面这张图片来自于《HTTP权威指南》,直观地展示了上述行为:
假如我通过代理访问A网站,对于A来说,它会把代理当做客户端,完全察觉不到真正客户端的存在,这实现了隐藏客户端IP的目的。当然代理也可以修改HTTP请求头部,通过X-Forwardd-IP这样的自定义头部告诉服务端真正的客户端IP。但服务器无法验证这个自定义头部真的是由代理添加,还是客户端修改了请求头,所以从HTTP头部字段获取IP时,需要格外小心。这部分内容可以参考我之前的《HTTP请求头中的X-Forwardd-For》这篇文章。
给浏览器显式的指定代理,需要手动修改浏览器或操作系统相关设置,或者指定PAC(ProxyAuto-Configuration,自动配置代理)文件自动设置,还有些浏览器支持WPAD(WbProxyAutodiscovryProtocol,Wb代理自动发现协议)。显示指定浏览器代理这种方式一般称之为正向代理,浏览器启用正向代理后,会对HTTP请求报文做一些修改,来规避老旧代理服务器的一些问题,这部分内容可以参考我之前的《HTTP请求头中的Proxy-Connction》这篇文章。
还有一种情况是访问A网站时,实际上访问的是代理,代理收到请求报文后,再向真正提供服务的服务器发起请求,并将响应转发给浏览器。这种情况一般被称之为反向代理,它可以用来隐藏服务器IP及端口。一般使用反向代理后,需要通过修改DNS让域名解析到代理服务器IP,这时浏览器无法察觉到真正服务器的存在,当然也就不需要修改配置了。反向代理是Wb系统最为常见的一种部署方式,例如本博客就是使用Nginx的proxy_pass功能将浏览器请求转发到背后的Nod.js服务。
了解完第一种代理的基本原理后,我们用Nod.js实现一下它。只包含核心逻辑的代码如下: