Wireshark 是网络包分析工具。网络包分析工具的主要作用是尝试捕获网络包,并尝试显示包的尽可能详细的情况。本文初衷是为了以后解决实验室内网排查问题的,后变成了一篇实验和记录文章,我们将从 Wireshark 的安装开始记录,并进行一些常用的抓包分析工作。
Wireshark 快速入门(labex.io)是一个在线体验网站,包含了 Linux 系统上 Wireshark 的安装和使用。
具体的安装过程可以参考后面给出的网站,主要知道 Wireshark 如何开始抓包,以及抓包前和抓包后的过滤规则怎么设置就行。
进入 Nmap 官网安装 Namp 后,可在 Windows 上使用 netcat 工具。
在有些场景下,其实不存在服务端和客户端的区别,只是被动监听和主动发送的区别,这种情况我们也表述为服务端和客户端,在此澄清。
实验主要在 Windows 系统上进行,部分实验需要另外的计算机配合。
UDP(User Datagram Protocol,用户数据报协议)是一种简单的、无连接的传输层协议,用于在网络中传输数据。与 TCP 不同,UDP 不提供可靠性、顺序性和流量控制,但它具有低延迟和高效的特点,适合对实时性要求较高的应用。
先开启抓包,再开放并监听 UDP 端口(服务端是 linux 系统自带 netcat):
bashnc -ul 12345
参数 -u
表示使用 UDP,-l
表示监听。
并在 Windows 上使用 netcat (没有可自行安装 Nmap 获取)作为客户端进行 UDP 连接,并发送消息:
bashncat -u xxx.xxx.xxx.237 12345
结束抓包,用 udp.port==12345
进行过滤,每个包对应一条消息,非常简单:
以下是客户端 xxx.xxx.xxx.40
发送的消息:
>ncat -u xxx.xxx.xxx.237 12345 hello world! hi! i'm acqua
以下是服务端 xxx.xxx.xxx.237
接收的消息
~# nc -ul 12345 hello world! hi! i'm acqua
使用 loopback 适配器
可以在本机的不同的终端上使用,一个作为服务端,一个作为客户端,ip 使用回环地址。但需要注意这时 Wireshark 需要使用 loopback 适配器,否则捕获不了网络包。
服务端没有打开接收端口会怎么样?
UDP 是无状态的且不保证交付,所以实际上服务端没有打开端口,网络包也能发出,也不会有如 TCP 那样的确认包。
服务端发送消息是确认目标 IP 的?
服务端能知道客户端 IP,是因为客户端发出的 UDP 报文本身就包含了源 IP 和源端口,内核会把这信息交给服务端应用程序。
服务端先发消息会怎么样?
服务端先发消息无法确定目标 IP 和端口,理论上无法发送。但神奇的是,客户端发送消息后,服务端会将之前那条无法发送的消息发送给客户端。这可能和 netcat 的实现有关,由 netcat 缓存着消息,待收到客户端 UDP 包确认目标 IP 和端口后一并发出。
TCP(Transmission Control Protocol,传输控制协议)是互联网协议套件中的核心协议之一,位于传输层。它提供了一种可靠的、面向连接的、基于字节流的数据传输服务。TCP 的主要特点是确保数据在传输过程中不丢失、不重复,并且按顺序到达。
TCP 包结构如下,图源来自小林 coding
相关信息
由于 TCP 涉及内容较多,拥塞控制、粘包拆包等内容并未放出。
先开启抓包,再开放并监听 TCP 端口(服务端是 linux 系统自带 netcat):
bashnc -lk 12345
参数 -k
代表持续监听,避免连接断开后停止监听。
然后在 Windows 上使用 netcat 作为客户端进行 TCP 连接:
bashncat -p 12340 xxx.xxx.xxx.237 12345
参数 -p
表示以指定端口为 TCP 源端口。
互相发送消息后,结束抓包,用 tcp.port == 12345 || tcp.port==12340
进行过滤。然后右键数据包选择追踪流。
服务端没有在相应端口上进行监听时
三次握手、收发消息、超时断开
ACK=X+1
为对方 SEQ=X
值再加 1,意味着接收对方 SEQ=X
的包 ,同时意味着要求对方下一次传输 SEQ
应为 X+1
。hello from client
,长度为 19。服务端接收并返回 ACK=1+19=20
hello from server
,长度为 18。客户端接收并返回 ACK=1+18=19
四次挥手
SEQ
和 ACK
值是一样的。
SEQ
是不变的。SYN
或 FIN
,所以 ACK
是不变的。ACK
。超时重传
ACK
RST
包结束连接。ACK 与 SEQ 的关系?
由于背八股的时候基本只看三次握手和四次挥手,所以传输数据时是什么情况基本不了解,还以为和建立连接时一样是对方包的 SEQ
值加 1 就行。实则不然,ACK
号代表着期望下次发的字节序号,SEQ
表示包内第一个字节在字节流中的编号。上次发送的长度为 0 的话,这次的 SEQ
号就不变。当然如果涉及 SYN
或者 FIN
的话,也额外占一个序号。因此如上文解释的发送消息的情况,出现了 ACK=20
,是因为接收到了 19 个字节,所以期望下次发送字节编号为 1+19=20 的数据。
字符数一样,怎么一个长度 19 字节,一个长度 18?
Linux 和 Windows 系统的换行符不一样。0x0D = CR (Carriage Return, 回车),而 0x0A = LF (Line Feed, 换行)
系统 | 换行符组成 | 换行符十六进制码 |
---|---|---|
Windows / DOS | \r\n | 0D 0A |
Unix / Linux / macOS (现代) | \n | 0A |
老 macOS (pre-OSX) | \r | 0D |
主动断开连接之后想重新执行之前的命令,提示:通常每个套接字地址(协议/网络地址/端口)只允许使用一次
windows 上执行以下命令
cmdnetstat -aon|findstr "12340"
会显示
TCP 10.102.21.40:12340 117.72.95.237:12345 TIME_WAIT 0
说明上一次的连接还处于 TIME_WAIT
状态,至于为什么要在 TIME_WAIT
状态等一段时间,相信大家都明白的吧。
若要在 Linux 上排查,可使用:
bashss -tulnp | grep 12340
服务端发送消息是确认目标 IP 的?
情况与前述 UDP 是一样的,未建立连接无从知晓目标 IP。
服务端先发消息会怎么样?
与前述 UDP 实验一样,应当是 netcat 的机制。
cmdcurl --local-port 12340-12340 http://example.com/
cmdcurl --local-port 12340-12340 https://blog.zerolacqua.top/
ARP(Address Resolution Protocol,地址解析协议)是一种用于将网络层地址(如 IP 地址)解析为数据链路层地址(如 MAC 地址)的协议。ARP 在局域网(LAN)中广泛使用,帮助设备在通信时确定目标设备的物理地址。
获取电脑网卡的 IP 和 MAC:
cmdipconfig /all
查看 ARP 缓存表:
cmdarp -a
开启抓包,并清空 ARP 缓存:
cmdarp -d *
此时可以看到 ARP 请求与响应,网关等 IP 的解析会比较快。稍后结束抓包,使用获取的 MAC arp&ð.addr==XX-XX-XX-XX-XX-XX
进行过滤,结果如下。
设备 | IP | MAC |
---|---|---|
本机 | xxx.xxx.xxx.104 | xx-xx-xx-xx-xx-ef |
网关 | xxx.xxx.xxx.254 | xx-xx-xx-xx-xx-1f |
设备1 | xxx.xxx.xxx.14 | xx-xx-xx-xx-xx-9c |
另一次抓取的结果如下:
设备 | IP | MAC |
---|---|---|
本机 | xxx.xxx.xxx.104 | xx-xx-xx-xx-xx-ef |
网关 | xxx.xxx.xxx.254 | xx-xx-xx-xx-xx-1f |
网盘 | xxx.xxx.xxx.51 | xx-xx-xx-xx-xx-90 |
设备1 | xxx.xxx.xxx.14 | xx-xx-xx-xx-xx-9c |
可以看到,ARP 过程主要是两步:
ARP 请求不是广播的吗?为啥第一次抓取中 xxx.xxx.xxx.104
和 xxx.xxx.xxx.14
在互相单播?
可能是触发了 ARP 缓存确认机制。
第二次抓取中,两个 IP 地址怎么解析到同一个 MAC 地址?
可能的原因如下:
虚拟化宿主机:在一台物理服务器上,你可能会运行多个虚拟机。每个虚拟机都有自己的 IP 地址,但它们共享同一个物理网卡。
NAT(网络地址转换):如果你的路由器或电脑开启了 NAT 功能,内网中所有设备的私有 IP 地址(比如 192.168.x.x)在对外通信时,都会被转换成路由器唯一的公网 IP 地址。
负载均衡:在某些服务器集群中,多个后端服务器可能共享一个“虚拟”的 IP 地址。所有发往这个 IP 的请求都会被分发到不同的服务器上,但从网络物理层面看,它们可能都通过同一个设备进行通信。
ARP 代理:一种网络技术,由路由器或三层设备代替目标主机响应 ARP 请求,使请求方误以为目标在同一局域网内,实际通信数据先发往代理设备,再由其进行转发,从而实现跨子网通信或兼容不支持网关配置的设备。
对我们的实验而言,应该是 ARP 代理的原因导致网关在响应不同 IP 的 ARP 请求。
第二次抓取中,一个 IP 地址怎么解析出两个 MAC 地址?
这个可能是我测试的内网出现了问题。正常情况下,不应出现这种情况。不过 AI 提供了几种情景:
TUN/TAP 代理时 ARP 会怎么样
TUN 不是相当于虚拟网卡吗?那 ARP 的时候 MAC 会不同吗?TUN 虚拟网卡是点对点设备,没有 MAC 也不会包装以太网帧。TAP 模式是以太网设备,有 MAC 地址。根据我的理解,TUN 和 TAP 本质上是虚拟的网卡,实际发送用的还是物理网卡,使用物理网卡的 MAC(具体情况需要后续做实验研究)。
DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一种用于自动分配 IP 地址和其他网络配置信息(如子网掩码、默认网关、DNS 服务器)的协议。DHCP 简化了网络管理,允许设备在加入网络时自动获取必要的配置,而无需手动设置。
DHCP 是一个工作在 UDP 上的应用层协议。一般的工作流程可以参见 小林 Coding 中给出的示意图,分为 Discover、Offer、Request、Ack 四个阶段。
先开始抓包,然后通过 Windows 命令行执行以下命令释放 IP 并重新请求分配 IP:
CMDipconfig /release ipconfig /renew
然后结束抓包,用 bootp 或 dhcp 进行过滤,得到以下包
第一个包是 Release,用于释放 IP,后续四个包是请求分配 IP 过程中收发的包。我们只讨论后面的四个包。后面的四个包就是对应 Discover、Offer、Request、Ack 的四个阶段。其中 xxx.xxx.xxx.254
是 DHCP 服务器的 IP,xxx.xxx.xxx.134
是本机 IP(释放和请求)。
具体的 DHCP 中字段的格式与含义在此不表,可以在后文的参考文章中看到。
Offer、ACK 包中都有目标 IP 了,但是 DHCP 明明还没完成呢!
如果是广播会使用 255.255.255.255
,但这里是单播使用的是客户端可能的 IP,实际处理不是依赖这里的 IP 获取 MAC 的,通知客户端的分配的 IP 是在 DHCP 的负载里的
不是说好了 Offer 和 Ack 是广播(255.255.255.255
)吗?怎么变成单播了(xxx.xxx.xxx.134
的内网 IP)?
在 Discover 包中的 dhcp.flags
字段会告诉 DHCP 服务器使用单播还是广播。广播的问题在于会影响到广播域里其它所有主机。当主机收到广播报文时,网卡会产生一次硬件中断 CPU,CPU 会暂停手头的工作来处理这个中断,处理完中断,CPU 继续工作。IP 协议栈取走数据,检查之后和自己无关,丢弃。会造成资源的浪费。
在我们 Release 掉 IP 之后,DHCP 服务器怎么找到我们的 MAC 的?
不是通过 ARP 协议获取的,而是 Discover 包的 dhcp.hw.mac_addr
字段,由客户端给出的。
为什么重新申请之后又拿到了同样的 IP?
在 Discover 包中的 dhcp.option.requested_ip_address
字段包含了上一次获取到的 IP,如果这个 IP 没有被指派出去,那么依然会重新分配给这台客户端。
租约问题
另外,在 Offer 包的 dhcp.option
中有 ip_address_lease_time
、dhcp.option.renewal_time_value
、dhcp.option.rebinding_time_value
分别代表了租约时长和两个租约续期的时间点。(查看 DHCP 发现租约只有 8 小时,这么抠门?)
安装 Wireshark
查看 UDP 包
查看 TCP 包
查看 HTTP 包
查看 ARP 包
查看 DHCP 包
本文作者:Zerol Acqua
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!