四层反向代理和七层反向代理
1、概述
代理也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。
2、四层网络代理
如果说网络层通信的粒度是物理终端设备的话,IP就是标记不同物理设备的符号,那么传输层通信的粒度是进程,端口就是标记不同进程的符号。
四层代理的四层就是OSI七层模型中的传输层;四层代理是基于IP+端口做的代理。四层通过虚拟IP+端口接收请求,然后再分配到真实的服务器。
以常见的TCP为例,从三次握手的第一次握手开始,代理设备在接收到第一个来自客户端的SYN 请求时,即按照一定的策略选择一个被代理的后端服务器,并对报文中目标IP地址进行修改(改为后端服务器IP),直接转发给该服务器。只不过在后端机器上看到的都是与代理机的IP的established而已。
TCP连接建立,即三次握手,实际上是客户端和后端服务器建立的,代理设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。
代表软件:LVS、F5。
3、七层网络代理
七层代理的七层就是OSI七层模型中的应用层;七层代理是基于内容数据做的代理(理解应用层中的应用数据),最终的转发规则取决于内容的差异。鉴于七层应用协议非常广泛,现在的七层代理主要是指HTTP代理。
和四层代理不同的是,七层代理必须要先和代理设备三次握手后,才能得到七层(HTTP层)的具体内容,然后再转发。意思就是代理机必须要与客户端和后端服务器的机器都要建立连接。显然,七层代理对代理设备的性能要求要高于四层代理。
我们常使用的Nginx,用作代理服务器的时候,一般都是工作在第七层的。使用Nginx,我们可以代理静态文件、ajax后台接口、CDN重定向等等,都是在传输层之上理解内容后做的工作。
七层应用负载的好处,是使得整个网络更智能化。例如访问一个网站的用户流量,可以通过七层的方式,将对图片类的请求转发到特定的图片服务器并可以使用缓存技术;将对文字类的请求可以转发到特定的文字服务器并可以使用压缩技术。当然这只是七层应用的一个小案例,从技术原理上,这种方式可以对客户端的请求和服务器的响应进行任意意义上的修改,极大的提升了应用系统在网络层的灵活性。很多在后台,例如Nginx或者Apache上部署的功能可以前移到负载均衡设备上,例如客户请求中的Header重写,服务器响应中的关键字过滤或者内容插入等功能。
另外一个常常被提到功能就是安全性。网络中最常见的SYN Flood攻击,即黑客控制众多源客户端,使用虚假IP地址对同一目标发送SYN攻击,通常这种攻击会大量发送SYN报文,耗尽服务器上的相关资源,以达到Denial of Service(DoS)的目的。从技术原理上也可以看出,四层模式下这些SYN攻击都会被转发到后端的服务器上;而七层模式下这些SYN攻击自然在负载均衡设备上就截止,不会影响后台服务器的正常运营。另外负载均衡设备可以在七层层面设定多种策略,过滤特定报文,例如SQL Injection等应用层面的特定攻击手段,从应用层面进一步提高系统整体安全。
现在的七层代理,主要还是着重于应用HTTP协议,所以其应用范围主要是众多的网站或者内部信息平台等基于B/S开发的系统。四层代理则对应其他TCP应用,例如基于C/S开发的系统。
代表软件:Nginx、Haproxy。
4、四层网络代理和七层网络代理区别
根据上文对四层网络代理和七层网络代理介绍可以,它俩最直观的区别是四层代理只进行了一次TCP请求,而七层代理进行了两次TCP请求。
4.1 四层网络代理
所谓四层网络代理,也就是主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
以常见的TCP为例,负载均衡设备在接收到第一个来自客户端的SYN 请求时,即通过上述方式选择一个最佳的服务器,并对报文中目标IP地址进行修改(改为后端服务器IP),直接转发给该服务器。TCP的连接建立,即三次握手是客户端和服务器直接建立的,负载均衡设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。
4.2 七层网络代理
所谓七层网络代理,也称为“内容交换”,也就是主要通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。
以常见的TCP为例,负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接受到客户端发送的真正应用层内容的报文,然后再根据该报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。负载均衡设备在这种情况下,更类似于一个代理服务器。负载均衡和前端的客户端以及后端的服务器会分别建立TCP连接。所以从这个技术原理上来看,七层负载均衡明显的对负载均衡设备的要求更高,处理七层的能力也必然会低于四层模式的部署方式。
5、现在对网络代理的使用是随着网站规模的提升根据不同的阶段来使用不同的技术
第一阶段:利用Nginx或HAProxy进行单点的负载均衡,这一阶段服务器规模刚脱离开单服务器、单数据库的模式,需要一定的负载均衡,但是仍然规模较小没有专业的维护团队来进行维护,也没有需要进行大规模的网站部署。这样利用Nginx或HAproxy就是第一选择,此时这些东西上手快, 配置容易,在七层之上利用HTTP协议就可以。这时是第一选择。
第二阶段:随着网络服务进一步扩大,这时单点的Nginx已经不能满足,这时使用LVS或者商用Array就是首要选择,Nginx此时就作为LVS或者Array的节点来使用,具体LVS或Array的是选择是根据公司规模和预算来选择,Array的应用交付功能非常强大,性价比也远高于F5,商用首选,但是一般来说这阶段相关人才跟不上业务的提升,所以购买商业负载均衡已经成为了必经之路。
第三阶段:这时网络服务已经成为主流产品,此时随着公司知名度也进一步扩展,相关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。
最终形成比较理想的基本架构为:Array/LVS — Nginx/Haproxy — Squid/Varnish — AppServer。
6、示例(Centos7下通过四层代理LVS转发请求)
因为7层代理使用比较多,本文便不再演示示例(七层代理进行了两次TCP请求),本文主要演示下四层代理示例(四层代理只进行了一次TCP请求,性能高)。
6.1 测试环境
客户端: 10.20.31.135 四层代理LVS: 10.20.31.133 真实上游服务实例:10.20.31.106:30000
6.2 加载Ipvs(10.20.31.133机器)
yum install ipset ipvsadm -y ipvsadm -l -n cat >> /etc/sysconfig/modules/ipvs.modules << EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_sh modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- nf_conntrack_ipv4 EOF chmod +x /etc/sysconfig/modules/ipvs.modules ./etc/sysconfig/modules/ipvs.modules
查看模块是否被加载:
6.3 配置LVS代理规则(10.20.31.133机器)
配置LVS代理规则前先检查当前机器环境,ipvs和iptables规则均为空。
配置LVS代理,访问代理机器(VIP:10.20.31.133)30000端口,通过IPVS NAT模式将服务转发到真实上游服务实例(10.20.31.106)30000端口上。
[root@xx ~]# ipvsadm -A -t 10.20.31.133:30000 -s rr [root@xx ~]# ipvsadm -a -t 10.20.31.133:30000 -r 10.20.31.106:30000 -m [root@xx ~]# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.20.31.133:30000 rr -> 10.20.31.106:30000 Masq 1 0 0
使用客户端10.20.31.135访问代理服务10.20.31.133:30000。
不通,对代理服务器和真实服务实例机器进行抓包分析,可以看到代理设备在接收到第一个来自客户端的SYN 请求时,即按照代理策略选择被代理的后端服务器,并对报文中目标IP地址进行修改(改为后端服务器IP),直接转发给该服务器:
再访问一次,通过查看TCP随机生成端口,LVS代理服务就像路由器一样,只是转发请求。
由此可以得出,TCP连接建立,即三次握手,实际上是客户端和后端服务器建立的,代理设备只是起到一个类似路由器的转发动作。
对于客户端没有响应是因为,在代理服务器只是进行了目标地址转换,数据包到了真实服务实例机器时,源地址是客户端地址,目标地址是真实服务实例机器地址,那么真实服务实例机器回包时源地址是真实服务实例机器地址,目标地址是客户端地址,由于客户端收包时发现发送包的源地址变了,不再是代理服务地址了,所以拒绝收包,相当于给张三发信,李四回的信,显然不受信任。这时候为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。
对于客户端发来的包进行源地址转换,这样到达真实服务实例机器时,包的源地址是代理服务机器IP,这样真实服务实例机器IP回包会先回到代理服务机器。
[root@xx ~]# iptables -t nat -A POSTROUTING -s 10.20.31.135 -j MASQUERADE [root@xx ~]# iptables -t nat -nvL Chain PREROUTING (policy ACCEPT 2 packets, 128 bytes) pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 2 packets, 128 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 MASQUERADE all -- * * 10.20.31.135 0.0.0.0/0
客户端再次访问10.20.31.133:30000服务,发现到达真实服务机器的包的源地址并没有进行转换!!!
这时候请检查内核参数net.ipv4.ip_forward值,如果值为0,请设置为1。
[root@xx ~]# sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 0 [root@xx ~]# sysctl -w net.ipv4.ip_forward=1
启用 net.ipv4.ip_forward 使得内核能够在不同网络接口之间转发数据包,这是确保 iptables 中的 SNAT 规则能够生效的关键。禁用 IP 转发时,数据包不会通过 NAT 表的 POSTROUTING 链,因此源地址转换不会发生,即使配置了 SNAT 规则,数据包也不会应用这些规则。
这时候客户端再次访问10.20.31.133:30000服务,还是同样问题,发现到达真实服务机器的包的源地址并没有进行转换!!!
代理节点的iptables日志为空:
[root@xx anaconda]# pwd /var/log/anaconda [root@xx anaconda]# cat syslog | grep 'int32bit ipvs' [root@xx anaconda]#
也就是说,ipvs的包根本不会经过iptables nat表POSTROUTING链?网上查了下内核参数需要开启net.ipv4.vs.conntrack。
sysctl net.ipv4.vs.conntrack=1
开启后,再次抓包,发现通了。
通过以上示例可以清晰知道,对于四层代理LVS,TCP连接建立,即三次握手,实际上是客户端和后端服务器建立的,代理设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。(这就是为什么LVS性能高的原因)
7、总结
四层是TCP层,使用IP+端口的方式。类似路由器,只是修改下IP地址,然后转发给后端服务器,TCP三次握手是直接和后端连接的。只不过在后端机器上看到的都是与代理机的IP的established而已。
7层代理则必须要先和代理机三次握手后,才能得到7层(HTT层)的具体内容,然后再转发。意思就是代理机必须要与client和后端的机器都要建立连接。显然性能不行了,但胜在于七层,能写更多的转发规则。
所以在生产环境中为了实现业务系统的高并发,链路一般都是四层代理->多个七层代理(水平扩容)->业务服务。
参考:4层代理和7层代理的区别