背景

起因是钉钉群内发现大量告警

查看集群状态,发现node状态在ready和notready之间反复横跳,有问题的node都是某地区IDC机房的节点,集群跟该地区IDC节点组网使用基于WireGuard协议的应用,节点间通信依赖公网出口。

问题定位

agent组网节点检查

检查组网节点是否工作正常

发现是agent节点出现无法连接中继节点或者直连master节点,所以有可能是网络问题

机房公网流量检查

查看机房公网流量出口,发现公网的出流量把带宽都占满了,可以确定是有人把公网出流量占满了,导致集群组网出现问题,从而出现节点notready的情况

排查

集群内的公网流量分为:

  • 内部流量:各个pod、node之间相关访问的流量(因为有组网,所以这些内部流量也是走公网出口)
  • 外部流量:集群中的工作负载通过网关访问公网

内部流量排查

集群中内部组网使用了agent节点,所以该机房中的内部流量都会走该agent出去,查看其流量趋势

发现流量数据还算正常,排除集群内大流量的问题

外部流量排查

集群使用kube-ovn CNI,外部公网流量分为集中式网关和分布式网关两种方式。

  • 集中式网关用的是 vpc-nat-gateway + multus-cni ,它会把节点上面的网卡加入到对应pod上面,所以可以通过查看对应节点的网卡流量情况得出该网关的流量情况。

  • 分布式网关是pod访问公网时,流量会经过pod所在节点的网卡,走节点自身的网络。

因为集群里面的节点都安装了node-exporter,所以可以使用pmql来定位哪个节点的网卡出流量最多

# 3小时内,平均发送数据(MB)top5的网卡信息
topk(5, sum by (instance,device) (rate(node_network_transmit_bytes_total{device!~"lo|veth.*|docker.*|br.*"}[3h]))) / 1024 / 1024

结果发现有一张网卡的流量十分高,定位到是一个集中式网关的节点,上面的网卡被用来做网关的公网出口网卡了,所以可以确定大流量的应用就在这个网关后面。

在集群中使用集中式网关的都会给它分配一个EIP资源,同时集群里面也有对应的exporter来收集EIP的流量使用情况,所以可以继续使用对应的pmql来定位对应的EIP资源。

# 内部查看eip流量的pmql,仅供参考
topk(5, sum by (eipName) (rate(xxx_eip_network_traffic_egress_bytes{xxx}[3h]))) / 1024 / 1024

在成功定位到有问题的EIP后,后台马上找到了对应的资源,是一台裸金属。

这台裸金属在1个月前因初始配置不当导致未授权访问,并被修改了密码,在修改密码后就可以登录回去了。但是因为上面有一些虚拟机应用在跑,所以没有选择重装系统,而是重装了部分核心软件,并检查和清除相关入侵痕迹。所以可以确定是裸金属被黑了导致出流量激增,不是因为相关业务。

处理

这里处理分为两步:

  • 对应的同学备份虚拟机和系统上面的重要数据,确保系统可以重装
  • 对裸金属进行临时处理,并且看一下是否可以找到对应的问题

裸金属处理

流量查看

通过iftop查看实时流量,发现随机向多个IP发送大流量数据

使用tcpdump进行抓包查看相关数据,发现流量会访问目标ip的80或443端口,并且会一直发送SYN包

综上所述,这台服务器是被人拿来做肉鸡,对公网服务发起SYN洪水攻击

临时处理

为避免进一步影响业务,临时用tc给系统限速,确保不要再发送大流量把系统公网带宽占满。要求:业务ip流量不限制(ssh登录ip、虚拟机的业务流量),只限制异常流量(所有ip的80、443端口出流量)。

# 清空对应网卡旧规则
# tc qdisc del dev enp1s0 root

# 添加qdisc,并且默认归类为 1:20 的规则(没有匹配到规则的流量走 1:20 )
# tc qdisc add dev enp1s0  root handle 1: htb default 20

# 添加class规则
# tc class add dev enp1s0  parent 1: classid 1:1   htb rate 20Mbit ceil 20Mbit burst 15k
# 异常流量限速规则
# tc class add dev enp1s0 parent 1:1 classid 1:10 htb rate 1Mbit ceil 1Mbit burst 1k 
# 其它流量规则
# tc class add dev enp1s0 parent 1:1 classid 1:20 htb rate 20Mbit ceil 20Mbit burst 15k

# 为了避免一个会话永占带宽,添加随即公平队列sfq
# tc qdisc add dev enp1s0  parent 1:10 handle 10: sfq perturb 10 
# tc qdisc add dev enp1s0  parent 1:20 handle 20: sfq perturb 10  

# 添加filter来应用class规则,这里是目标端口为80、443的都到 1:10的class 中
# tc filter add dev enp1s0  protocol ip parent 1:0 prio 3 u32   match ip dport 443 0xffff   flowid 1:10 
# tc filter add dev enp1s0  protocol ip parent 1:0 prio 2 u32   match ip dport 80 0xffff   flowid 1:10

# 规则检验
# tc qdisc show dev enp1s0
# tc class show dev enp1s0
# tc filter show dev enp1s0 

# 数据统计 查看有多少流量命中那些规则
# tc -s class show dev enp1s0
# tc -s filter show dev enp1s0 

限速后,公网流量恢复正常,集群节点状态恢复。

排查

直接说结论,还没有排查出来问题系统就被重装了,所以怀疑是有问题的进程被替换成正常的进程程序了。😥

这里说一下排查思路和过程:

  • 重新安装基础命令工具(ps、ss、lsof等)
  • 使用 iftop 持续监控流量
  • 使用 ss、ps、lsof 定位可疑进程:
    • 未发现可疑进程与攻击IP的连接
    • 发现几个异常公网ip的VNC-console连接,禁止相关IP访问后重启libvirt服务,问题仍存在
  • 检查系统日志、登录日志、操作日志、安全日志及内核日志
  • 检查iptables配置,确认无异常丢弃ACK/FIN包规则
  • 检查定时任务、启动脚本、可疑用户及登录信息
  • 检查虚拟机内部流量,确认正常
  • 使用Rootkit工具进行全面检查

值得注意的是,上述排查后发现,自上次修改密码后,系统无任何可疑IP登录记录,怀疑攻击者在初次入侵时植入了持久化后门或恶意程序。

最后在其他同学备份好相关文件后,对系统进行了重装。

总结

在经历了上述事件后,还是要加强以下两点:

  • 系统暴露在公网环境下,最好是不要用弱密码(用密钥或者强密码)并且要开启防火墙,限制可以登录的ip白名单。
  • 要精细化监控告警,像上述的问题都是通过PMQL来定位的,这样完全可以编写对应的告警规则,在出现相关问题的时候,第一时间可以定位到对应的资源,加快故障恢复速度。