[关闭]
@gaoxiaoyunwei2017 2020-10-13T08:13:22.000000Z 字数 5196 阅读 570

巧用抓包神器 Tcpdump 解决各种生产问题

未分类


说明:本文根据高效运维最新一期线上小课堂整理而成。

作者简介
宋广明,高效运维社区资深 DevOps 专家,从事运维工作多年,熟悉 Linux 系统管理、公有云、产品运维、监控、持续交付等相关工作。

今天跟大家分享一些 Tcpdump 的应用案例。通过 Tcpdump 学习网络协议,验证一些配置,还有解决一些实际问题。

安装及用法

首先我们先看一下安装和用法,安装在 Linux 下是非常简单的,可以通过 yum、dnf、apt-get 去安装,这个很简单,不做过多介绍。

以下是它的基本用法,

屏幕快照 2020-09-04 下午4.22.02.png-83.9kB

第一是基于IP抓包,就是基于源IP又是基于目标IP抓包;第二个是基于源IP抓包,第三是基于目标IP抓包,第四个是基于网段抓包,第五个是基于端口范围抓包,第六个是基于源地址和目标端口抓包,第七个是基于某种协议抓包,这里有抓 FTP 相关的数据包。

屏幕快照 2020-09-04 下午4.29.19.png-57.1kB

这个是找到明文密码,这是一个命令的组合,Tcpdump 去抓 HTTP、FTP、SMTP,通过管道输出传给egrep,egrep 去查关键字,然后就能得到密码了。所以明文传输没有加密是很不安全的。

  1. tcpdump -nn -v -i eth1 -s 0 port 443

这个命令就是抓 HTTPS 的包,默认情况下如果没有改的话就是 443,我们一般情况下可以通过命令去验证我们的传输是不是加密了。举个例子,比如说内部系统跟 LDAP 集成了,前端有 LB,这样加密是分成三段,第一段是从客户端到 LB,第二段是从 LB 到后台的 real server,第三段是从 real server 到 LDAP server 这段也要加密。

一般情况下,假如从客户端到 LB 没有加密,那么就在浏览器端我们看到比如说这个链接是不安全的,但是如果是 LB 客户端做了加密,但是 real server 到 LB 这段没有加密,那其实这个密码还是可以抓到的,所以说 HTTPS 加密过程要是全链路的,有任何一段没有加密就可能被抓过来,这个大家有兴趣可以自己去试一下。

我记得当时那个应用有个字段叫[00:04:04],字段后面存的是明文密码,如果你用 HTTPS 加密的话,那段数据就显示全部都是 TLS、VER,VR 都是加密过的数据,这个看不到密码的。

通过 tcpdump 找到对应的交换机端口

  1. Tcpdump -nn -v -i eth1 -s 1500 -c 1 'ether[20:2] == 0x2000'

这块是通过 Tcpdump 找到对应交换机的端口,这个命令我认为是一个非常实用的命令,因为有一些情况我们总要找到服务器对应交换机哪个端口,一种方法是可以请网络管理员上交换机上查一下,另外就是我们自己去机房顺着网线一直找到交换机对应的端口。

这两种方法尤其是第二种都很麻烦,如果我们有了这个命令,这个信息可以输出你当前所连交换机的名字,还有连接交换机的端口,这些信息都有,这些我就列出来了,我觉得这个命令还是比较实用的。

更多的用法我们可以参考Man Tcpdump就可以了,这里面有更多的介绍。

应用场景分享

分享一:解决 DNS 问题

下面介绍一下应用场景。第一个问题解决 DNS 问题,背景是,当时办公室用 MAC 笔记本的同事配置了两个DNS ,突然有一天说,解析域名出现错误了,然后错误提示:

  1. Got recursion not available from 192.168.0.100, try next server

就是说这个不能查询了,这个时候我们通过 Tcpdump 抓包就可以去找到这个问题是什么原因。

下面是它的命令,这个命令很简单,抓 53 端口就可以了。

  1. tcpdump -i en0 -vvv -s0 port 53

最后一轮我们发现,因为 dns server A 可以正常解析,dns server B 不能提供解析。

dns B 不提供办公室的递归查询,仅仅返回了该域名的 NS 记录,也就是迭代查询。解决办法就是将该办公室的 IP 网段加入到 dns B 的递归查询白名单里面,然后把 DNS reload,问题就解决了。

其实现在看这个问题其实很简单,尤其对于 DNS 特别熟的人,可能一下就知道是什么问题,不用抓包去解决,但是可能当时还不是那么熟悉,所以说也是印象比较深刻,总结了三点。

第二问题解决 DB 连接的问题。背景是生产服务器 Mysql Slave 定时会生成一些文件,然后通过 rsync 把生成文件拷贝到其他应用服务器上面,rsync,因为它是 Mysql Slave,所以通过还提供了只读的服务,也是突然之间就发现某天 Mysql Slave 连接超时了,之前是没有的,这种情况有监控看监控,然后顺带抓包看看,这个其实也是抓3306 的包,跟前面有点类似。

故障现象,当 rsync 拷贝数据到其他机器的时候,带宽就满了,然后连接就超时了。

初步得到结论,rsync 拷贝数据到其他机器的时候,带宽满了,因为带宽被占满,导致 Mysql 连接超时。初步解决办法增加服务器带宽。

但是这个问题不是跟想的那么简单,因为服务器数量没有变,rsync 拷贝命令也没有变,文件大小也没有变,所以说什么都没有变,关键是之前是一直可以正常工作的。还有一个问题,之前带宽也是满的,那Mysql也没有超时,所以很显然不是问题的根本原因。

所以只能继续查找问题,说实话这个问题也不太好找,现象就是带宽满的时候数据库连接会超时,带宽不满的时候连接不超时,这就是现象。所以说很容易让人想到它跟带宽满有关系。但是不好解释的是之前带宽满它就没有超时,所以说想来想去可能跟 Linux QOS 有一定关系。

继续找了一个问题发现,我们通过 Tcpdump 抓包还是有些发现,我们发现 rsync 的tos值和默认值不一样,我们发现因为rsync的QOS比Mysql的高了,所以造成Mysql的流量需要一直等待,等待rsync完成了才轮到Mysql这边流量被系统处理。

所以说这个问题找到了,首先rsync的优先级不一样,是因为sshd的配置文件被改了,导致SSh的应用tos优先级变高了。因为rsync是用ssh这种方式传输的,所以说ssh的tos变高了,相当于 rsync 的 tos 也变高了。

Linux QOS 默认的策略就是先处理高优先级的任务,低优先级的必须等待高优先级处理完成才会被处理。这个时候就很好解释了,之前为什么带宽满了可以正常工作,那后来带宽满了就不能工作了,其实之前它们优先级都是一样的,不用等,Mysql 不用等,后来优先级 rsync 变高了,所以 Mysql 必须要等。

关于 Linux 高级路由和流量控制这块,咱们可以参考一下官方上大家可以搜索 Linux 的高级路由和流量控制这块就可以了。

所以说这个问题,当你解决这个问题你发现这个问题其实很好解决,很简单,但是你当时没有解决的时候发现很不好找,所以我在总结一下这个问题,就是因为ssh配置被改了,导致ssh的tos值变高了,优先级变高了,Linux的QOS策略先处理的rsync的流量,然后再处理了 Mysql 的流量。

那解决办法就是通过我们和相关修改sshd的配置文件团队成员,问一下原因,后来他把配置文件还原了,这个问题就彻底解决了,也没有加带宽,也用也都恢复正常了,这个是第二个分享。

分享三:应用连接超时

第三个分享,也是应用连接超时的问题,就是生产环境某应用服务一直稳定运行。突然某天开始不定时超时错误,开始不定时的,log 里面也没有相关的日志,因为为了查这个问题还特意发了一版,把 debug 日志打开了,最后也没有发现有价值的线索,后来我们用了 Tcpdump 的抓包分析问题。

这个问题其实就比较好找了,因为我们当时抓包的时候发现,有好多大量的 tcp retransmission 这样的连接,你点开进去发现对应都是统一的IP和端口,因为这个有些问题我没有办法重现,所以没有办法截图,这个 tcp retransmission 链接,如果把抓包的结果存到本地分析的时候都是黑的,所以很明显快速过一下就知道这种连接tcp retransmission 全部都是黑的,很明显你能够看见的。然后发现同一个IP和端口,这个时候就怀疑是不是网络有问题,然后这个时候我们把问题反馈给网络组,网络组的同事找了半天最后终于在日志里面找到了,后来找到问题根本原因,是因为防火墙他们更新了,更新的防火墙有设置把 tcp 断连接掉了,所以说这个就是这个问题的根本原因。

对这个问题的总结,因为应用是使用的是长连接连的DB数据库,然后因为网络部门更新了防火墙策略,然后里面有一条策略是把空闲时间超过1小时的 tcp 连接关掉,应用端是按需连接DB的,并不清楚连接池里面的连接是不能用的,因为它是长连接,认为这个连接是一直可以用的,所以说每次连DB的时候,还是这个tcp连接,这就是为什么时不时就报错了。如果是一个新的连接,如果在一个小时之内保持激活,这个时候就不会出现这个问题了,所以说这个问题相对于前面第二个问题其实还是比较好发现的,用这个抓包工具确实能够提供一些有价值的线索,因为有些时候你怀疑是这个问题,但是你没有明显的证据的话,也不太好找,可能我这边没有什么改动,我这边很正常,什么都没有改,那你可能把这个问题提供给对方之后,可能更能够加速这个问题被解决了,咱们还是想把这个问题快点解决了,因为毕竟这个是生产环境,所以说这个场景比上一个场景简单,但是这个场景给我们提供了比较有利的证据,比较有说服力的证据,而且确实能够快速帮我们定位问题和解决问题的。

分享四:会议掉线

还有一个分享就是会议掉线。这个背景我介绍一下,有一个会议系统分了手机端、固定电话端和IP电话端入会,IP电话端就是用IP,然后入会的接入场景是语音的网段系统是一个集群系统。

这个现象在入会时,IP端是不会掉线的,手机端或是固定电话端通话一分钟左右就会掉线,这个问题也是我们能够找log的时候就找log,如果没有找log实在没有办法的情况下,只能是通过抓log。

  1. tcpdump -i eth1 -t -n -s 0 port 5060

这个也是抓 5060 的包,这个也是通过端口来开包。

这个问题其实有一个区别,IP电话端入会是直接访问接入层,手机端还有固定电话端是通过语音转了一下,然后到开源接入层,语音的集群负载均衡。

我们一开始提示找这个问题的时候,抓包的时候也没有发现什么问题,因为这个包抓完说实话也挺长的,也不太好找这个问题,但是没有办法有问题就要尝试多方面尝试解决,然后最后发现,我们想的办法手机端还有IP电话端分别同时抓包,然后对比分析,一个个分析,发现语音网关语音集群系统负载均衡向语音网关发了一条消息之后,这个连接就断了,是因为语音网关设备不识别这个信息,所以说最后就掉线了。

最后解决办法,我们在配置文件里面把这个信息给strip掉了之后,这个问题就得到解决了。

这个问题其实我总结了一下,正常情况下两边都是一样的,都不会掉线,那不同的地方电话端入会经过一个语音网关的设备,然后语音网关的请求转到集群负载均衡设置上,这是唯一的不同,然后语音网关设置是一个硬件的设置,然后集群负载均衡是因为开源,问题就是开源负载均衡设备给语音网关发了一条消息,识别,最终掉线,这个就是问题的原因。这是它的解决办法,把信息给去掉,在配置文件当中关键字就strip就可以了。

总结

最后我想总结一下,其实 Tcpdump,有时候我们解决问题的途径还是通过应用日志,如果说 log 不能帮我们解决问题,我们可以尝试用 Tcpdump 抓包去分析一下,Tcpdump 有时候可以帮助我们找到解决问题的线索。我前面分享4个场景其实都是 Tcpdump 给我们提供的线索,根据这些线索我们可以分析问题,找到问题的原因,解决问题。

Tcpdump 还是有助于我们巩固学习到的知识,比如说 HTTPS 会话建立其实有好多步骤,如果我们自己抓包去分析,可能更直接一些。还有刚才 DNS 的问题,我自己感受来说我看书的时候说了一句,所有 DNS 都支持迭代查询,我当时不是特别理解,后来我才明白通过抓包才明白,通过抓包明白确实都支持迭代查询。

还有一个 Tcpdump 有的时候可以帮我们验证一些配置,前面说的 HTTPS,我们自己配之后可以抓包试一下,然后可以验证一下,加密之前我们可以抓到密码,加密之后密码就看不见,因为是被加密了。

这是我分享的就结束了,希望能给大家带来一些解决问题的思路,然后咱们也可以一起交流,一起学习,那我今天的分享就到这了,谢谢大家!

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注