通过Tcpdump抓包 Wireshark分析 找出Wget文件下载失败的原因

在实际工作的过程中,服务程序每日开盘前需要依赖一下静态的文件进行初始化操作,类似版块文件、财务文件、除权文件等文件。由于下载工作比较简单,我们使用linux系统自带的wget,通过shell脚本的方式进行下载,脚本编写完成在测试过程中发现,随着下载频率的增加出现下载不成功的次数会增加,下载到的内容类似:

未分类

从上面的信息可以看到,等到的信息中有类似hs_cc_cookie,初步得出两个怀疑方向:

  • 难道是异常使用cookie导致请求直接返回?
  • 或者是请求被认为是CC攻击,安全设备直接返回了上面的上面的HTML内容??

基于上面的怀疑我们开始问题的排查。

问题排查

1、对wget的请求增加参数

在请求中增加 -S参数,打印详细的响应头,正常下载:

未分类

错误下载:

未分类

然后对请求 增加–no-cookies 参数 ,不使用 cookies ,增加参数后结果一样,多次下载继续出现问题,关于cookies可能性排除,难道真的是安全设备的问题?涉及到跨部门协调,需要拿出证据,那么只能出最后的绝招–网络抓包 ,结果绝对公平公正,童叟无欺。

抓包分析

说到抓包,不得不说说TCP的建立连接的“三次握手”和断开连接的“四次挥手”。
如果觉得有必要回顾一下的同学可以先看看“附录一”,里面会有详细的接收。了然于胸的同学我们继续问题排查。
通过TCPDUMP (LINUX 网络抓包工具)抓取正常下载和异常下载的网络包进行对比分析。

正常下载:

未分类

下载异常:

未分类

下面我们对下载异常的网络包进行分析:

  • 665号包说明服务器认为自己已经完成了服务请求,但客户端却没有主动关闭连接,于是在 20s 后只好主动将连接关闭。665号包显示 “TCP Previous segment not captured” 并且包中 “Seq=640” 而上一个 “Seq=1”我们确实有包没有抓到。

  • 666号包客户端在收到 “Seq=640” 后认为自己收到了一个乱序包,因此试图通过 “TCP Dup ACK 663#1” 和 “Ack=1” 试图让服务器重传缺失的 639 字节。

  • 667号包 出现 “TCP Out-Of-Order” ,产生该问题的原因一般:Packet 可能 Lost,所以重新传送造成。或存在Load Balance 之类的架构,晚送的封包却比早送的到达。

  • 671 号包开始说明客户端由于某种原因还进行了多次针对 “FIN” 的==“TCP Spurious Retransmission”== 。

TCP Previous segment not captured的问题一般有以下几种情况,我们来一一排查。
服务器CPU或网络压力导致上述问题(服务器没有压力)

未分类

  • 杀毒软件、恶意软件监测程序等导致问题(无此问题)。

  • 交换机、路由器和防火墙等网络层问题。

排查到这里,基本可以判断问题是由于网络层相关问题导致,接下来我们从以下两个方向进行问题排查。

1、查看防火墙出口带宽,整个出口我有200M 现在看看只有50M的峰值,和出口带宽无关

未分类

2、查看防火墙关于CC攻击的配置发现开启了IPS防御以及防病毒配置,对于单IP的访问频次过高时,认为是攻击行为会产生丢弃操作,当出现错误请求时有如下报错信息:

未分类

3、调整防火墙配置关闭CC防护,问题解决:

未分类

通过以上的排查我们得出结论:wget在频繁被执行时触发了防火墙的CC攻击防护机制,导致请求被截断从而出现了文章开头的问题。

解决方案:

  • 针对wget下载脚本:
    在增加 中wget 时增加–limit-rate=2048k (限制下载速度为2M)参数,限制下载速度,并增长两次下载过程中的sleep 时间间隔。

  • 针对防火墙:
    适当调高防火墙CC防护的rps值,避免正常请求被防火墙作为CC攻击屏蔽。

为什么Wireshark无法解密HTTPS数据

问题

由于需要定位一个问题,在服务器上tcpdump抓取https数据包,然后下载到本地打开wireshark分析。然后我们下载域名私钥配置到wireshark,发现数据包居然无法解密。是wireshark配置密钥的方法不对?但谷歌了好多文章都是说这样配置的。由于对HTTPS认识不够深,一时不知道如何入手解决。没办法,只能先了解tls这个协议了,于是查看了TLS1.2的RFC文档,终于勉强解答了这个疑惑。

TLS握手整个过程

在解决这个问题之前,先整体了解一下TLS的握手全过程。省略了不常见的过程。如图:
系统管理
下面按顺序介绍各握手步骤。

Client Hello

这是TLS握手的第一步,由客户端发起请求。此协议主要包括了一个客户端生成的随机字符串(用来下面生成session key),还有客户端支持的加密套件列表。如图:
系统管理

Server Hello

服务器收到客户端的Client Hello数据包之后,根据客户端发来的加密套件列表,选择一个加密套件,也生成一个随机字符串返回给客户端。我们看到下图中的加密套件为,密钥交换算法使用ECDHE_RSA,对称加密算法使用AES_256_GCM_SHA384,如图:
系统管理

Server Certificate

接着服务器再返回证书列表,包括证书链及域名证书。返回的证书用来给客户端验证当前连接服务器的身份,防止中间人攻击。

Server Key Exchange

Server Key Exchange协议包,由服务器返回,主要目的是与客户端交换用于数据对称加密的密钥。如图:
系统管理

Server Hello Done

服务器返回此协议数据,告诉客户端已经完成返回所需用于密钥交换的数据。服务器等待客户端响应。

Client Key Exchange

客户端根据服务器返回的DH密钥数据生成DH公共数据也发给服务器,用来生成最终的pre-master-secret。如图:
系统管理

Change Cipher Spec

此协议用于客户端和服务器相互告知也完成密钥交换过程,可以切换到对称加密过程。

到这里大概的TLS握手过程就结束了。为解决本文中的问题,还需要了解密钥交换的算法,RSA和Diffie–Hellman。

密钥交换算法

密钥交换算法目前常用的有RSA和Diffie-Hellman。
对于密钥交换使用RSA算法,pre-master-secret由客户端生成,并使用公钥加密传输给服务器。
对于密钥交换使用Diffie-Hellman算法,pre-master-secret则通过在Key Exchange阶段交换的信息,由各自计算出pre-master-secret。所以pre-master-secret没有存到硬盘,也没有在网络上传输,wireshark就无法获取session key,也就无法解密应用数据。那我们是否可以反向计算出pre-master-secret呢?理论上可以,但是非常困难。
对Diffie-Hellman算法感兴趣的可以参考https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange

解决方法

说了这么多,究竟有什么办法可以让wireshark解密数据?我们可以通过下面几种方法来使wireshark能解密https数据包。

  • 1. 中间人攻击;
  • 2. 设置web服务器使用RSA作为交换密钥算法;
  • 3. 如果是用chrome,firefox,可以设置导出pre-master-secret log,然后wireshark设置pre-master-secret log路径,这样就可以解密了。

Linux命令行抓包及包解析工具tshark(wireshark)使用实例解析

在Linux下,当我们需要抓取网络数据包分析时,通常是使用tcpdump抓取网络raw数据包存到一个文件,然后下载到本地使用wireshark界面网络分析工具进行网络包分析。
最近才发现,原来wireshark也提供有Linux命令行工具-tshark。tshark不仅有抓包的功能,还带了解析各种协议的能力。下面我们以两个实例来介绍tshark工具。

1、安装方法

  1. CentOS: yum install -y wireshark
  2. Ubuntu: apt-get install -y tshark

2、实时打印当前http请求的url(包括域名)

  1. tshark -s 512 -i eth0 -n -f ‘tcp dst port 80’ -R ‘http.host and http.request.uri’ -T fields -e http.host -e http.request.uri -l | tr -d ‘t’

下面介绍参数含义:

  • -s 512 :只抓取前512个字节数据
  • -i eth0 :捕获eth0网卡
  • -n :禁止网络对象名称解析
  • -f ‘tcp dst port 80’ :只捕捉协议为tcp,目的端口为80的数据包
  • -R ‘http.host and http.request.uri’ :过滤出http.host和http.request.uri
  • -T fields -e http.host -e http.request.uri :打印http.host和http.request.uri
  • -l :输出到标准输出

3、实时打印当前mysql查询语句

  1. tshark -s 512 -i eth0 -n -f ‘tcp dst port 3306’ -R ‘mysql.query’ -T fields -e mysql.query

下面介绍参数含义:

  • -s 512 :只抓取前512个字节数据
  • -i eth0 :捕获eth0网卡
  • -n :禁止网络对象名称解析
  • -f ‘tcp dst port 3306’ :只捕捉协议为tcp,目的端口为3306的数据包
  • -R ‘mysql.query’ :过滤出mysql.query
  • -T fields -e mysql.query :打印mysql查询语句

tshark使用-f来指定捕捉包过滤规则,规则与tcpdump一样,可以通过命令man pcap-filter来查得。
tshark使用-R来过滤已捕捉到的包,与界面版wireshark的左上角Filter一致。