学习目标
1 巩固网络协议
ping需要建立连接吗?tcp的数据传递一定需要ack吗?只通过ip地址和port就能把数据发送到目的主机吗?(这个面试常问) 微信登录是如何认证的?附近的人是如何实现的?
2 排查网络故障
为什么服务后台会收到connection reset或者connection reset by peer? 如果我没有打印日志如何拿到终端传递的参数信息?网络和服务都是通的为什么终端和后台无法建立连接?如果打开的socket用完之后不关闭有什么后果?
通过本次交流培训能够熟练使用tcpdump抓包并且熟练验证网络知识的在实战中的使用。
网络协议介绍
1. 协议分层
2. 协议体系
3. 协议各层的功能
常规的网络问题排查方式
ping和telnet、curl相结合,但是当ping和telnet都没有问题,但是网络服务有问题的情况下,就需要更进一步在网络层面进行分析。
常见使用ping的方式如下:
ping -l 1500 -t -f
-l是携带数据大小,-t是一直ping,-f是不允许传输数据分片,在网络不稳定时,ping一次是没问题,但是如果一直ping或者ping的同时携带数据,可能出现丢包现象。
常见telnet使用方式如下:
telnet
tcpdump介绍
在网络问题的调试中,tcpdump应该说是一个必不可少的工具,和大部分linux下优秀工具一样,它的特点就是简单而强大。它是基于Unix系统的命令行式的数据包嗅探工具,可以抓取流动在网卡上的数据包。默认情况下,tcpdump不会抓取本机内部通讯的报文。根据网络协议栈的规定,对于报文,即使是目的地是本机,也需要经过本机的网络协议层,所以本机通讯肯定是通过API进入了内核,并且完成了路由选择。【比如本机的TCP通信,也必须要socket通信的基本要素:src ip port dst ip port】
Linux 抓包原理:
Linux抓包是通过注册一种虚拟的底层网络协议来完成对网络报文(准确的说是网络设备)消息的处理权。当网卡接收到一个网络报文之后,它会遍历系统中所有已经注册的网络协议,例如以太网协议、x25协议处理模块来尝试进行报文的解析处理,这一点和一些文件系统的挂载相似,就是让系统中所有的已经注册的文件系统来进行尝试挂载,如果哪一个认为自己可以处理,那么就完成挂载。当抓包模块把自己伪装成一个网络协议的时候,系统在收到报文的时候就会 给这个伪协议一次机会,让它来对网卡收到的报文进行一次处理,此时该模块就会趁机对报文进行窥探,也就是把这个报文完完整整的复制一份,假装是自己接 收到的报文,汇报给抓包模块。
tcpdump介绍
1. tcpdump语法
tcpdump
[-aAbdDefhHIJKlLnNOpqRStuUvxX][ -B size ] [ -c count ]
[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
[ -i interface ] [ -j tstamptype ] [ -M secret ]
[ -P in|out|inout ]
[ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]
[ -W filecount ] [ -y datalinktype ] [ -z command ]
[ -Z user ] [ expression ]
类型的关键字
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”
选项
-A:以ASCII编码打印每个报文(不包括链路层的头),这对分析网页来说很方便;
-a:将网络地址和广播地址转变成名字;
-c:在收到指定的包的数目后,tcpdump就会停止;
-C:用于判断用
-w 选项将报文写入的文件的大小是否超过这个值,如果超过了就新建文件(文件名后缀是1、2、3依次增加);
-d:将匹配信息包的代码以人们能够理解的汇编格式给出;
-dd:将匹配信息包的代码以c语言程序段的格式给出;
-ddd:将匹配信息包的代码以十进制的形式给出;
-D:列出当前主机的所有网卡编号和名称,可以用于选项-i;
-e:在输出行打印出数据链路层的头部信息;
-f:将外部的Internet地址以数字的形式打印出来;
-F:从指定的文件中读取表达式,忽略其它的表达式;
-i:监听主机的该网卡上的数据流,如果没有指定,就会使用最小网卡编号的网卡(在选项-D可知道,但是不包括环路接口),linux 2.2 内核及之后的版本支持any 网卡,用于指代任意网卡;
-l:如果没有使用-w 选项,就可以将报文打印到标准输出终端(此时这是默认);
-n:显示ip,而不是主机名;
-N:不列出域名;
-O:不将数据包编码最佳化;
-p:不让网络界面进入混杂模式;
-q:快速输出,仅列出少数的传输协议信息;
-r:从指定 的文件中读取包(这些包一般通过-w选项产生);
-s:指定抓包显示一行的宽度,-s0表示可按包长显示完整的包,经常和-A一起用,默认截取长度为60个字节,但一般ethernet MTU都是1500字节。所以,要抓取大于60字节的包时,使用默认参数就会导致包数据丢失;
-S:用绝对而非相对数值列出TCP关联数;
-t:在输出的每一行不打印时间戳;
-tt:在输出的每一行显示未经格式化的时间戳记;
-T:将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程调用)和snmp(简单网络管理协议);
-v:输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;
-vv:输出详细的报文信息;-x/-xx/-X/-XX:以十六进制显示包内容,几个选项只有细微的差别,详见man手册;
-w:直接将包写入文件中,并不分析和打印出来;
expression:用于筛选的逻辑表达式;
tcpdump实践
抓取所有经过指定网络接口上的数据包:tcpdump -i eth0
如果不指定网卡,默认tcpdump只会监视第一个网络接口,一般是eth0,下面的例子都没有指定网络接口。
控制台输出如下:
[root@localhost compose]# tcpdump -i enp1s0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp1s0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:08:44.716144 ARP, Request who-has 192.168.7.125 tell 192.168.7.201, length 46
10:08:44.719010 IP 192.168.7.228.41392 > 192.168.9.221.domain: 15482+ PTR? 125.7.168.192.in-addr.arpa. (44)
10:08:44.726248 IP 192.168.9.221.domain > 192.168.7.228.41392: 15482 NXDomain 0/1/0 (79)
10:08:44.726412 IP 192.168.7.228.60734 > 192.168.9.221.domain: 23783+ PTR? 201.7.168.192.in-addr.arpa. (44)
10:08:44.733012 IP 192.168.9.221.domain > 192.168.7.228.60734: 23783 NXDomain 0/1/0 (79)
10:08:44.733196 IP 192.168.7.228.34871 > 192.168.9.221.domain: 2185+ PTR? 221.9.168.192.in-addr.arpa. (44)
10:08:44.733436 IP 192.168.9.221.domain > 192.168.7.228.34871: 2185 NXDomain 0/1/0 (79)
10:08:44.733571 IP 192.168.7.228.55766 > 192.168.9.221.domain: 636+ PTR? 228.7.168.192.in-addr.arpa. (44)
10:08:44.738729 IP 192.168.9.221.domain > 192.168.7.228.55766: 636 NXDomain 0/1/0 (79)
10:08:44.744101 ARP, Request who-has 192.168.7.126 tell 192.168.7.201, length 46
10:08:44.744223 IP 192.168.7.228.60837 > 192.168.9.221.domain: 20675+ PTR? 126.7.168.192.in-addr.arpa. (44)
2. 抓取所有经过eth0,目的或者源地址是 11.12.184.34 并且端口是 2777 的网络数据:
tcpdump -i eth0 host 11.12.184.34 and port 2777
如果需要抓取抓取主机11.12.84.34发送的所有数据:(注意数据流向)
tcpdump -i eth0 src host 11.12.184.34 and port 2777
如果需要抓取抓取主机11.12.84.34接收的所有数据:(注意数据流向)
tcpdump -i eth0 dst host 11.12.184.34 and port 2777
控制台输出:
[root@111taish]# tcpdump -i enp125s0f0 host 192.168.1.21 and port 81
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp125s0f0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:17:22.359558 IP 192.168.35.65.61367 > 111taishan.81: Flags [F.], seq 282823919, ack 723079450, win 8210, length 0
10:17:22.359658 IP 111taishan.81 > 192.168.35.65.61367: Flags [.], ack 1, win 257, length 0
10:17:26.663028 IP 192.168.35.65.61393 > 111taishan.81: Flags [S], seq 1773488140, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
10:17:26.663140 IP 111taishan.81 > 192.168.35.65.61393: Flags [S.], seq 3291468842, ack 1773488141, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
10:17:26.663231 IP 192.168.35.65.61394 > 111taishan.81: Flags [S], seq 2246489497, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
10:17:26.663261 IP 111taishan.81 > 192.168.35.65.61394: Flags [S.], seq 3453542583, ack 2246489498, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
3. 抓取主机192.168.1.2所有在TCP 2077端口的完整数据包,并用16进制格式化输出:
tcpdump -i eth0 host 192.168.1.2 and port 2077 -s0 -XX -nn
如果需要抓取udp数据包:
tcpdump -i eth0 host 192.168.1.2 and udp port 1977 -s0 -XX -nn
控制台输出:
[root@taish xxxx]# tcpdump -i enp125s0f0 host 192.168.1.2 and port 81 -XX -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp125s0f0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:20:36.545273 IP 192.168.3.65.61470 > 192.168.1.2.81: Flags [S], seq 2332750219, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
0x0000: 1c20 db4b 4e4b 80fa 5b23 f592 0800 4500 ...KNK..[#....E.
0x0010: 0034 a711 4000 8006 8b3a c0a8 2341 c0a8 .4..@....:..#A..
0x0020: 23e6 f01e 0051 8b0a f18b 0000 0000 8002 #....Q..........
0x0030: faf0 3ea1 0000 0204 05b4 0103 0308 0101 ..>.............
0x0040: 0402 ..
10:20:36.545743 IP 192.168.1.2.81 > 192.168.3.65.61470: Flags [S.], seq 779736890, ack 2332750220, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
0x0000: 80fa 5b23 f592 1c20 db4b 4e4b 0800 4500 ..[#.....KNK..E.
0x0010: 0034 0000 4000 3f06 734c c0a8 23e6 c0a8 .4..@.?.sL..#...
0x0020: 2341 0051 f01e 2e79 d73a 8b0a f18c 8012 #A.Q...y.:......
0x0030: 7210 c89e 0000 0204 05b4 0101 0402 0103 r...............
0x0040: 0307 ..
10:20:36.545985 IP 192.168.3.65.61470 > 192.168.1.2.81: Flags [.], ack 1, win 8212, length 0
0x0000: 1c20 db4b 4e4b 80fa 5b23 f592 0800 4500 ...KNK..[#....E.
0x0010: 0028 a712 4000 8006 8b45 c0a8 2341 c0a8 .([email protected]..#A..
0x0020: 23e6 f01e 0051 8b0a f18c 2e79 d73b 5010 #....Q.....y.;P.
0x0030: 2014 548c 0000 ..T...
10:20:36.547490 IP 192.168.3.65.61461 > 192.168.1.2.81: Flags [P.], seq 3549829007:3549829634, ack 1338248970, win 8212, length 627
0x0000: 1c20 db4b 4e4b 80fa 5b23 f592 0800 4500 ...KNK..[#....E.
0x0010: 029b a715 4000 8006 88cf c0a8 2341 c0a8 ....@.......#A..
0x0020: 23e6 f015 0051 d396 178f 4fc4 0f0a 5018 #....Q....O...P.
0x0030: 2014 ce39 0000 4745 5420 2f6f 7065 7261 ...9..GET./xxxa
0x0040: 7469 6f6e 2d77 6172 2f6c 6f67 696e 2e68 txxx/login.h
0x0050: 746d 6c20 4854 5450 2f31 2e31 0d0a 486f tml.HTTP/1.1..Ho
4. 抓取主机11.12.184.123除了和主机11.12.8.35之外所有主机通信的数据包:
tcpdump -i eth0 dst host 11.12.8.123 and ! 11.12.8.35
5. 抓取所有经过en0,网络是192.168上的数据包 tcpdump -i eth0 net 192.168
tcpdump -i eth0 src net 192.168
tcpdump -i eth0 dst net 192.168
tcpdump -i eth0 net 192.168.1
tcpdump -i eth0 net 192.168.1.0/24
6. 协议过滤 tcpdump -i eth0 arp
tcpdump -i eth0 ip
tcpdump -i eth0 tcp
tcpdump -i eth0 udp
tcpdump -i eth0 icmp
7. 抓取所有经过en0,目的地址是192.168.1.254 或192.168.1.200 端口是80 的TCP 数据
tcpdump -i eth0 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))'
8. 只抓SYN 包
tcpdump -i en0 'tcp[tcpflags] = tcp-syn'
9. 抓SYN, ACK
tcpdump -i en0 'tcp[tcpflags]
10. 抓SMTP 数据,抓取数据区开始为” M AIL”的包,”MAIL” 的十六进制为0x4d41494c
tcpdump -i en0 '((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))'
11. 抓HTTP GET 数据,”GET “的十六进制是0x47455420
tcpdump -i en0 'tcp[(tcp[12]>>2):4] = 0x47455420'
0x4745 为"GET"前两个字母"GE",0x4854 为"HTTP"前两个字母"HT"
tcpdump -XvvennSs 0 -i en0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854
12. 其他-c参数对于运维人员来说也比较常用,因为流量比较大的服务器,靠人工 CTRL+C 还是抓的太多,于是可以用-c 参数指定抓多少个包。
tcpdump -nn -i en0 'tcp[tcpflags] = tcp-syn' -c 10000 > /dev/null
上面的命令计算抓10000 个SYN 包花费多少时间,可以判断访问量大概是多少。
实时抓取端口号8000的GET包,然后写入GET.log
tcpdump -i en0 '((port 8000) and (tcp[(tcp[12]>>2):4]=0x47455420))' -nnAl -w /tmp/GET.log
总结
tcpdump是开发人员科学推卸责任必备工具,如果在有人说你的代码运行有问题,抓个包保存起来,告诉他这是你的责任,网络包查收一下!
tcpdump -i enp125s0f0 host 192.168.3.20 and port 81 -XX -nn -w/home/2011.cap
推荐阅读
TCP滑动窗口消息堆积
如何跳过es分页这个坑?
添加关注直接获取更多技术书籍、视频资源
原创不易,如果觉得有用,可以随手转发或者”在看“