LVS-TUN模式集群在开启防火墙情况下的一次调试之旅

目录

一、集群说明二、预备知识三、问题描述四、排查流程五、回顾总结

一、集群说明

  • OS: CentOS7.2
  • DS(LVS): 10.1.61.114
  • LVS-MODE: TUN
  • VIP: 10.1.61.82
  • RS1(Nginx): 10.1.62.105
  • RS2(Nginx): 10.1.62.106
  • PORT: 80
  • 防火墙: DS、RS1、RS2均安装 firewalld,且开放80端口(tcp,udp)

二、预备知识

  1. firewalld 是 iptables 的前端控制器,用于实现持久的网络流量规则。

  2. firewalld 自身并不具备防火墙的功能,而是和 iptables 一样需要通过内核的 netfilter 来实现,也就是说 firewalld 和 iptables 一样,他们的作用都是用于维护规则,而真正使用规则干活的是内核的 netfilter,只不过 firewalld 和 iptables 的结构以及使用方法不一样罢了。

  3. netfilter 有五链四表,说明如下。
    五链:

    • PREROUTING:数据包进入路由表之前
    • INPUT:通过路由表后目的地为本机
    • FORWARD:通过路由表后,目的地不为本机
    • OUTPUT:由本机产生,向外转发
    • POSTROUTIONG:发送到网卡接口之前。

    四表:

    • filter表,负责过滤数据包,也就是防火墙实现"防火"的功能,iptables命令中如果没有指定 -t,即默认为此表。filter表中只有OUTPUT/FORWARD/INPUT链。
    • nat表,实现网络地址转换的表。可以转换源地址、源端口、目标地址、目标端口。NAT表中的链是PREROUTING/POSTROUTING/OUTPUT。
    • mangle表,拆解报文,做出修改,并重新封装。mangle表中包含所有的链。
    • raw表,加速数据包穿过防火墙的表。只有PREROUTING/OUTPUT表。
  4. 四个表的优先级由高到低的顺序为:raw → mangle → nat → filter,比如说 PRROUTING 链上,即有 mangle 表,也有 nat 表,那么先由 mangle 处理,然后由 nat 表处理。

  5. Linux 上的防火墙是由 netfilter 实现的,但是 netfilter 的功能不仅仅只有“防火”,一般可以认为“防火”的功能只是 filter 表的功能。

    了解上述知识后,我们可以吧数据包通过防火墙的流程总结为下图。

    特此说明:图片借用自朱双印博客,这位大佬的博客里有一套 iptables 系列教程,想学习详细知识的可以直接去他博客看,链接:www.zsythink.net
    特此说明:图片借用自朱双印博客,这位大佬的博客里有一套 iptables 系列教程,想学习详细知识的可以直接去他博客看,链接:www.zsythink.net

三、问题描述

集群部署完成后,访问 VIP:PORT 遭到拒绝(Connection refused)。

直接访问 RS1:PORT 和 RS2:PORT 均可以正常访问 Nginx 服务(由于我未写入index.html,所以返回404页面是正常现象)。

四、排查流程

关闭 DS 防火墙,未解决问题。恢复开启 DS 防火墙后,再尝试关闭 RS1 防火墙,RS1 服务正常返回,RS2 依旧是连接拒绝。

猜测 Client → DS 这条链路是正常的,问题出现在 DS → RS 这条链路上。

恢复开启 RS1 的防火墙,登陆至 DS 机器上,使用命令ipvsadm -L -n查看连接状态来验证猜想。

ipvsadm -L -n 命令结果小科普:
对于 TCP 协议而言,ActiveConn 列是活动连接数,也就是tcp连接状态的 ESTABLISHED ,而 InActConn 列是指除了 ESTABLISHED 以外的,所有的其它状态的 tcp 连接。

当前 InActConn 和 ActiveConn 均为0。

在 Client 端继续使用命令for i in {1..100}; do curl 10.1.61.82:80; sleep 0.5; done循环请求 VIP:PORT,然后在 DS 上使用命令ipvsadm -L -n再次查看连接状态。发现 InActConn 数值发生了改变,说明 DS 是收到了 Client 端的数据包的,ActiveConn 为0是因为 DS → RS 被拒,所以 tcp 连接未能建立。

目前已定位到数据包出现问题的链路是在 DS → RS ,OK,那就抓个包看看呗。

在DS上使用命令tcpdump -i any host 10.1.62.105截获 RS1 收到和发出的所有数据包(在 Client 依然用老方法循环请求 VIP:PORT ),可以看到 DS 发给 RS1 的数据包被 RS1 用一个协议为 ICMP 的数据包拒绝了。等等,这个数据包的内容咋这么眼熟(ICMP host prohibited),好像用 iptables 查看规则时见过。

我马上登陆到RS1,直接用命令iptables --line -vnL INPUT查看 INPUT 链中的规则(--line可显示规则的编号,数据包在链中是顺着规则编号往下逐步匹配的;-v显示详细信息;-n不解析IP地址;-L指定链名;不指定-t默认显示 filter 表)。

可以看到第七条 REJECT 规则就是用 icmp-host-prohibited 作为数据包内容拒绝的。啊哈?DS 发给 RS1 的数据包被最后一条规则匹配到了?为什么没被前面的规则处理掉?我不是开启了80端口吗?

虽然一堆疑问,不过还是先确认下 DS 发给 RS1 的数据包是不是真被第七条规则匹配处理了。这里我采用的方法是,在 Client 端循环请求 VIP:PORT 的前后分别用命令iptables --line -vnL INPUT查看第七条规则的 pkts(该规则匹配到的数据包数量)数值是否发生了变化,果然 pkts 发生了增长,说明数据包真的是被第七条规则匹配到并且 REJECT 掉了。

额,我用命令iptables --line -vnL查看了所有 Chain(链) 的规则,找到我开放80端口的那两条规则又确认了一下,发现 dport 是80,协议为 tcp 的那条规则 pkts 一直是0,并没有变化(这条规则在 INPUT 链中是被第五条规则匹配的,规则虽然是在 IN_public_allow 链的,但了解过 iptables 自定义链相关知识后,就会明白这实际上是一个调用链的关系:INPUT_ZONES → IN_public → IN_public_allow,从下图的每个 Chain 的 target 也能看出来)。

再次确认下,这条规则源地址、目标地址、端口、协议等等都没有问题,而且最开始我也直接访问 RS1:PORT 确认过 Nginx 服务是没有问题的,可以正常返回,所以我怀疑从 DS → RS1 的数据包并不是一个 tcp 包,所以没有被此规则匹配并处理。

然后又返回去查了下 LVS-TUN 模式的数据包处理流程。

ipvs 工作在 INPUT 链,它在原有的 IP 报文外再次封装多一层 IP 头,内部 IP 头 (源地址为 CIP,目标 IP 为 VIP),外层 IP 头 (源地址为 DIP,目标 IP 为 RIP),然后将封装好的数据包从 DS 发往 RS 。

到这,我已经恍然大悟了,它确实不是一个 tcp 包,再翻到之前从 DS 上抓取 RS1 的数据包内容,可以看到 DS → RS1 的数据包协议为 ipip-proto-4。

所以,处理方法也很明确了,放行这个 ipip 协议的数据包。我的处理方法是在 RS1 上使用命令iptables -t filter -I INPUT -p ipv4 -j ACCEPT增加一条对所有协议类型为 ipip 的数据包ACCEPT的规则(这里的 prot 显示的 4 代表 ipv4 的协议号,想要查看协议名与协议号的对应关系可以在这里查找Protocol Numbers)。

记住一定要在 INPUT 链第七条之前,我这里是直接插入到了第一条,我之前看一篇博文上用的是-A INPUT,这表示 append(追加) 一条规则,会出现在最后,这样设置的规则数据包根本就匹配不到,因为它已经被在你前面的那条REJECT规则匹配并拒绝掉了。

最后我们再从 Client 端请求验证一下规则是否生效,可以看到 RS1 已经正常返回了,且 RS1 上的第一条规则 pkts 也发生了增长,说明数据包已被匹配且正确处理。

RS2 也设置相同的过滤规则,然后再次验证,两台 RS 均正常返回,over。

五、回顾总结

  1. 很多搭建 LVS 集群的文章都会前置声明关闭防火墙或者使用iptables -F命令将 iptables 规则清空,以免发生通信问题。实际上大多数情况下你确实可以这样做,但是万一生产环境就要开防火墙呢,万一设置的某几条 iptables 规则非常重要,你啪一条命令给人全清了,是不是得写个事故报告。

  2. 我的排查流程真的是像文章中一样如此顺利吗?其实并不是,因为这个问题出现时,我既不清楚 iptables 相关知识(一两年前简单的看过,然后忘光了),也不清楚 ipvs 的工作原理,就是拿来主义,所以刚开始排查的时候和无头苍蝇一样,一顿瞎比操作,后来还是滚回去补了 iptables 和 ipvs 的相关知识。所以其实排查流程中的第4步开始都已经是第二天的事了。

  3. 如果懂了 iptables 相关知识(五链四表、规则管理、匹配条件、扩展模块、自定义链等等)。清楚命令及命令结果中每个参数的意思非常重要,像遇到此类防火墙问题,你都可以用文中的排查流程去走一遍,无非就是规则匹配问题。

  4. 分析网络问题,简单的抓包可以达到事半功倍的效果,配合 Wireshark 一起食用味道更佳。

猜你喜欢

转载自juejin.im/post/5df757556fb9a016323d7d8c