FireWall Mark + LVS

+======================================================================
张贺,多年互联网行业工作经验,担任过网络工程师、系统集成工程师、LINUX系统运维工程师
笔者微信:zhanghe15069028807,现居济南历下区
+======================================================================

FireWall Mark + LVS

为了解决什么问题?

我们在之前讲过,如果不使用SSL层的话,会不安全,数据包内的数据都是明文,比如我就曾经在我们公司的路由器上做了一个端口镜像,然后就把公司所有人的OA和企业邮箱账号和密码都给抓出来了;如果使用了SSL层,安全性会提高一些,数据不再是明文传输,但是速度会慢一些,慢的原因很简单呀,SSL层本来就不属于OSI七层参考模型,如果要使用HTTPS就必须把SSL层加到应用层和会话层之间,七层变八层了,数据向下封装的步骤就多了一步。其实HTTP速度慢的原因我认为有以下几点:

  1. 使得三层握手的时间更长了,使用SSL层之后,在三层握手和传输正式内容之前又多了一步:服务器要把证书文件发送给客户端
  2. 客户端要通过内置CA证书验证服务器的证书,验证好之后还要用证书里面的公钥加密要传输的内容。
  3. 服务器端收到客户端的报文之后,还要通过私钥文件解密内容。

世上安得两全法,不负如来不负卿。我们要寻找一种更好的办法来平衡好安全问题和速度问题,生活中这样的问题实在是太多,比如:不戴金箍,如何救你;戴了金箍,如何爱你,有点跑题了,我们接着说技术,如果平衡呢?一中庸之道就出来了,外国人称之为“第三选择”,比如,我们在浏览网站商品的时候使用http,但是登录的时候就会跳转成为https,这种意味着网站必须同时提供了80和443两种服务,拓扑图可能是这样的,如下所示:

LVS同时提供了两个集群的负载均衡,它的ipvsadm规则应该是这么写的:

//http集群
ipvsadm -A -t 192.168.80.99:80 -s sh
ipvsadm -a -t 192.168.80.99:80 -r 192.168.80.11:80 -g
ipvsadm -a -t 192.168.80.99:80 -r 192.168.80.12:80 -g
//https集群
ipvsadm -A -t 192.168.80.99:443 -s sh
ipvsadm -a -t 192.168.80.99:443 -r 192.168.80.11:443 -g
ipvsadm -a -t 192.168.80.99:443 -r 192.168.80.12:443 -g
[root@lvs ~]# ipvsadm -Ln
TCP  192.168.80.99:80 sh
  -> 192.168.80.11:80             Route   1      0          0         
  -> 192.168.80.12:80             Route   1      0          0         
TCP  192.168.80.99:443 sh
  -> 192.168.80.11:443            Route   1      0          0         
  -> 192.168.80.12:443            Route   1      0          0         

其结果就是A客户端访问HTTP集群时,LVS会通过SH算法给A客户端分配一个R-SERVER1,以后A客户端再次访问V80端口时就一直是R-SERVER1给客户端A服务;而B客户端访问的是443端口,通过SH算法依然可能将B客户端分配给R-SERVER1,因为SH算法是静态算法并不考虑服务器的负载,仅仅通过算法本身进行转发,这就可能导致在R-SERVER1的负载过重,而R-SERVER2可能会一直闲着,如何进行平衡一下呢?

除了平衡问题之外,还有一个问题,A客户端浏览商品和向购物车当中加商品时通过80端口集群被分发到R-SERVER1上,但当A用户想登付款时,这时用户会通过HTTPS访问,结果由于是两个集群各自通过算法分发,把A用户又给分发到R-SERVER2上去了,R-SERVER2上并没有A用户的缓存记录,结果用户登录上之后发现购物车里面的商品全都不见了!!可能你会说,不是通过SH算法吗?源地址哈希怎么还能把同一个用户不同请求调度到不同的R-SERVER上呢?当A客户端访问的是80端口时保持连接没有问题,但是当A客户端用443端口访问时,这对于LVS的443端口集群来说这是一个新的用户请求,A用户之前通过80端口访问的连接记录在80集群的缓存上保存着呢?443端口集群没有呀!所以就会出现上述情况。

对于R-SERVER负载不平衡的问题,有的同学可能会说,换一个动态算法不过完了吗?这不行呀,LVS支持的10种算法里面,只有SH算法能保持连接,那怎么办呢?

解决办法其实也好简单,我们只要把两个集群合并成为一个集群,然后统一进行调度不就行了吗?可是一个集群是80,另一个集群是443,如何合并呢?这个时候我们就要用到iptables当中mangle功能了。

iptables mark

lvs的ipvs函数位于net-filter架构当中的input函数上,我们在input函数的前面,也就是prerouting上将访问VIP的80端口和443端口的都打上一样的标记,就类似于交换机上的tag;然后我们再通知ipvs函数,不让它根据报文当中的IP+端口的方式强行改道了,而是根据标记强行改道,只要报文上有这个标记的,统统改道到postrouting上,这样同一个用户无论访问的是80端口和还是443端口,都会统一通过一个SH算法调度到同一台R-SERVER上,并提高了缓存命中率,有效的解决了用户在将商品加入完购物车之后付款时商品丢失问题,而且因为是一个集群,所以也不会出现两个集群通过不同算法调度导致R-SERVER负载不平衡的问题。

通过iptables打标记的方式与模型没有关系,任何模型都可以使用。

理解了原理之后,我们再做配置就简单多了,我们直接上配置,关于iptables的使用这时不讲,有兴趣的同学可以去看一下我这篇博文: https://www.cnblogs.com/yizhangheka/p/12356781.html

//先在LVS上把VIP搞出来
ifconfig eth0:0 192.168.80.99 netmask 255.255.255.255 broadcast 192.168.80.99

//查看一下网卡
[root@lvs ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.80.10  netmask 255.255.255.0  broadcast 192.168.80.255
eth0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.80.99  netmask 255.255.255.255  broadcast 192.168.80.99
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
//在LVS的prerouting上对目标是VIP的80和443商品统统打上一样的标记3,其实是几都无所谓
iptables -t mangle -A PREROUTING -d 192.168.80.99 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 3

//然后再通知ipvs函数通过mark来区分
[root@lvs ~]# ipvsadm -A -f 3 -s sh
[root@lvs ~]# ipvsadm -a -f 3 -r 192.168.80.11 -g
[root@lvs ~]# ipvsadm -a -f 3 -r 192.168.80.12 -g
[root@lvs ~]# ipvsadm -Ln
FWM  3 sh
  -> 192.168.80.11:0              Route   1      0          0         
  -> 192.168.80.12:0              Route   1      0          0        

其实现在网站大多数都是全栈https,虽然速度可能会慢一些,但可以通过其它的手段来弥补,比如加缓存、比如上SDN,这些都是很常见的的加速方法。

下面我们再来介绍一种加速方法“卸载https”,这是如何实现的呢?卸载https的详细过程和步骤我会在nginx代理那一篇博文里面详细讲一讲,这里不多说,仅做一个简单的介绍,所谓的卸载https就是客户端和LVS服务器之间通过全部通过HTTPS建立连接,而LVS服务器和WEB集群之间全部通过HTTP协议通信,速度快嘛,如果LVS服务器和WEB集群之间还要通过HTTPS通信,那得多慢呀!可惜的是,LVS无法实现这种功能,为什么无法实现呢?想要实现卸载https的功能就得需要LVS服务器充当客户端向WEB集群请求,然后LVS再回复给客户端,这就要求LVS服务器的用户空间进程要侦听80端口,而LVS是内核的功能,无法侦听任何套节字,所以就无法实现披卸载https的功能。

posted @ 2020-02-26 16:52  张贺贺呀  阅读(354)  评论(0编辑  收藏  举报