网络信息获取之被动获取
TCP/IP协议
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%201.png)
数据包接收:
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%202.png)
以太网的通讯
以太网处理一二层,也就是我们的链路层和物理层,与TCP/IP协议通过ARP和RARP协议进行相互转换。
同时具有载波监听和冲突检测功能。
在以太网中,所有的通讯都是广播的。因此在同一个网段下的所有网络接口都可以访问在物理媒体上传输的数据。
正常情况下,一个网络接口只响应这两种数据:
-
与自己mac地址相匹配的数据帧
-
发向所有机器的广播数据帧
网卡收发数据步骤:
-
网卡接收到传输来的数据,由网卡内的单片程序接收数据帧的目的MAC地址,并由网卡驱动程序的接受模式判断该不该接收
-
如果认为接收则产生中断信号通知CPU
-
认为不接收则直接丢弃
-
CPU得到中断信号产生中断,操作系统根据网卡驱动程序设置的网卡中断程序地址调用驱动程序接收数据
-
驱动程序接收数据后放入信号堆栈让操作系统处理。
网卡有四种接收方式
-
广播方式:该模式下的网卡能够接收网络中的广播信息。
-
组播方式:设置在该模式下的网卡能够接收组播数据。
-
直接方式:在这种模式下,只接收目的网卡的数据
-
混杂模式:在这种模式下的网卡能够接受一切通过它的数据,而不管这个数据是否是传给他的。
被动获取
这里的被动指的是监听/嗅探的方式,收集流经设备的流量。
主要分为串行和旁路模式
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%203.png)
旁路模式的常见网络设备主要是 集线器、交换机
串行模式的常见网络设备主要是 网桥、网关、路由器
进而划分串联监控模式和旁路监控模式
旁路监控主要依赖”镜像端口”功能来实现监控,也就是将数据复制为两份,一份发给镜像端口,一份发给目的端口。
优缺点:
旁路部署起来比较灵活方便,不会影响现有的网络结构,串行需要对现有网络结构进行变动。
旁路模式对原始传递的数据包不会造成时延,不会对网速造成任何影响。而串联模式是串联在网络中的,所有的数据都需要先经过监控系统,检查之后再发给各个客户端,有一定的时延。
旁路监控设备一旦故障或者停止运行,不会影响现有网络,而串联监控设备如果出现故障,会导致网络中断,导致网络单点故障。
总结:
-
对网络结构影响
-
时延
-
单点故障
但是同样旁路也存在局限性。
**数据获取:**旁路需要交换机支持端口镜像才可以实现监控。
**数据管控:**旁路模式采用发送RST包的方式来断开TCP连接,不能禁止UDP通讯。对于UDP应用,还需要在路由器上面禁止UDP端口进行配合。而串联模式不存在这个问题。
串行适用的网络产品:防火墙,数据包过滤设备。
旁路适用的网络设备:内容审计,内容分析,检测设备。
数据分流技术
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%204.png)
主要有三种分流的方式:
-
分光器 将光缆上的光信号直接备份出一份,最简单的方式,设备要求最高。
-
路由交换 交换机需要通过镜像端口
-
HUB 集线器能够看到所有端口的报文
包捕获技术
为了实现被动捕包,将在数据链路层设置旁路监听。
基于socket的网络的编程方法
思路是将网络通讯当作”文件”描述字符进行处理,极大地简化了网络程序开发过程。
Linux内核版本2.0以前的一种套接字类型,可以接收网络上所有的数据包。
数据链路提供者接口(DLPI)
Data Link Provider Interface,定义了数据链路层向网络层提供的服务,是数据链路服务的提供者和使用者之间的一种标准接口,在实现上基于Unix的流机制。数据链路层服务的使用者既可以是用户的应用程序,也可以是访问数据链路服务的高层协议,比如TCP/IP等。
实际上是一种物理设备辅助(
BPF 伯克利数据包过滤器
这个过滤器工作在操作系统的内核层,主要由网络转发部分和数据包过滤两部分组成。
效率很高,而且使用了数据缓存机制,使捕获数据包缓存在内核中,达到一定数量再传递给程序。
实际应用上用Libpcap实现
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%205.png)
理论上来说即使被iptables封禁了某些数据包,tcpdump仍可以抓到,因为tcpdump作用于网络接口层,而iptables作用于IP协议层,tcpdump理论可以先抓到包。
一些常用的库
libnet
提供的接口函数主要实现和封装了数据包的构造和发送过程
libpcap
提供的接口函数主要实现和封装了与数据包截获有关的过程
libnids
提供的接口函数主要实现了开发网络入侵监测系统所必须的一些结构框架
Libdnet
通用网络安全开发包
libicmp等
相对较为简单,封装的是ICMP数据包的主要处理过程(构造、发送、接收等)
协议的关键字段IP/TCP/UDP
IP数据包
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%206.png)
如图所示,每一行为4Bytes,也就是32bits
固定部分有20Bytes。对于可选字段来说,一般是32bit(4Bytes)的整数倍,无最小,最大为40Bytes,当有可选项字段不足32bits的时候,余下的部分用无用数据来填充,所以一个完整的IP包头,最小为20Bytes,最大为60Bytes。
版本号(4bits):
告知IP地址是ipv4地址还是ipv6地址
首部长度(4bits):
告知这个数据包头的长度,由此推断出有无可选项
服务类型TOS(8bits):
按位被定义为 PPP DTRM0
PPP:定义包的优先级,取值越大数据越重要
000 普通 (Routine)
001 优先的 (Priority)
010 立即的发送 (Immediate)
011 闪电式的 (Flash)
100 比闪电还闪电式的 (Flash Override)
101 CRI/TIC/ECP(找不到这个词的翻译)
110 网间控制 (Internetwork Control)
111 网络控制 (Network Control)
D 时延: 0:普通 1:延迟尽量小
T 吞吐量: 0:普通 1:流量尽量大
R 可靠性: 0:普通 1:可靠性尽量大
M 传输成本: 0:普通 1:成本尽量小
0 最后一位被保留,恒定为0
总长度(16bits):
告知IP数据报文的总长度(包括被分片数据在内),最大承载量为1500字节,超过将进行数据分片
片偏移量(13bits):
决定IP分片数据的先后顺序,只能是0或1480的倍数,第一个分片数据发送时偏移量为0,第二个为1480,第三个为2960,以此类推。目的端重组数据包时靠偏移量来按顺序组合分片数据
标志位(3bits):
第一位bit未启用为0
第二位bit如果需要分片第二位为0,不需要分片第二位为1
第三位比特为1代表还有后续分片,为0代表为最后一个分片共有三种情况:
001(需要分片且还有后续分片)
000(需要分片且当前为最后一个分片)
010(不需要分片)
标识符(16bits):
区分不同的IP数据包的分片数据,在目的端重组分片数据时能快速找到同一数据包的分片数据
生存时间TTL(8bits):
范围为1-255;单位为跳数,数据包每经过一台路由器即为一跳,TTL值减一;当TTL为0时,丢弃数据包。作用是防止数据包在网络中永久的循环
Windows系统TTL一般为128,Linux系统TTL为1-128之间,通常为56,64。注:跳点跟踪命令:tracert IP地址
协议(8bits):
区分上层协议;6代表TCP协议,17代表UDP协议
首部校验和(16bits):
校验三层IP包头是否有误
源IP地址(32 bits):
指发送数据包的主机地址
目的IP地址(32 bits):
指接收数据包的目标主机地址
选项字段:
通常不会使用到,因为IP包头部分的长度单位为32bit,因此可选项字段的长度必须为32bit的整数倍,当使用时且剩余部分不足32bit会自动填充无用数据来补足32bit。
UDP数据包
这个容易理解,首部大小为8 Bytes,注意这里是数据包长度
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%207.png)
TCP数据包
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%208.png)
flag位:
1)CWR、ECE,与IP首部的ECN字段对应,ECE标志为1,则通知对方网络拥塞,已将拥塞窗口缩小。
2)URG:urgent flag,置1是表示数据需要紧急处置
3)ACK:acknowledgement flag,置1时,确认应答字段有效,除了建立连接的SYN包之外均应置1
4)PSH:push flag,置1时,应立刻传给上层应用协议,PSH置0时,并不需要立刻传而是先缓存
5)RST:reset flag,置1时表示TCP连接出现异常必须紧急断开连接。
6)SYN:synchronize flag,用于建立连接,并在其序列号字段进行序列号初始值设置。
7)FIN:finish flag,置1时希望断开连接。
5-1.校验和:16位,包括首部和数据这两部分。在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。
网络捕包的基本流程
-
把网卡等同于文件进行I/O
查找网卡:Find all devices()
打开网卡:open()
-
从网卡中读取数据
监听:loop()
数据回传给用户变量
-
处理获取的数据
转用户程序执行:Handler()
-
释放I/O资源
与TCP有关
读者不懒,读者不懒不太可能。
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%209.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2010.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2011.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2012.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2013.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2014.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2015.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2016.png)
高性能捕包
造成丢包的主要原因是:
-
CPU处于频繁中断状态,造成接收数据包效率低下。
-
数据包被多次拷贝,浪费了大量的时间和资源。从网卡驱动到内核,再到内核到用户空间。
Linux传统优化技术-NAPI技术(DMA)
NAPI(New API)技术是linux上采用的一种提高网络处理效率的技术,它的核心就是不采用中断的方式读取数据,取而代之的是采用中断唤醒数据接收的服务程序(软中断),然后用POLL的方法来轮询数据。
NAPI技术的设备轮询机制具体特点如下:
-
当一个网卡接收到一个数据包,便产生一个中断信号给系统
-
系统进行如下操作:
关闭网卡中断(屏蔽了中断信号,网卡仍然可以接收数据报到缓冲队列)
激活轮询进程,对该网卡进行轮询(处理缓冲队列)
打开网卡中断(解除屏蔽中断信号)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2017.png)
DMA技术
DMA技术不过多介绍了,可以在DMA控制器下,将数据从网卡拷贝到主存,拷贝过程中,CPU是不参与的。直接避免开销。
无锁环形队列
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2018.png)
通过mmap实现零拷贝I/O
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2019.png)
简单来说就是将内存直接映射到内核区域,不需要经过拷贝了,只是页表的替换(
mmap原理:虚拟内存可以通过页目录,页表映射到物理内存地址,也可以直接映射到物理磁盘(文件)上。当内核的一块内存区域映射到一个文件,而用户进程(server进程)又关联到这个文件,那么用户即可直接操作这块区域了。此时如果映射的内存是DMA的内存区域,即可实现零拷贝
传统的报文分组捕获模型和零拷贝报文获取方式对比
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2020.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2021.png)
ebpf技术(kernel bypass)
bpf是linux内核中高度灵活和高效的类似虚拟机的技术,允许以安全的方式在各个挂钩点执行字节码。它用于许多Linux内核子系统,最突出的是网络、跟踪和安全。
ebpf是比较新的扩展的BPF技术,具有更为庞大的功能体系。
实际上的运用就是kernel bypass技术,也就是内核旁路技术,跳过内核的网络层,在用户态user-space做全部的包处理。kernel bypass涉及到从user-space管理NIC(network interface controller,网卡),也就是需要用户态的驱动程序来处理NIC。
用户态程序完全控制NIC,有什么好处呢?减少了内核开销;等
坏处呢?用户程序需要直接管理硬件;kernel被完全跳过,所以内核提供的所有网络功能也被跳过,用户程序可能需要实现一些原来内核提供的功能;
BPF是一个VM,它定义了一个程序执行的环境。除了字节码,它还定义了基于数据包的内存模型(packet-based memory model)、寄存器(A and X; Accumulator ans Index register)、暂存内存(scratch memory)、隐式程序计数器(implicit pc)。
xdp(kernel bypass)
XDP的全称是:eXpress Data Path
XDP是Linux内核中提供高性能、可编程的网络数据包处理框架。
-
直接接管网卡的RX数据包(类似DPDK用户态驱动)处理
-
通过运行BPF指令快速处理报文
-
和linux协议栈无缝对接
哈哈难蹦,原来是和ebpf一块工作的,如图:
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2022.png)
NIC中接收到数据包之后。该checkpoint应将数据包传递给eBPF程序,该程序将决定如何处理该数据包:丢弃该数据包(drop)或让其继续通过正常路径(pass). 就像这幅图一样
DPDK(Data Plane Development Kit)高性能包处理(kernel bypass)
产生背景
传统框架的局限性:传统Linux/Unix系统中的协议栈对数据包的处理具有一定的局限性。网卡驱动程序运行在Linux的内核态,被动捕包的性能收到以下因素的影响。
内核态和用户态之间的内容拷贝,多线程调度,系统中断
互联网网络规模迅速扩张
高速网络应用开发的需求
什么是DPDK
基于linux运行,是一个快速处理数据包的函数库和驱动集合。
在用户态实现数据包的收发和处理,绕过了kernel协议栈对数据包的处理过程,也就是kernel bypass。
DPDK关键技术
传统技术缺点:
硬件中断导致的线程/进程切换
内存拷贝
多处理器平台的CPU漂移
缓存失效
UIO技术
当然UIO现在也变成了linux的核心技术
UIO,即Userspace I/O内核驱动,它在Linux kernel的世界比较小众,主要服务于一些定制设备。UIO负责将中断和设备内存暴露给用户空间,然后再由UIO用户态驱动实现具体的业务。
UIO干了什么事:
在内核区域放置了一段代码,用来监听硬件中断轮询 内核空间驱动
在用户空间实现了读取硬件设备内存,甚至硬件寄存器等 用户空间驱动
当然这个轮询(PMD)是流量大的时候处理的。
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2023.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2024.png)
对于多核也有支持
cpu affinity机制,将进程放在指定的CPU上尽量长地运行而不迁移到其他处理器,避免cpu cache missing,也减少了进程和线程地上下文切换,从而提高性能和效率。
使用NUMA亲和,避免CPU跨NUMA访问内存。CPU访问自己的物理地址(cache),有较短的响应时间,俗称Local Access,如果要访问其他CPU attach的内存,就需要通过inter-connect通道来访问,要慢一些,俗称Remote Access,在DPDK中,可以灵活地使用Local Access和Remote Access来提高访问速度。
大页表技术
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2025.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2026.png)
内存池技术
DPDK在用户空间实现了一套精致的内存池拷贝技术,内核空间和用户空间的内存交互不需要进行拷贝,只做控制权转移,这样就减少了内存拷贝的开销。
大页内存管理
兼容上层API申请大内存(
无锁环境队列
PMD技术
无中断开销
EBPF/XDP和DPDK的区别
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2027.png)
![Untitled](./images/%E7%BD%91%E7%BB%9C%E4%BF%A1%E6%81%AF%E8%8E%B7%E5%8F%96%E4%B9%8B%E8%A2%AB%E5%8A%A8%E8%8E%B7%E5%8F%96%20346be0c29ec34ad8bc9bbc1dd7589f1b/Untitled%2028.png)