网络协议分析
第1章
杂七杂八的知识点
-
wireshark功能:
- 检测网络问题
- 为新通信协议除错
- 学习网络协议
-
wireshark特点:不会修改和发送封包
-
wireshark支持的过滤器
- Display Filter:显示过滤器
- Capture Filter:捕捉过滤器(菜单栏中的Capture)
-
wireshark界面组成:
-
菜单栏
-
快捷方式
-
显示过滤器
-
封包列表
-
封包详细信息
-
解析器,即16进制数据查看面板
-
杂项
-
捕捉过滤器过滤规则
-
两种形式:
-
原语(Primitive)
-
关系运算符(and,or,not,小括号())将原语组合构成的表达式
[not] primative [and | or] primitive
-
-
捕捉过滤器示例
[]是可选项,<>是必填项
ether [src | dst] host <mac_addr> # 捕获源/目的mac是mac_addr的以太网帧 [src | dst] host <ip_addr> # 捕获源/目的IP是ip_addr的 <tcp | udp> [src | dst] port <number> # 捕获源/目的端口号是number的tcp/udp协议的包 arp | ip | icmp | udp | tcp # 捕获这些协议的包
-
显示过滤器示例
可以由运算符(==; >; <=; !=; &&; ||; !; ())进行连接
eth.addr == <mac_addr> # 显示以太网地址为mac_addr的所有帧 ip.addr == <ip_addr> # 显示ip地址为ip_addr的所有包 tcp.port == <port_number> # 显示端口号为80的所有tcp包
WinPcap
介绍
-
WinPcap介绍:基于Win32平台,利用网络数据包捕获库函数,捕获网络数据包并进行分析的开源库,为应用程序提供了一组API接口
-
组成:
- 内核级数据包过滤器
- 低层动态链接库(packet.dll)
- 高层依赖系统的库(wpcap.dll)
部分内容运行在操作系统内核,直接访问网络接口驱动(Netgroup Packet Filter,NPF)
-
功能:
- 捕获原始数据包
- 发送原始数据包
- 数据包发送给应用程序前根据用户规则过滤数据包
- 收集并统计网络流量信息
-
WinPcap典型应用
- 网络与协议分析器
- 网络扫描器,监视器
- 网络流量记录器,发生器
- 用户级网桥及路由
- 网络入侵检测系统
- 安全工具
-
WinPcap能独立地发送和接收数据,但是无法操纵数据,不支持网络流量控制,服务质量调度和个人防火墙
-
使用Hub等基于共享的网络,网络接口处于混杂模式,可以监听到网络上所有数据
-
WinPcap和LibPca最强大特性之一是:拥有过滤数据包引擎
WinPcap编程
流程
- 获得已连接的网络适配器列表(pcap_findalldevs_ex())
- 打开适配器(pcap_open())
- 设置过滤器(pcap_compile(),pcap_setfilter())
- 开始捕获数据包(pcap_loop() / pcap_next_ex())
- 解析数据包(packet_handler())
捕获数据包
-
pcap_findalldevs_ex()
int pcap_findalldevs_ex ( char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf )
获得已连接的网络适配器列表,列出本地机器或远程机器的设备
-
Parameters:
-
source: 指明适配器类型为本地/远程接口
PCAP_SRC_FILE_STRING
:“file://”PCAP_SRC_IF_STRING
:“rpcap://” -
auth: 存储远程主机连接所需的认证信息,请求本地主机时可置为NULL
-
alldevs: 存储网络适配器列表中的第一个接口
-
errbuf: 返回的错误信息
-
-
Returns:
函数执行正常返回0
函数执行过程有错误发生返回-1,并将错误信息存储到errbuf中
已连接的网络适配器列表存储在alldevs变量中
struct pcap_if { struct pcap_if *next; char *name; char *description; struct pcap_addr *addresses; bpf_u_int32 flags; };
-
-
pcap_open()
pcap_t* pcap_open ( const char * source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth * auth, char * errbuf )
打开适配器开始捕获数据包
Parameters:
-
source:指明要打开适配器的名称
-
snaplen:数据包保留长度
-
flags:设置适配器属性
PCAP_OPENFLAG_PROMISCUOUS
:混杂模式 -
read_timeout:等待时间(毫秒),一个数据包的时候读操作不必立即返回,而是等待一段时间,让更多的数据包到来后从OS内核一次读多个数据包
-
auth:存储远程主机连接所需的认证信息,请求本地主机时可置为NULL
-
errbuf:返回的错误信息
Returns:
无错误发生返回pcap_t类型指针
有错误发生返回NULL,并将错误信息存储到errbuf中
-
-
pcap_compile()
int pcap_compile ( pcap_t * p, struct bpf_program * fp, char * str, int optimize, bpf_u_int32 netmask )
编译过滤器,将一个高层的布尔过滤表达式编译成一个能够被过滤引擎所解释的低层的字节码
-
pcap_setfilter()
int pcap_setfilter ( pcap_t * p, struct bpf_program * fp )
设置过滤器,将一个过滤器与内核捕获会话相关联。所有的符合要求的数据包将会立即复制给应用程序
-
pcap_next_ex() / pcap_loop()
int pcap_loop ( pcap_t * p, int cnt, pcap_handler callback, u_char * user )
循环抓取cnt个网络数据包。每捕获到一个报文就调用用户设定的callback函数
使用 pcap_loop()函数捕获数据包时, 应用程序不能直接控制数据包处理函数的调用,这个包处理函数是自动由包捕获驱动程序调用的
Parameters:
- p:操作句柄
- cnt:每一次调用pcap_loop的抓包数
- callback:用户自定义的数据包处理函数
- user:一般设置为NULL
Returns:
0:处理完cnt个数据报
-1:有错误发生,并将错误信息存储到errbuf中
-2:在输出数据包之前因调用pcap_breakloop而终止循环
int pcap_next_ex (
pcap_t * p,
struct pcap_pkthdr ** pkt_header,
const u_char ** pkt_data
)
从接口或离线记录文件获取一个报文
该函数就是不用回调函数捕获数据包的方法
只在Win32下可用
**Parameters:**
1. p:操作句柄
2. pkt_header:数据报文头
3. pkt_data:数据报数据缓冲区
**Returns:**
1:数据包读取无错误发生
0:时间到达pcap_open()设置的时间
-1:有错误发生
-2:离线捕获器已达文件尾
6. pcap_handler
```c
typedef void(* pcap_handler)(
u_char *user,
const struct pcap_pkthdr *pkt_header,
const u_char *pkt_data
)
数据包分析回调函数原型
Parameters:
-
user:回调函数调用者,保存capture session的状态
-
pkt_header:数据报文头
-
pkt_data:数据报数据缓冲区
-
pcap_freealldevs()
void pcap_freealldevs ( pcap_if_t * alldevsp )
关闭网络设备,释放由pcap_findalldevs_ex生成的网络适配器列表空间
Parameters:
alldevsp:网络适配器列表
-
pcap_close
void pcap_close ( pcap_t * p )
关闭WinPcap句柄
Parameters:
p:WinPcap句柄
发送数据包
原始libpcap不支持发送数据包,发送函数均是winpcap的扩展
-
pcap_sendpacket(pcap_t *fp, packet, 100(size))
:发送单个数据包,数据包直接发送到网络,不会进行加工处理,需要手动创建一个正确的协议首部 -
pcap_sendqueue_alloc()
:创建一个队列 -
pcap_sendqueue_queue()
:向队列中加入一个包 -
pcap_sendqueue_transmit()
:将队列发送出去 -
pcap_sendqueue_destroy()
:删除一个队列
收集统计流量信息
- pcap_open()打开适配器,通过read_timeout设置统计时间间隔
- pcap_setmode()设置设备为统计模式
- pcap_loop()开始统计
- 在pcap_handler()参数中包含统计信息,pkt_data包含了最后一个时间间隔内,收到的数据包数量和字节总数
第2章
以太网帧
-
硬件地址 == 物理地址 == MAC地址
-
802说的地址,严格意义上是指每一个站的名字或标识符
-
48位MAC地址 = 高24位(IEEE注册管理结构RA分配) + 低24位扩展标识符(厂家自行指派),MAC地址是适配器地址或适配器标识符EUI-48(通用名称)
-
适配器仅收下发往本站的帧,即
- 单播(unicast)帧(一对一)
- 多播(multicast)帧(一对多)
- 广播(broadcast)帧(一对全体)
-
以太网MAC帧格式2种标准:
- DIX Ethernet V2标准(最常用)
- IEEE 802.3标准
-
MAC帧的FCS字段采用CRC校验
-
格式
类型字段取址:
类型值 上一层的协议类型 0x0800 IP数据报 0x0806 ARP地址解析协议 0x8863 PPPoE发现阶段 0x8864 PPPoE会话阶段 -
合法帧要求
- 帧长是整数个字节
- 帧校验序列FCS计算正确
- MAC长度在64~1518字节,数据部分46 ~ 1500字节,加上头尾的18字节
PPPoE
Point-to-Point Protocol over Ethernet:以太网上的点对点协议
-
提供了在广播式网络中多台主机连接到远端的访问集中器(AC或宽带接入服务器),对用户进行计费和管理
-
用户主机要能够独立初始化自己的PPP协议栈
-
主机与访问集中器之间要建立唯一的点对点会话
-
用途:ppp协议中没有地址信息,无法在以太网中传播,将其封装在pppoe中即可传播,pppoe类似一个交通工具
-
帧格式:
- Code:指示报文类型(IORST,971965a7)
- Length:净载荷长度,即Length后面那部分长度
- 净载荷域(Length后面的字段):发现阶段填充一些Tag(TLV编码方式),会话阶段包含无标志,地址,控制域的PPP数据报文
报文类型 报文CODE域值 PADI(发现初始报文) 0x09 PADO(提供) 0x07 PADR(请求) 0x19 PADS(会话确认) 0x65 PADT(终止) 0xa7 会话阶段数据 0x00
PPP
Point-to-Point Protocol:点对点协议,数据链路层
-
应用场景:用户使用拨号电话线接入因特网
-
满足的需求
- 简单(首要要求)
-
3个组成部分
- 一个将IP数据报封装到串行链路的方法
- 链路控制协议LCP:Link Control Protocol
- 网络控制协议 NCP:Network Control Protocol
-
PPP是面向字节的,帧长都是整数字节
-
PPP协议字段
协议字段值 上层协议类型 0x0021 IP报文 0xC021 LCP 0x8021 IPCP 0xc023 安全性认证PAP 0xc223 安全性认证CHAP -
PPP同步传输采用硬件完成比特传输;异步传输采用字符填充法
字符填充方法:0x7E->(0x7D, 0x5E),0x7D->(0x7D,0x5D),ASCII->(0x7D, 原ASCII码)
PPP协议用在SONET/SDH链路时,是同步传输,此时采用零比特填充方法实现透明传输
-
PPP协议不采用序号和确认机制原因:
- 链路层出错概率不大
- 链路层可靠传输无法保证网络层可靠传输
- 帧校验序列FCS可保证无差错接受
发现阶段((Discovery Stage))
无论哪一阶段的报文最终都会被封装为以太网的帧
-
发现阶段任务:用户主机和AC获知对方的MAC地址(PADI+PADO完成)和唯一的会话ID号(PADR+PADS完成)
- 会话ID作用:保证连接有效性
- MAC地址+会话ID:可以完全确定对方点对点关系
-
PADI
PPPOE Active Discovery Initiation:发现初始报文
- 查找网络中的PPPoE服务器
- 广播
- 用户主机发出
- session-id=0x0000
-
PADO
PPPOE Active Discovery Offer:发现提供报文
- 这里的数据包第一次包含了AC的MAC,目的MAC为PADI中的用户主机MAC
- 单播
- AC发出
- session-id=0x0000,tag中包含ac-name
-
PADR
PPPOE Active Discovery Request:发现请求报文
- 请求会话号
- 单播
- 用户主机发出
- service-id=0x0000
-
PADS
PPPOE Active Discovery Session-confirmation:发现会话确认报文
- AC确定会话ID,通过此报文发送给用户主机
- 单播
- AC发出
- session-id:访问集中器确定的会话id
-
PADT
会话终止报文
- 单播
- 会话建立后可在任何时间由用户主机或AC发出
- session-id:要终止的session对应的id
会话阶段(Session Stage)
发现阶段确定好双方MAC地址和会话ID后,之后就都是会话阶段了。
会话阶段可以分为2部分,未接入互联网(PPP3个过程阶段)和已接入互联网(PPP3个过程结束后阶段)
下面只讨论未接入互联网,即PPP的3个过程
-
PPP链路建立过程
- 创建阶段
- 认证阶段
- 网络协商阶段
-
创建链路阶段
就是ppp帧的数据部分填充上了LCP的数据
建立,配置,维护,终止一条点对点链路,对通讯方式进行选择
Ack: 所有选项都理解且可接收
Nak: 所有的选项都理解但不可接收
Reject: 选项有的无法理解或不能接收,需要协商
数据字段取值
LCP的数据部分也是TLV(type-length-value)格式
TYPE对应数值 配置内容 0x01 MTU最大传输单元 0x03 Authentication-Protocol进行验证使用的协议 0x04 Quality-Protocol传输质量检测协议 0x05 Magic-Number魔术字 0x07 Protocol-Field-Compression协议域字段压缩 0x08 Address-And-Control-Field-Compression地址控制字段压缩 -
认证阶段
把PPP的数据部分填充上PAP或CHAP
仅LCP,认证协议和链路质量监视协议packets被允许
常用认证协议:口令验证协议(PAP),挑战握手验证协议(CHAP)
- PAP:明文验证,在数据部分存在认证用的用户名和密码,两次握手认证协议
-
网络协商阶段
建立、配置不同的网络层协议
-
IPCP静态协商
不协商
PPP协商前已配置好IP地址
此协商过程只是告知对方自身IP
-
IPCP动态协商
一端动态获取IP,另一端手动配置IP且允许给对端分配IP
-
第3章
IP
IP数据包首部分析
首部长度,片偏移
-
版本——占 4 位,指 IP 协议的版本,目前的 IP 协议版本号为 4 (即 IPv4)
-
首部长度-最大15个单位,一个单位4字节
-
总长度-数据报的最大长度为 65535 字节,总长度必须不超过最大传送单元 MTU
-
标识:计数器,用来产生数据报的标识
-
标志-中间位DF (Don't Fragment) ,最低位是 MF (More Fragment)
-
片偏移:某片在原分组中的相对位置。以 8 个字节为偏移单位
todo:如何计算
-
生存时间:数据报被路由器丢弃之前允许通过的最大网段数量
-
协议:此数据报携带的数据使用何种协议,指示交给上层传输层的哪一进程进行处理(数据部分是传输层的什么协议)
eg:ICMP,IGMP,TCP,UDP,OSPF
取值 对应传输层协议 1 ICMP 2 IGMP 6 TCP 17 UDP 89 OSPF -
首部检验和:只检验数据报的首部,不检验数据部分,这里不采用 CRC 检验码而采用简单的计算方法
计算方法(反码算数运算求和取反码):按16位一组,反码有进位求和(最高位进位加到最低位),最后结果取反码得检验和
-
可选字段: 字节,用于支持排错;测量;安全
ARP
ARP协议
Address Resolution Protocol:地址解析协议,网络层 和 数据链路层 接口
-
ARP 用途:解决同一个局域网上的主机或路由器的IP 地址和硬件地址的映射问题。
如果目的主机不再一个网络内,实际上发送端根本就不需要去找目的主机的MAC,它会找网关的MAC,把数据包发送给网关,由网关完成后续的数据包转发工作
-
使用ARP的4种情况
- 主机->本网络另一台主机:用 ARP 找到目的主机的MAC地址。
- 主机->另一个网络一台主机:用 ARP 找到本网络上的一个路由器的硬件地址。剩下的工作由这个路由器来完成。
- 路由器->本网络一台主机:用 ARP 找到目的主机的硬件地址。
- 路由器->另一个网络另一台主机:用 ARP 找到本网络上的一个路由器的硬件地址。剩下的工作由这个路由器来完成
ARP协议分析
-
硬件类型:以太网接口类型为1
-
协议类型:IP协议类型为0x0800
-
硬件地址长度:MAC地址长度为6(Bytes)
-
协议地址长度:IP地址长度为4(Bytes)
-
操作:ARP请求(ARP request)为1,ARP应答(ARP response)为2
-
源MAC地址: (请求或应答报文)发送方的 MAC地址
-
源IP地址: (请求或应答报文)发送方的IP地址
-
目的 MAC 地址:ARP 请求中该字段没有意义;ARP应答中为(应答报文)接收方的MAC地址
-
目的 IP 地址:ARP请求中为请求解析的 IP 地址;ARP应答中为(应答报文)接收方的IP地址
ARP欺骗攻击
- 原理:
- 每个主机都用一个ARP高速缓存存放最近IP地址到MAC硬件地址之间的映射记录
- 缓存中的IP-MAC条目是根据ARP响应包动态变化的。只要网络上有ARP响应包发送到本机,即会更新ARP高速缓存中的IP-MAC条目
- 用伪造源MAC地址发送ARP响应包,可以对ARP高速缓存机制进行攻击。攻击者只要持续不断的发出伪造的ARP响应包就能更改目标主机ARP缓存中的IP-MAC条目,造成网络中断或中间人攻击
第4章
TCP
TCP协议分析
-
源端口,目的端口
-
序号:TCP面向字节流,字节流中每个字节都按照顺序编号。此字段指本报文段所发送数据的第一个字节序号
-
确认号:期望收到对方下一个报文段的第一个数据字节的序号。确认号为N表示到N-1为止的所有数据都已经收到了
-
数据偏移:代表首部长度,以4B为单位
-
保留:就是保留着以后用,置0
-
多个标志位:
- URG:紧急位,为1表示紧急指针有效,表示高优先级数据,与紧急指针配合使用
- ACK:确认位,为1确认号字段才有效
- PSH:为1表示要尽快交付给接收应用程序
- RST:为1表示TCP连接中出现严重差错需要释放重新建立连接
- SYN:为1表示连接请求或连接接受报文,SYN=1,ACK=0:连接请求;SYN=1,ACK=1:连接接受
- FIN:为1表示释放连接
-
窗口:发送此报文一方告知另一方本端还有多少字节的接受缓存空间
-
校验和:校验首部和数据(注意与IP报文段中首部检验和的区别)
计算方法:所有数据依次按照2个字节一组,求得反码进行有进位求和,最终结果取反码即为校验和
-
紧急指针:URG=1时有效,表示该报文段从第1个字节开始到紧急指针所指字节为紧急数据
-
填充:使得首部长度是4B的整数倍
TCP3次握手建立连接
- 客户机TCP向服务器TCP发送连接请求报文段(SYN=1,ACK=0,seq=x),客户机进入SYN-SENT(同步已发送)状态
- 服务器同意建立连接,向客户机发回确认,为TCP连接分配缓存和变量(SYN=1,ACK=1,seq=y,ack=x+1),进入同步收到状态
- 最后都进入已建立连接状态
TCP4次握手结束连接
- 客户端发送FIN=1,进入终止等待1状态
- 服务器发送ACK=1,进入关闭等待状态
- 服务器发送FIN=1,ACK=1,进入最后确认状态
- 客户端发送ACK=1,等待2MSL(最长报文段寿命)后,进入连接关闭状态
2,3步之间,客户端处于终止等待2状态
UDP
特点
- 无连接
- 尽最大努力交付,不保证可靠
- 面向报文,无拥塞控制
- 支持一对一,一对多,多对一,多对多的交互通信
首部字段8个字节,是不包含伪首部的,伪首部仅仅用于计算检验和
检验和的计算方法同tcp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2021-05-29 二分题目总结