一. 前言
代理技术,是针对客户端(Client)和服务器(Server)之间的通信交互而言的一种介入技术。依据代理方式的不同,大致可以分为两种:1. 非透明代理;2. 透明代理。
1. 非透明代理
即被代理的客户端知晓代理服务器的存在。知晓的方式有很多种,比如客户端浏览器中设置代理服务器的IP地址和端口;又比如说,客户端在访问服务器时,捕获到了服务器返回的HTTP 302重定向报文(通常是代理服务器伪装源服务器返回的)等等。当然,对于不熟悉通信协议的用户来说,HTTP 302重定向这种方式也可以归类为透明代理。
2. 透明代理
即被代理的客户端根本不知道有代理服务器的存在。代理服务器在客户端和服务器的通信中途,接管了客户端的通信报文。透明代理的存在方式一般为网关、路由器和透明网桥等之中。
非透明代理的实现方式一般来说较为简单,搭建一个代理服务器(如Squid和Nginx等),把该代理服务器的IP地址和端口提供给客户端即可,这不是本文讨论的内容。
透明代理的实现方式相对来说复杂一些,但是也有成熟的解决方案。通常的思路是,在客户端和服务器通信的中途,将客户端的流量透明接管,同时利用4层/7层协议分析技术,过滤出需要代理的流量,并将这些流量牵引至代理服务器。常用的方案有(以Linux为例):
1. Iptables/Netfilter/Tproxy ----(特定IP/Port流量)----> Squid/Nginx代理服务器
2. Iptables/Netfilter/Tproxy ----(特定IP/Port流量)----> Haproxy ----(7层过滤)----> Squid/Nginx代理服务器
第一种方式效率高,但是也存在问题,就是有可能把非HTTP流量送给了HTTP代理服务器(很多非HTTP流量占用的是80/8080/3128端口),可能造成代理服务器出现问题;第二种方式,在前端增加了Haproxy的7层过滤,确保送给代理服务器的流量是HTTP流量。
这些透明代理方案的问题在于,缺乏精确的流量识别能力,所以需要管控的流量过多(所有HTTP Port的流量),在大背景流量下压力下,代理服务器的资源开销会很高;同时,为了减小代理服务系统出错概率,需要在Squid/Nginx前端对流量进行层级的过滤。试想,流量经过了多个模块的多次过滤,抛开代理服务器资源占用不说,报文的处理时间也被拉长了。
因此,本文讨论的重点,就是阐述基于条件约束的HTTP/TCP透明代理和流量牵引方案。该方案具备如下特征:
1. 条件约束
即待代理的流量,必须在明确知道其内容时,才进行管控。明确的内容,比如GET什么文件,是rar还是exe,Host是什么等等。这样,才能极大的减小管控流量范文。通俗的讲,就是“不见兔子不撒鹰”。
2. 透明HTTP/TCP代理
这里说的透明,不是依靠HTTP 302来实现的。HTTP 302能够被用户抓包发现,同时,部分客户端软件是不支持HTTP 302重定向的;另外,针对纯TCP通信(非HTTP通信)而言,是没有类似HTTP 302这种重定向机制的。代理服务器必须能够实现条件约束下的HTTP/TCP流量透明代理。
3. 资源开销小
什么叫资源开销小,就是系统只经过一级过滤,即可实现以上1、2的功能要求。
这样说来,这种透明HTTP/TCP代理的实现是具备一些挑战的。当然,越是有挑战的事情,就越值得去做,哪怕做不出来,这种经历也值得拥有。
同时,为什么要起名“条件约束”?因为,在条件满足的情况下做出来的事情,那不叫“成功”;只有在有限条件下做出来的事情,才能叫“成功”。呵呵,这说得有点夸大了。
另外,为什么要在Linux下去实现?因为,本人专业是通信与信息系统,不懂操作系统,但也不是完全不懂,Linux还是懂一些的。而且,做IT的人都知道,“不要重复造轮子 Stop Trying to Reinvent the Wheel”。既然Linux已经提供了Netfilter这么好的轮子,那直接用就可以了。