分享

借windump初窥网络底层

 海顺达 2012-03-22
1 旧 icon20 【原创】借windump初窥网络底层
发送 MSN 消息给 thisIs thisIs 当前在线 添加 thisIs 的声望 反映此帖

标 题: 【原创】借windump初窥网络底层
作 者: thisIs
时 间: 2012-03-09,15:26:42
链 接: http://bbs./showthread.php?t=147644


最近在学ndis以及网络方面的知识,今天借论坛宝地整理一些笔记出来,与大家共同分享下
<太过基础的原理就不做说明了,大家可以去网上搜索>

首先是各种包的格式定义:

以太头:
代码:
// MAC地址长度
#define MAC_ADDRESS_LEN 6

// 常用的以太网帧类型
#define ETHERNET_FRAME_IP    0x0800        // IP帧 
#define ETHERNET_FRAME_ARP    0x0806        // ARP帧 
#define ETHERNET_FRAME_RARP    0x8035        // RARP帧 
#define ETHERNET_FRAME_IPv6    0x86DD        // IP6帧 

typedef struct _EthernetHeader    // 以太头
{
  UCHAR    DstMacAddr[MAC_ADDRESS_LEN];    // 目标MAC
  UCHAR    SrcMacAddr[MAC_ADDRESS_LEN];    // 源MAC
  USHORT    FrmType;              // 类型
}EthernetHeader, *PEthernetHeader;

ARP,RARP头
代码:
// 定义ARP操作类型
#define ARP_QUERY        0x0001        // ARP请求 
#define ARP_REPLY        0x0002        // ARP应答
#define RARP_QUERY        0x0003        // RARP请求
#define RARP_REPLY        0x0004        // RARP应答

// 定义ARP硬件类型
#define ARP_ETHER        0x0001        // 以太网格式
#define ARP_IEEE802        0x0006        // 令牌环网
#define ARP_FRELAY        0x000f        // 帧中继硬件格式

typedef struct _ArpHeader      // ARP头<RARP>
{
  USHORT    HrdType;              // 硬件类型
  USHORT    ProType;              // 协议类型
  UCHAR    HrdAddrLen;              // 硬件地址长度
  UCHAR    ProAddrLen;              // 协议地址长度
  USHORT    Opr;                // 操作字段 <是ARP请求或者应答 异或RARP请求或者应答>
  UCHAR    SrcMacAddr[MAC_ADDRESS_LEN];    // 发送端的MAC地址
  ULONG    SrcIp;                // 发送端的IP地址
  UCHAR    DstMacAddr[MAC_ADDRESS_LEN];    // 目的MAC地址
  ULONG    DstIp;                // 目的IP地址
}ArpHeader, *PArpHeader;

typedef struct _ARPPACKET      // ARP封包
{
  EthernetHeader  Ehhdr;
  ArpHeader    Arphdr;
}ARPPACKET, *PARPPACKET;
IP头
代码:
 0                            15                              31
-----------------------------------------------------------------
|  ver  |  HL   |     TOS       |        Total len              |
-----------------------------------------------------------------
|          Packet id            |0|D|M|   Fragment Offset       |
-----------------------------------------------------------------
|     TTL       |    protocol   |          checksum             |
-----------------------------------------------------------------
|                       source ip address                       |
-----------------------------------------------------------------
|                       dest ip address                         |
-----------------------------------------------------------------
|                           Optional                            |
-----------------------------------------------------------------
|                              Data                             |
-----------------------------------------------------------------

// 定义IP数据报中的协议类型
#define ICMP_PROTOCOL      0x0001        // ICMP 报文
#define IGMP_PROTOCOL      0x0002        // IGMP 报文
#define TCP_PROTOCOL      0x0006        // TCP 报文
#define UDP_PROTOCOL      0x0011        // UDP 报文 17

// IP标志
#define IP_DF_MASK        0x4000        // 如果置位,表示不能被分割
#define IP_MF_MASK        0x2000        // 为1表示还有更多的数据报分片 为0表示已经是最后一个分片

typedef struct _IPHeader      // IP头 20 BYTES
{
  UCHAR    Ver:4;                // 版本信息
  UCHAR    HdrLen:4;              // IP数据报首部的双字个数,一般为5即20字节长
  UCHAR    TOS;                // 服务类型<一般忽略>
  USHORT    TotalLen;              // IP数据报总长度<字节单位>,包括了IP头,这个长度减去HdrLen就是数据实际长度
  USHORT    PktID;                // 封包ID 每发送一个包这里加一
  USHORT    FlagSeg;              // 标致字段和片偏移 3位标志 13位偏移
  UCHAR    TTL;                // 存活周期
  UCHAR    Protocol;              // 协议类型
  USHORT    Checksum;              // 效验和
  ULONG    SrcIp;                // 源IP
  ULONG    DstIp;                // 目的IP
}IPHeader, *PIPHeader;

typedef struct _IPPACKET      // IP封包
{
  EthernetHeader  Ehhdr;
  IPHeader    Iphdr;
}IPPACKET, *PIPPACKET;

TCP头
代码:
 0                            15                              31
-----------------------------------------------------------------
|          source port          |       destination port        |
-----------------------------------------------------------------
|                        sequence number                        |
-----------------------------------------------------------------
|                     acknowledgment number                     |
-----------------------------------------------------------------
|  HL   | rsvd  |C|E|U|A|P|R|S|F|        window size            |
-----------------------------------------------------------------
|         TCP checksum          |       urgent pointer          |
-----------------------------------------------------------------
|                           Optional                            |
-----------------------------------------------------------------
|                              Data                             |
-----------------------------------------------------------------

// TCP头标志位掩码 OffFlag
#define TCP_HDR_LEN        0xF000        // TCP头长度<双字的个数>转化为字节数需要x4    
#define TCP_URG_FLAG      0x0020        // URG标志
#define TCP_ACK_FLAG      0x0010        // ACK标志 应答1或请求0
#define TCP_PSH_FLAG      0x0008        // psh标志 以最快速度传输数据
#define TCP_RST_FLAG      0x0004        // RST标志 先断开连接,再重建连接
#define TCP_SYN_FLAG      0x0002        // SYN标志 用来建立连接
#define TCP_FIN_FLAG      0x0001        // FIN标志 发送方完成数据发送

typedef struct _TcpHeader      // TCP头 20 BYTES
{
  USHORT    SrcPort;              // 源端口
  USHORT    DstPort;              // 目的端口
  ULONG    SeqNum;                // 序号
  ULONG    AckNum;                // 确认号
  USHORT    OffFlag;              // 首部长度<首部双字的个数>+保留位+标志位
  USHORT    WndSize;              // 窗口大小<实现流量控制>
  USHORT    Checksum;              // 效验和
  USHORT    UrgPointer;              // 紧急指针
}TcpHeader, *PTcpHeader;

// OffFlag : 4位首部长度 + 6位保留位 + URG+ACK+PSH+RST+SYN+FIN

typedef struct _TCPPACKET      // TCP封包 <当ip中没有附加数据时>
{
  EthernetHeader  Ehhdr;
  IPHeader    Iphdr;
  TcpHeader    Tcphdr;
}TCPPACKET, *PTCPPACKET;

UDP头:
代码:
 0                            15                              31
-----------------------------------------------------------------
|          source port          |       destination port        |
-----------------------------------------------------------------
|          udp len              |       udp checksum            |
-----------------------------------------------------------------
|                             data                              |
-----------------------------------------------------------------
typedef struct _UdpHeader
{
  USHORT    SrcPort;              // 源端口
  USHORT    DstPort;              // 目的端口
  USHORT    UdpLen;                // 长度 头+数据字节长 最小8字节
  USHORT    Checksum;              // 效验和
}UdpHeader, *PUdpHeader;

typedef struct _UDPPACKET      // UDP封包 <当ip中没有附加数据时>
{
  EthernetHeader  Ehhdr;
  IPHeader    Iphdr;
  UdpHeader    Udphdr;
}UDPPACKET, *PUDPPACKET;

上面这些头在传输时都是网络字节序列,在访问时需要注意,而且不会进行双字对其.
所以最好使用对其标志将结构包起来:
代码:
#pragma pack(push)
#pragma pack(1)
..
..
#pragma pack(pop)

介绍完结构我们就抓几个包来实践一下,抓包工具我使用了windump,不过这个是基于控制台的程序,
大家看着不方便也可以使用其他的抓包工具,比如wireshark
windump我会在最后的附加中上传,使用它需要先安装winpcap


打开CMD命令提示符,定位到windump的目录然后输入windump,就能让它运行起来了:
名称:  01.jpg
查看次数: 355
文件大小:  98.2 KB
<可以使用Ctrl+C停止windump>

如果你的电脑上有多个网卡,可以用windump -D指令首先列出可来监听的接口列表,
然后在启动windump的时候用 -i 指令来指定使用哪个接口来监听, 比如 : windump -i3

如果没有附加条件,windump默认将dump所有经过网卡的封包,下面我会介绍几个过滤条件,
更多的信息可以在附件中附带的帮助文档中找到.也可以在网上搜索到详细介绍


首先我们看一下网络中的ARP封包,可以通过 windump -n arp 命令来过滤
其中-n表示不要将主机的ip地址显示为主机名称;arp表示只过滤arp封包
<我的测试环境是局域网,路由ip:192.168.1.1, 我的ip:192.168.1.23, OS:win7 sp1>

监听一会就能捕获一些局域网上的ARP封包:
名称:  02.jpg
查看次数: 354
文件大小:  109.4 KB


arp who-has 192.168.1.1 (00:25:86:99:2c:d6) tell 192.168.1.23
可以理解为我的主机在主动判断网关地址是否存在

reply 192.168.1.1 is-at 00:25:86:99:2c:d6
则是路由对我的主机的回复

我们现在使用命令 windump -n -XX arp 来打印出封包的具体内容
-XX表示使用16进制和ASCii码的形式打印封包内容.-X与之相仿,不过不会打印以太头:
名称:  03.jpg
查看次数: 353
文件大小:  86.5 KB

前14个字节描述了以太头的相关信息,windump完全按照字节序列进行打印,
以太头最后的 0806 代表了后面帧的类型,代表了ARP帧<参见前面的定义>

接下来是ARP头,我们来看第一个封包的内容,
代码:
0x000E: 0001 表示硬件类型是以太网类型
0x0010: 0800 表示协议类型是IP协议
0x0012: 0604 表示硬件地址<MAC>长为6字节,协议地址<IP>长为4字节
0x0014: 0001 表示操作类型为ARP请求 ARP_QUERY
后面就依次是源MAC,源IP,目标MAC,目标IP了

第二个封包描述了路由器对ARP请求的应答,不过末尾多了一部分数据,我找了一些资料也没找到相关说明,
如果哪位朋友知道可以告诉我一下,先行谢过了~~

最后的部分:
代码:
2 packets captured        // 捕获的包的数量
49 packets received by filter  // 被过滤的包的数量
0 packets dropped by kernel    // 被内核丢弃的包的数量
接下来我们监听一下当电脑的IP地址发生变更的时候会有什么情况发生,
执行 windump -n arp, 然后我更改本机IP为192.168.1.24
名称:  04.jpg
查看次数: 357
文件大小:  153.2 KB

可以看到,我的电脑先向本地网络进行广播<目标MAC为 FF:FF:FF:FF:FF>,询问是否有主机在使用192.168.1.24这个地址,
在广播了三次没有收到回复之后就设置本机IP为192.168.1.24,之后又广播一条信息来询问网关的MAC地址.
前面的三次广播源地址都设置为了0,我想此时可能因为本机IP已经改变而且新的IP还没有正式被启用的缘故<此时没有IP>
而局域网中数据传输是不需要IP地址的,只依靠MAC就能进行通讯

如果本地网络中有人占用了我们向设置的IP,会在广播之后收到一条回复,表示"我正在使用这个IP,你不能使用它",
接下来我们将会看到Windows的窗口提示,然后本机IP会被设置为一个值<我不知道这个值是否是随机的.不过它不属于本网络>
接下来毫无疑问地断网了,大家有条件的可以试一下



下面看复杂一点的,观察浏览器在连接网站时的底层封包发送接收流程,为了减少干扰,我关闭了所有能联网的程序.
我们使用 windump -n ip 命令,也就是将IP包过滤上来,不过却出现了莫名的干扰:
名称:  07.jpg
查看次数: 354
文件大小:  99.7 KB

过滤出了很多路由器的组播包,我们需要再次向windump传递过滤指令.
我们使用 windump -n ip and not host 239.255.255.250
如果我们打算向windump传递多于一个的条件表达式作为过滤条件的时候需要用 and 将它们连接起来
这里的 ip 和 not host 239.255.255.250 就属于两个条件表达式,可以想象为C的描述 if ( ip && !host )

host用来指定主机, windump host 192.168.1.1 表示过滤出所有 192.168.1.1 相关的封包,包括收和发
windump src host 192.168.1.1  表示过滤出所有 192.168.1.1 发出的封包
windump dst host 192.168.1.1  表示过滤出所有 192.168.1.1 收到的封包

那么这里 not host 239.255.255.250 就表示收发地址中不包括 239.255.255.250 的封包

windump -n ip and not host 239.255.255.250
表示过滤表示收发地址中不包括 239.255.255.250 的IP封包,且不要将主机地址显示为主机名称
更多的条件表达式用法大家可以搜一搜,用法非常灵活


执行命令前我用ipconfig /flushdns清空了本地dns缓存,这样就可以也将dns的查询情况捕获了
另外如果捕获大量的封包,应该对CMD窗口进行一下调整,防止因显示行数不足之前的回显被覆盖掉.
主要就是调整屏幕缓冲区大小以及窗口的宽度
名称:  08.jpg
查看次数: 344
文件大小:  34.6 KB

同时为了显示的更直观,最好使用IE浏览器
现在我们进行一下封包的捕获,先执行 windump -n ip and not host 239.255.255.250 然后打开IE连接 www.baidu.com
瞬间CMD窗口就铺满了:
名称:  09.jpg
查看次数: 352
文件大小:  377.0 KB


我们可以想一下:当浏览器连接一个网站时,首先需要知道其IP地址,这需要通过DNS服务来获取,
当前前提是在本地DNS缓冲中没有相关记录的情况下,但是之前我们清空了本地DNS,
所以迫使系统必须借助DNS服务来获取连接目标的IP地址

我们捕获的前个封包正是系统发送和接收到的DNS查询和回复,下面第三个封包就开始与目标建立连接了.
先来看一下DNS封包中都有什么内容.
再次使用ipconfig /flushdns 清空了dns缓冲,然后再次监听封包,但是这次我们打印出封包的内容,而且进行更严密的过滤

windump -n -s0 -XX ip and src host (192.168.1.1 or 192.168.1.23) and dst host (192.168.1.1 or 192.168.1.23)
过滤表达式表示过滤出发送端IP为 192.168.1.1 或 192.168.1.23 并且 接收端IP为 192.168.1.1 或 192.168.1.23 的IP封包
也就是说只监听dump出 192.168.1.1 和 192.168.1.23 的双向通讯
新添加的 -s0 参数表示dump整个封包大小,默认windump只是dump最大96个字节的封包,这将导致封包dump不全

再次监听,连接百度:
点击图片以查看大图

名称:	10.jpg
查看次数:	2
文件大小:	362.3 KB
ID:	65377

前两个封包是对www.baidu.com这个域名的DNS查询, 下面是对gimg.baidu.com域名的查询,这里只看前两个封包
先看一下关于DNS报头的一些信息

// DNS报文
代码:
 0                            15                              31
-----------------------------------------------------------------
|        Transaction ID         |            Flags              |
-----------------------------------------------------------------
|           Questions           |         Answer RRs            |
-----------------------------------------------------------------
|         Authority RRs         |        Additional RRs         |
-----------------------------------------------------------------
|                           Question                            |
-----------------------------------------------------------------
|                            Answer                             |
-----------------------------------------------------------------
|                           Authority                           |
-----------------------------------------------------------------
|                           Additional                          |
-----------------------------------------------------------------
<下面信息摘自 TCP IP详解>
报头中前12字节是必需的,也就是前6个域,下面四个域可选

Transaction ID   : 客户程序设置并由服务器返回,用来进行匹配
Flags      : 该域被分割为多个字段
          --------------------------------
          |Q|  op   |A|T|R|R|  0  | rcode|
          |R|       |A|C|D|A|     |      |
          --------------------------------
           1    4    1 1 1 1   3     4
           //QR  : 0表示查询报文 1表示响应报文
           //op  : 通常值为0表示标准查询,1表示反向查询
           //AA  : 表示授权回答,该名字服务器是授权于该域的
           //TC : 表示可截断.使用UDP时,表示当应答长度超过512字节,只返回前512字节
           //RD : 表示期望递归.它在查询中设置并在响应中返回.置为1表示必须处理这个查询,如果置0,服务器可能在没有一个授权回答时返回一个能解答该查询的其他名字服务器列表
           //RA  : 表示可用递归.如果名字服务器支持递归查询,则在响应中将该比特置1
           //rcode  : 返回码字段.0表示没有差错,3表示名字差错表示指定的域名不存在
后面四个双字节长的字段表示后面可选的域的条目数目
一般查询报文会将Questions置1,其余填0;应答报文回答数至少是1,剩下的两项是0或非0

//Question部分格式如下:
代码:
 0                            15                              31
-----------------------------------------------------------------
|                            Name                               |
-----------------------------------------------------------------
|          Type                |           class                |
-----------------------------------------------------------------
Name指要查找的名字,它是一个或多个标识符序列.每个标识符以首字节的计数值来说明随后标识符的字节长度
每个名字以最后字节为0结束.计数字节值必须是0-63的数

每个问题有一个类型Type,每个响应也有一个类型
代码:
  -----------------------------------------------------------------
      名字   |   数值   |        描述         | 类型 | 查询类型
  -----------------------------------------------------------------
    A        |      1   |   IP地址            |
    NS       |      2   |   名字服务器        |
    CNAME    |      5   |   规范名称          |
    PTR      |     12   |   指针记录          |
    HINFO    |     13   |   主机信息          |
    MX       |     15   |   邮件交换记录      |
  -----------------------------------------------------------------
    AXFR     |    252   |   对区域转换的请求  |
    ANY      |    255   |   对所有记录的请求  |
  -----------------------------------------------------------------
常用的查询类型是A,表示获得域名的IP;PTR请求获得IP地址对应的域名
class通常置1,表示互联网地址


//Answer Authority Additional部分
这三部分使用同一种格式称作资源记录<Resource Record RR>
代码:
 0                            15                              31
-----------------------------------------------------------------
|                              Name                             |
-----------------------------------------------------------------
|           Type                |            Class              |
-----------------------------------------------------------------
|                              TTL                              |
-----------------------------------------------------------------
|           Data Len            |           Data                |
---------------------------------
|                             Data                              |
-----------------------------------------------------------------
Name Type Class与上面的那些字段相同
TTL是客户程序保留该资源记录的秒数
DataLen说明资源数据的数量
Data的格式依赖于类型字段的值对于类型1资源数据是4字节的IP地址


下面先解析第一个包,也就是DNS查询封包
代码:
IP 192.168.1.23.49439 > 192.168.1.1.53:  13992+ A? www.baidu.com. (31)
0x0000:  0025 8699 2cd6 0030 18a2 17f7 0800 4500  .%..,..0......E.
0x0010:  003b 1607 0000 8011 0000 c0a8 0117 c0a8  .;..............
0x0020:  0101 c11f 0035 0027 83a1 36a8 0100 0001  .....5.'..6.....
0x0030:  0000 0000 0000 0377 7777 0562 6169 6475  .......www.baidu
0x0040:  0363 6f6d 0000 0100 01                   .com.....
前14字节是以太头,其中协议域是 0800 也就是说后面是ip头,其中ip头长的指示域为5,它表示ip头的双字个数为5,所以字节长为20,
其中ip头的协议域为 0x11 <地址0x0017处>,所以跟在ip头后面的是UDP头,起始地址为 0x000E+0x14=0x22
UDP头中源端口号为 0xc11f = 49439; 目的端口号 0x0035 = 53
越过8字节长的UDP头就到了DNS报头位置 0x002C: 36a8

结合DNS头结构看一下:
Transaction ID  : 36a8 ID号,它应当被服务器传回用来进行包的匹配确认
Flags      : 0100 转为二进制:0000 0001 0000 0000 结合前面的标志位说明,这个标志是递归查询标志,表示必须完成这个查询
Questions    : 0001 问题数1
Answer      : 0000 没有回答数
Authority    : 0000 没有授权回答
Additional    : 0000 没有附加信息

走完DNS报头,下面到了Question域
Question域首个域是Name,它是一个或多个标识符序列.每个标识符以首字节的计数值来说明随后标识符的字节长度
在这里表示方法就是分段描述,www用03描述,baidu用05描述,com用03描述,最后以一个00字节结尾

然后是Type域两个字节长,起始地址 0x0045,值为 0001 表示 A - 查询IP地址
Class域一般总是 0001

最后回过头看一下 IP 192.168.1.23.49439 > 192.168.1.1.53:  13992+ A? www.baidu.com. (31)
基本就能看懂了 13992 代表了Transaction ID
A 代表了查询类型,后面就是要查询的域名,31表示DNS包长度




下面看一下DNS的查询回答,第二个包
代码:
IP 192.168.1.1.53 > 192.168.1.23.49439:  13992 3/6/6 CNAME www.a.shifen.com., A 119.75.218.77, A 119.75.217.56 (294)
0x0000:  0030 18a2 17f7 0025 8699 2cd6 0800 4500  .0.....%..,...E.
0x0010:  0142 17a3 0000 4011 de9f c0a8 0101 c0a8  .B....@.........
0x0020:  0117 0035 c11f 012e b79a 36a8 8180 0001  ...5......6.....
0x0030:  0003 0006 0006 0377 7777 0562 6169 6475  .......www.baidu
0x0040:  0363 6f6d 0000 0100 01c0 0c00 0500 0100  .com............
0x0050:  0002 3200 0f03 7777 7701 6106 7368 6966  ..2...www.a.shif
0x0060:  656e c016 c02b 0001 0001 0000 00c3 0004  en...+..........
0x0070:  774b da4d c02b 0001 0001 0000 00c3 0004  wK.M.+..........
0x0080:  774b d938 c02f 0002 0001 0000 2710 0006  wK.8./......'...
0x0090:  036e 7332 c02f c02f 0002 0001 0000 2710  .ns2././......'.
0x00a0:  0006 036e 7335 c02f c02f 0002 0001 0000  ...ns5././......
0x00b0:  2710 0006 036e 7334 c02f c02f 0002 0001  '....ns4././....
0x00c0:  0000 2710 0006 036e 7336 c02f c02f 0002  ..'....ns6././..
0x00d0:  0001 0000 2710 0006 036e 7339 c02f c02f  ....'....ns9././
0x00e0:  0002 0001 0000 2710 0006 036e 7337 c02f  ......'....ns7./
0x00f0:  c066 0001 0001 0000 021b 0004 7b7d 7142  .f..........{}qB
0x0100:  c08a 0001 0001 0000 021b 0004 7b7d 7143  ............{}qC
0x0110:  c078 0001 0001 0000 021b 0004 dcb5 03b2  .x..............
0x0120:  c09c 0001 0001 0000 021b 0004 dcb5 04b2  ................
0x0130:  c0c0 0001 0001 0000 0015 0004 dcb5 262f  ..............&/
0x0140:  c0ae 0001 0001 0000 00fb 0004 3d87 a6e2  ............=...
Transaction ID  : 36a8 ID号
Flags      : 8180 转为二进制:1000 0001 1000 0000 最高位为1表示响应
Questions    : 0001 问题数1
Answer      : 0003 回答数3
Authority    : 0006 授权回答6
Additional    : 0006 附加信息6

Question地址范围: 0x0035~0x0048 与前面的问题相同
第一个Answer起始地址: 0x0049
这里有一个特例,就是当Name域首个字节是0xC0的时候要进行跳转,规则是跳转到距离DNS报头的一个偏移地址,
这个偏移地址由0xC0后面的一个字节给出<如果目标地址首个字节还是0xC0,需要继续跳转>,
这里的偏移是0x0C,加上DNS报头地址 0x002A 得到地址 0x0036 这里是百度域名的起始,
所以第一个Answer的Name域为 www.baidu.com

接下来是Type域: 0x004B, 值为 0005, CNAME - 规范名称<具体什么意思我也没弄懂,大概就像是域名跳转>
Class域    : 0x004D, 值为 0001
TTL域    : 0x004F, 值为 00000232
DataLen域  : 0x0053, 值为 000F
data域是一个字串: www.a.shifen.com, 注意最后的com是经过跳转得到 

第一个应答:
Name  : www.baidu.com
TYPE  : CNAME
CLASS  : 1
TTL    : 0x232
LEN    : 0x0F
DATA  : www.a.shifen.com

后面的应答,授权回答以及附加信息都可以依次推导出来

可以想象,这些回答随后都会被系统存到本地缓存中,可以通过ipconfig /displaydns 查看一下:
名称:  11.jpg
查看次数: 340
文件大小:  86.8 KB


现在,再使用 windump -n ip and not host 239.255.255.250 看一下<清空dns缓冲之后>:
名称:  13.jpg
查看次数: 343
文件大小:  465.9 KB

前两个封包进行DNS查询,之后就可以看到熟悉的TCP的三次握手了,
代码:
 IP 192.168.1.23.50749 > 119.75.217.56.80: S 4004469303:4004469303(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>
 IP 119.75.217.56.80 > 192.168.1.23.50749: S 2551825006:2551825006(0) ack 4004469304 win 8192 <mss 1440,nop,nop,nop,nop,nop,nop,sackOK>
 IP 192.168.1.23.50749 > 119.75.217.56.80: . ack 1 win 64800
 IP 192.168.1.23.50749 > 119.75.217.56.80: P 1:409(408) ack 1 win 64800
 IP 119.75.217.56.80 > 192.168.1.23.50749: . ack 409 win 6432
 IP 119.75.217.56.80 > 192.168.1.23.50749: P 1:412(411) ack 409 win 6432
 IP 119.75.217.56.80 > 192.168.1.23.50749: . 412:1852(1440) ack 409 win 6432
 IP 192.168.1.23.50749 > 119.75.217.56.80: . ack 1852 win 64800
 IP 119.75.217.56.80 > 192.168.1.23.50749: . 1852:3292(1440) ack 409 win 6432
 IP 119.75.217.56.80 > 192.168.1.23.50749: P 3292:3812(520) ack 409 win 6432
 IP 192.168.1.23.50749 > 119.75.217.56.80: . ack 3812 win 64800
 IP 192.168.1.23.50749 > 119.75.217.56.80: P 409:816(407) ack 3812 win 64800
 IP 192.168.1.23.50367 > 192.168.1.1.53:  60818+ A? gimg.baidu.com. (32)
 IP 192.168.1.23.50750 > 119.75.217.56.80: S 535857440:535857440(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>
 IP 192.168.1.23.50751 > 119.75.217.56.80: S 271755341:271755341(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>
 IP 119.75.217.56.80 > 192.168.1.23.50749: . ack 816 win 7504
默认情况下windump显示格式如下:
协议 源IP.端口 > 目的IP.端口
后面则是根据情况显示, 如果是TCP连接一般首先是TCP封包中的标志比如见到的 S<SYN> P<PSH>,如果没有标志被置位则显示".",
后面将是序号和确认号,确认号如果有效<ACK标志被置位>,将会以 ack xxxx 的形式显示出来
不过默认情况序号和确认号会以增量的形式表示,比如第三行第四行,表示对于第一个序号的增量,通过添加 -S 参数将可以打印绝对序号

后面的win xxxx表示滑动窗口的大小,再之后就是一些附加的选项
下面的注释针对于上面的封包,各行序号对应入座
1.发起连接,向服务器发送SYN封包
2.服务器确认SYN分包并向我们发送服务器的SYN封包
3.确认收到服务器的SYN封包,连接正式建立起来
4.向服务器提交请求数据
5.服务器确认收到请求数据
6,7:服务器向我们传送网页数据,两次共传递1852字节
8.向服务器确认收到了1852字节数据
9,10:服务器向我们传送网页数据,共3812字节<加上之前>
11:向服务器确认收到了总共3812字节的数据
12:向服务器提交请求数据
13:进行DNS查询,域名为gimg.baidu.com.
14~16:发起另外一个连接

基本上TCP传输都是这样进行,服务器没法送两三个携带数据的封包,我们客户端就进行一次确认

最后再说一下win的作用,这个是向服务器说明客户端这里还有多大的缓冲区用来接收数据,
服务器会根据这个值来调整自己发送的封包的长度,如果指定为0,则服务器会暂停发送,
直到再次收到另一个封包指定了一个非0值的win,此时ack与上一个相同

写了这么多手都麻了,也不知道自己的这些理解是否是正确的,
如果有错误,希望能得到指正, QQ:2575439022

windump : 也包含了Windows下面能用的tcpdump
tcpdump.rar[谁下载?]


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多