1 原由linux
前段时间,一直在调线上的一个问题:线上应用接受POST请求,请求body中的参数获取不全,存在丢失的情况。这个问题是偶发性的,大概发生的概率为5%-10%左右,这个几率已经至关高了。在排查问题的过程当中使用到了tcpdump和Wireshark进行抓包分析。感受这两个工具搭配起来干活,很是完美。全部的网络传输在这两个工具搭配下,都无处遁形。安全
为了更好、更顺手地可以用好这两个工具,特整理本篇文章,但愿也能给你们带来收获。为你们以后排查问题,添一利器。服务器
2 tcpdump与Wireshark介绍网络
在网络问题的调试中,tcpdump应该说是一个必不可少的工具,和大部分linux下优秀工具同样,它的特色就是简单而强大。它是基于Unix系统的命令行式的数据包嗅探工具,能够抓取流动在网卡上的数据包。并发
默认状况下,tcpdump不会抓取本机内部通信的报文。根据网络协议栈的规定,对于报文,即便是目的地是本机,也须要通过本机的网络协议层,因此本机通信确定是经过API进入了内核,而且完成了路由选择。【好比本机的TCP通讯,也必需要socket通讯的基本要素:src ip port dst ip port】less
若是要使用tcpdump抓取其余主机MAC地址的数据包,必须开启网卡混杂模式,所谓混杂模式,用最简单的语言就是让网卡抓取任何通过它的数据包,无论这个数据包是否是发给它或者是它发出的。通常而言,Unix不会让普通用户设置混杂模式,由于这样能够看到别人的信息,好比telnet的用户名和密码,这样会引发一些安全上的问题,因此只有root用户能够开启混杂模式,开启混杂模式的命令是:ifconfig en0 promisc, en0是你要打开混杂模式的网卡。运维
Linux抓包原理:curl
Linux抓包是经过注册一种虚拟的底层网络协议来完成对网络报文(准确的说是网络设备)消息的处理权。当网卡接收到一个网络报文以后,它会遍历系统中全部已经注册的网络协议,例如以太网协议、x25协议处理模块来尝试进行报文的解析处理,这一点和一些文件系统的挂载类似,就是让系统中全部的已经注册的文件系统来进行尝试挂载,若是哪个认为本身能够处理,那么就完成挂载。socket
当抓包模块把本身假装成一个网络协议的时候,系统在收到报文的时候就会给这个伪协议一次机会,让它来对网卡收到的报文进行一次处理,此时该模块就会趁机对报文进行窥探,也就是把这个报文完完整整的复制一份,伪装是本身接收到的报文,汇报给抓包模块。tcp
Wireshark是一个网络协议检测工具,支持Windows平台、Unix平台、Mac平台,通常只在图形界面平台下使用Wireshark,若是是Linux的话,直接使用tcpdump了,由于通常而言Linux都自带的tcpdump,或者用tcpdump抓包之后用Wireshark打开分析。
在Mac平台下,Wireshark经过WinPcap进行抓包,封装的很好,使用起来很方便,能够很容易的制定抓包过滤器或者显示过滤器,具体简单使用下面会介绍。Wireshark是一个免费的工具,只要google一下就能很容易找到下载的地方。
因此,tcpdump是用来抓取数据很是方便,Wireshark则是用于分析抓取到的数据比较方便。
3 tcpdump使用
3.1 语法
类型的关键字
host(缺省类型): 指明一台主机,如:host 210.27.48.2
net: 指明一个网络地址,如:net 202.0.0.0
port: 指明端口号,如:port 23
肯定方向的关键字
src: src 210.27.48.2, IP包源地址是210.27.48.2
dst: dst net 202.0.0.0, 目标网络地址是202.0.0.0
dst or src(缺省值)
dst and src
协议的关键字:缺省值是监听全部协议的信息包
fddi
ip
arp
rarp
tcp
udp
其余关键字
gateway
broadcast
less
greater
经常使用表达式:多条件时能够用括号,可是要用转义
非 : ! or “not” (去掉双引号)
且 : && or “and”
或 : || or “or”
3.2 选项
3.3 命令实践
一、直接启动tcpdump,将抓取全部通过第一个网络接口上的数据包
二、抓取全部通过指定网络接口上的数据包
三、抓取全部通过 en0,目的或源地址是 10.37.63.255 的网络数据:
四、抓取主机10.37.63.255和主机10.37.63.61或10.37.63.95的通讯:
五、抓取主机192.168.13.210除了和主机10.37.63.61以外全部主机通讯的数据包:
六、抓取主机10.37.63.255除了和主机10.37.63.61以外全部主机通讯的ip包
七、抓取主机10.37.63.3发送的全部数据:
八、抓取主机10.37.63.3接收的全部数据:
九、抓取主机10.37.63.3全部在TCP 80端口的数据包:
十、抓取HTTP主机10.37.63.3在80端口接收到的数据包:
十一、抓取全部通过 en0,目的或源端口是 25 的网络数据
十二、抓取全部通过 en0,网络是 192.168上的数据包
1三、协议过滤
1四、抓取全部通过 en0,目的地址是 192.168.1.254 或 192.168.1.200 端口是 80 的 TCP 数据
1五、抓取全部通过 en0,目标 MAC 地址是 00:01:02:03:04:05 的 ICMP 数据
1六、抓取全部通过 en0,目的网络是 192.168,但目的主机不是 192.168.1.200 的 TCP 数据
1七、只抓 SYN 包
1八、抓 SYN, ACK
1九、抓 SMTP 数据,抓取数据区开始为”MAIL”的包,”MAIL”的十六进制为 0x4d41494c
20、抓 HTTP GET 数据,”GET “的十六进制是 0x47455420
2一、抓 SSH 返回,”SSH-“的十六进制是 0x5353482D
2二、高级包头过滤如前两个的包头过滤,首先了解如何从包头过滤信息:
2三、抓 DNS 请求数据
2四、其余-c 参数对于运维人员来讲也比较经常使用,由于流量比较大的服务器,靠人工 CTRL+C 仍是抓的太多,因而能够用-c 参数指定抓多少个包。
3.4 抓个网站练练
想抓取访问某个网站时的网络数据。好比网站 http://www.baidu.com/ 怎么作?
一、经过tcpdump截获主机www.baidu.com发送与接收全部的数据包
二、访问这个网站
三、想要看到详细的http报文。怎么作?
四、分析抓取到的报文
4 tcpdump抓取TCP包分析
TCP传输控制协议是面向链接的可靠的传输层协议,在进行数据传输以前,须要在传输数据的两端(客户端和服务器端)建立一个链接,这个链接由一对插口地址惟一标识,便是在IP报文首部的源IP地址、目的IP地址,以及TCP数据报首部的源端口地址和目的端口地址。TCP首部结构以下:
注意:一般状况下,一个正常的TCP链接,都会有三个阶段:一、TCP三次握手;二、数据传送;三、TCP四次挥手
其中在TCP链接和断开链接过程当中的关键部分以下:
源端口号:即发送方的端口号,在TCP链接过程当中,对于客户端,端口号每每由内核分配,无需进程指定;
目的端口号:即发送目的的端口号;
序号:即为发送的数据段首个字节的序号;
确认序号:在收到对方发来的数据报,发送确认时期待对方下一次发送的数据序号;
SYN:同步序列编号,Synchronize Sequence Numbers;
ACK:确认编号,Acknowledgement Number;
FIN:结束标志,FINish;
4.1 TCP三次握手
三次握手的过程以下:
step1. 由客户端向服务器端发起TCP链接请求。Client发送:同步序列编号SYN置为1,发送序号Seq为一个随机数,这里假设为X,确认序号ACK置为0;
step2. 服务器端接收到链接请求。Server响应:同步序列编号SYN置为1,并将确认序号ACK置为X+1,而后生成一个随机数Y做为发送序号Seq(由于所确认的数据报的确认序号未初始化);
step3. 客户端对接收到的确认进行确认。Client发送:将确认序号ACK置为Y+1,而后将发送序号Seq置为X+1(即为接收到的数据报的确认序号);
为何是三次握手而不是两次对于step3的做用,假设一种状况,客户端A向服务器B发送一个链接请求数据报,而后这个数据报在网络中滞留致使其迟到了,虽然迟到了,可是服务器仍然会接收并发回一个确认数据报。可是A却由于久久收不到B的确认而将发送的请求链接置为失效,等到一段时间后,接到B发送过来的确认,A认为本身如今没有发送链接,而B却一直觉得链接成功了,因而一直在等待A的动做,而A将不会有任何的动做了。这会致使服务器资源白白浪费掉了,所以,两次握手是不行的,所以须要再加上一次,对B发过来的确认再进行一次确认,即确认此次链接是有效的,从而创建链接。
对于双方,发送序号的初始化为什么值有的系统中是显式的初始化序号是0,可是这种已知的初始化值是很是危险的,由于这会使得一些黑客钻漏洞,发送一些数据报来破坏链接。所以,初始化序号由于取随机数会更好一些,而且是越随机越安全。
tcpdump抓TCP三次握手抓包分析:
sudotcpdump-n-S-ilo0host10.37.63.3andtcpport8080
# 接着再运行:
curlhttp://10.37.63.3:8080/atbg/doc
控制台输出:
每一行中间都有这个包所携带的标志:
S=SYN,发起链接标志。
P=PUSH,传送数据标志。
F=FIN,关闭链接标志。
ack,表示确认包。
RST=RESET,异常关闭链接。
.,表示没有任何标志。
第1行:16:00:13.486776,从10.37.63.3(client)的临时端口61725向10.37.63.3(server)的8080监听端口发起链接,client初始包序号seq为1944916150,滑动窗口大小为65535字节(滑动窗口即tcp接收缓冲区的大小,用于tcp拥塞控制),mss大小为16344(便可接收的最大包长度,一般为MTU减40字节,IP头和TCP头各20字节)。【seq=1944916150,ack=0,syn=1】
第2行:16:00:13.486850,server响应链接,同时带上第一个包的ack信息,为client端的初始包序号seq加1,即1944916151,即server端下次等待接受这个包序号的包,用于tcp字节流的顺序控制。Server端的初始包序号seq为1119565918,mss也是16344。【seq=1119565918,ack=1944916151,syn=1】
第3行:15:46:13.084161,client再次发送确认链接,tcp链接三次握手完成,等待传输数据包。【ack=1119565919,seq=1944916151】
4.2 TCP四次挥手
链接双方在完成数据传输以后就须要断开链接。因为TCP链接是属于全双工的,即链接双方能够在一条TCP链接上互相传输数据,所以在断开时存在一个半关闭状态,即有有一方失去发送数据的能力,却还能接收数据。所以,断开链接须要分为四次。主要过程以下:
step1. 主机A向主机B发起断开链接请求,以后主机A进入FIN-WAIT-1状态;
step2. 主机B收到主机A的请求后,向主机A发回确认,而后进入CLOSE-WAIT状态;
step3. 主机A收到B的确认以后,进入FIN-WAIT-2状态,此时即是半关闭状态,即主机A失去发送能力,可是主机B却还能向A发送数据,而且A能够接收数据。此时主机B占主导位置了,若是须要继续关闭则须要主机B来操做了;
step4. 主机B向A发出断开链接请求,而后进入LAST-ACK状态;
step5. 主机A接收到请求后发送确认,进入TIME-WAIT状态,等待2MSL以后进入CLOSED状态,而主机B则在接受到确认后进入CLOSED状态;
为什么主机A在发送了最后的确认后没有进入CLOSED状态,反而进入了一个等待2MSL的TIME-WAIT主要做用有两个:
第一,确保主机A最后发送的确认可以到达主机B。若是处于LAST-ACK状态的主机B一直收不到来自主机A的确认,它会重传断开链接请求,而后主机A就能够有足够的时间去再次发送确认。可是这也只能尽最大力量来确保可以正常断开,若是主机A的确认老是在网络中滞留失效,从而超过了2MSL,最后也没法正常断开;
第二,若是主机A在发送了确认以后当即进入CLOSED状态。假设以后主机A再次向主机B发送一条链接请求,而这条链接请求比以前的确认报文更早地到达主机B,则会使得主机B觉得这条链接请求是在旧的链接中A发出的报文,并不当作是一条新的链接请求了,即便得这个链接请求失效了,增长2MSL的时间可使得这个失效的链接请求报文做废,这样才不影响下次新的链接请求中出现失效的链接请求。
为何断开链接请求报文只有三个,而不是四个由于在TCP链接过程当中,确认的发送有一个延时(即经受延时的确认),一端在发送确认的时候将等待一段时间,若是本身在这段事件内也有数据要发送,就跟确认一块儿发送,若是没有,则确认单独发送。而咱们的抓包实验中,由服务器端先断开链接,以后客户端在确认的延迟时间内,也有请求断开链接须要发送,因而就与上次确认一块儿发送,所以就只有三个数据报了。
5 Wireshark分析tcpdump抓包结果
一、启动8080端口,tcpdump抓包命令以下:
tcpdump-ilo0-s0-n-Shost10.37.63.3andport8080-w./Desktop/tcpdump_10.37.63.3_8080_20160525.cap
# 而后再执行curl
curlhttp://10.37.63.3:8080/atbg/doc
二、使用Wireshark打开tcpdump_10.37.63.3_8080_20160525.cap文件
No. 1-4 行:TCP三次握手环节;
No. 5-8 行:TCP传输数据环节;
No. 9-13 行:TCP四次挥手环节;
三、顺便说一个查看 http 请求和响应的方法:
弹窗以下图所示,上面红色部分为请求信息,下面蓝色部分为响应信息:
以上是Wireshark分析tcpdump的简单使用,Wireshark更强大的是过滤器工具,你们能够自行去多研究学习Wireshark,用起来仍是比较爽的。