1

使用tcpdump分析常见网络协议(ARP,DNS,IP,TCP)

环境

linux: red-hat 8

yum install bind-utils tcpdump net-tools

ARP

前置条件

机器A与机器B处于同一网段

步骤

1.机器A的终端A执行 arp -D 机器B的IP
2.机器A的终端A执行 tcpdump -i ech0 -ent '(dst 机器AIP and src 机器BIP) or (dst 机器BIP and src 机器AIP)' -X
3.机器A的终端B执行 ping 机器B的IP
4.机器A的终端A获得网络包

结果

image.png

分析

0001 //硬件类型,1表示MAC地址
0800 //协议类型,表示要映射的协议地址类型,0800表示IP地址
06 //硬件地址长度字段,MAC地址是6
04  //协议地址长度字段,IPV4是4
0001 //操作类型,1为ARP请求,2为ARP应答,3位RARP请求,4位RARP应答 
000c 29ff 22e7 //发送端以太网地址
0a70 8871 //发送端IP地址
0000 0000 0000 //目的端以太网地址,全0表示广播,broadcast,同网段下所有的机器都会接收到
0a70 886a //目的端IP地址 


0001 //硬件类型,1表示MAC地址
0800 //协议类型,表示要映射的协议地址类型,0800表示IP地址
06 //硬件地址长度字段,MAC地址是6
04 //协议地址长度字段,IPV4是4
0002 //操作类型,1为ARP请求,2为ARP应答,3位RARP请求,4位RARP应答 
000c 297c 7c42 //发送端以太网地址
0a70 886a //发送端IP地址
000c 29ff 22e7 //目的端以太网地址,全0表示广播,broadcast,同网段下所有的机器都会接收到
0a70 8871 //目的端IP地址 
0000 0000 0000 0000 0000 0000 0000 0000 0000 //填充字节

DNS

步骤

  1. vi /etc/resolv.conf 配置DNS服务器
  2. 机器A终端1执行 tcpdump -i ech0 -nt -s 500 port domain -X
  3. 机器A终端2执行 host -t A www.baidu.com
  4. 机器A终端1获得结果

结果

image.png

分析

4500 003b 3f0d 0000 4011 9136 0a70 8871 0a70 0d1e c153 0035 0027 aaa7 //IP表头
1048 //16位标识
0100 //16位标志 0 0000 0 0 1 0 000 0000 QR:0表示请求 opcode:0表示默认查询 AA:0 TC:0 RD:1表示递归查询 RA:0 zero:全0, rcode:返回码,表示应答状态,0表示无错误
0001 //16位问题个数
0000 //16位应答资源记录个数
0000 //16位授权资源记录数目
0000 //16位额外的资源记录数目
//查询问题
0377 7777 0562 6169 6475 0363 6f6d 00//查询名(可变长) www.baidu.com
0001 //16位查询类型,1表示获取目标主机的IP地址
0001 //16位查询类,1表示获取因特网地址(IP地址)



4500 0076 52ae 0000 7a11 435a 0a70 0d1e 0a70 8871 0035 c153 0062 55ca //IP表头
1048 //16位标识,与请求报文对应
8180 //16位标志 1 0000 0 0 1 1 000 0000 QR:1表示应答 opcode:0表示默认查询 AA:0 TC:0 RD:1表示递归查询 RA:1表示服务器支持递归查询 zero:全0, rcode:返回码,表示应答状态,0表示无错误
0001 //16位问题个数
0003 //16位应答资源记录个数,有3个
0000 //16位授权资源记录数目
0000 //16位额外的资源记录数目
//查询问题
0377 7777 0562 6169 6475 0363 6f6d 00 //查询名(可变长) www.baidu.com
0001 //16位查询类型,1表示获取目标主机的IP地址
0001 //16位查询类,1表示获取因特网地址(IP地址)
//应答
c00c 0005 //32位域名
0001 //16位类型 A
0000 //16位类
02f6 000f //32位生存时间
0377 777701 6106 7368 6966 656e c016 // www.a.shifen

c02b 0001 //32位域名
0001 //16位类型A
0000 //16位类
0004 0004 //32位生存时间
dcb5 2696 // 220.181.38.150

c02b 0001 //32位域名
0001 //16位类型A
0000 //16位类
0004 0004 //32位生存时间
dcb5 2695 // 220.181.38.149              

IP

未分片

步骤

  1. 机器A终端1执行tcpdump -ntx -i lo -ent '(src 127.0.0.1 and dst 127.0.0.1)'
  2. 机器A终端2执行ssh 127.0.0.1
  3. 机器A终端1查看结果

结果

image.png

分析

4 //4位版本号,IPV4是4
5 //4位头部长度 20字节
00 //8位服务类型(TOS),3位优先权字段(现已忽略),4位TOS字段(最小延时,最大吞吐量,最高可靠性,最小费用),1位保留字段(必须置0) 
003c //16位总长度 60字节
bd6c //16位标识
4000//3位标志字段+13位分片偏移,
40 //8位生存时间,被设置为64
06 //8位协议,ICMP 1,TCP 6 UDP 17
7f4d //16位头部校验和
7f00 0001 //32位源IP,这里是127.0.0.1
7f00 0001 //32位目标IP,这里是127.0.0.1
d968 0016 d2e5 0761 0000 0000 a002 aaaa fe30 0000 0204 ffd7 0402 080a b8d3 0a45 0000 0000 0103 0307 //

分片

使用ping,指定包大小为1473,分包如下所示(每个包都会包含IP头部,且除最后一个包外都会设置MF,仅第一个包会设置ICMP头部,因为最后组包仅需1个ICMP头即可):

image.png

步骤

  1. 机器A终端1执行tcpdump -ntv -i ens192 icmp -x
  2. 机器A终端2执行ping 机器B的IP -s 1473
  3. 机器A终端1查看结果

结果

image.png

image.png

分析

第一个报文:0x05dc表示长度,十进制是1500,这是默认的MTU大小,0x1dbd是该报文唯一标识,0x2000,二进制是0010 0000 0000 0000,第三个为1表示该报文未终止,后面13位偏移量为0
第二个报文:0x0015表示长度,十进制是21,0x1dbd是该报文唯一标识,0x00b9,二进制是0000 0000 1011 1001 ,第三个为0表示该报文终止,后面13位为10111001,右移三位得到真实偏移量,也就是10111001000,即1480

TCP

tcp(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,分三次握手(为什么三次,因为中间服务端回传可以把ack和syn合并一起发送,节约一次,毕竟它只需要确定网络的连通性)和四次挥手(不能三次,因为要两边都确定结束,才算结束,客户端要结束,服务端可能要等数据发送完后才结束,所以不能合并在第二次一起发)。

image.png

步骤

  1. 机器B安装squid(yum install squid)并执行systemctl start squid
  2. 机器A安装wget(yum install wget)
  3. 机器A终端1执行tcpdump -s 2000 -i ens192 -ntX'(src 机器A的IP and dst 机器B的IP) or (src 机器B的IP and dst 机器A的IP) or (arp)'
  4. 机器A终端2执行export http_proxy="机器B的IP:3128"
  5. 机器A终端2执行wget --header="Connection:close" http://www.baidu.com/index.html

结果

image.png

image.png

分析

我们可以看到 [S] [S.] [.] 这就是三次握手,seq是由发送端随机生成的数字,接收端回的ack=seq+1,你可能会有疑问,这里不对啊,为什么第三次ack是1,不是3135247109呢?这是因为在建立连接后,ack和req会采用相对值而不是绝对值,因为抓包看收发包的过程中, ack seq自带一个随机无意义的基础巨大偏移量没有任何实际意义,用相对偏移量则更方便。想看绝对值的话可以加上-S(tcpdump -S),这个时候抓包就是下图所示

image.png


点墨
26 声望3 粉丝

全栈前端开发工程师