TCP 全连接队列与 tcpdump 抓包

news/2024/10/20 11:42:59/

TCP 相关实验

理解 listen 的第二个参数

  • 基于刚才封装的 TcpSocket 实现以下测试代码
  • 对于服务器, listen 的第二个参数设置为 1, 并且不调用 accept

test_server.cc

C
#include "tcp_socket.hpp"
int main(int argc, char* argv[]) {if (argc != 3) {printf("Usage ./test_server [ip] [port]\n");return 1;}TcpSocket sock;bool ret = sock.Bind(argv[1], atoi(argv[2]));if (!ret) {return 1;}ret = sock.Listen(2);if (!ret) {return 1;}// 客户端不进行 acceptwhile (1) {sleep(1);}return 0;
}

test_client.cc

C
#include "tcp_socket.hpp"
int main(int argc, char* argv[]) {if (argc != 3) {printf("Usage ./test_client [ip] [port]\n");return 1;}TcpSocket sock;bool ret = sock.Connect(argv[1], atoi(argv[2]));if (ret) {printf("connect ok\n");} else {printf("connect failed\n");}while (1) {sleep(1);}return 0;
}

此时启动 3 个客户端同时连接服务器, 用 netstat 查看服务器状态, 一切正常. 但是启动第四个客户端时, 发现服务器对于第四个连接的状态存在问题了。

tcp         3         0 0.0.0.0:9090         0.0.0.0:*
LISTEN         9084/./test_server
tcp         0         0 127.0.0.1:9090       127.0.0.1:48178
SYN_RECV     -
tcp         0         0 127.0.0.1:9090       127.0.0.1:48176
ESTABLISHED  -
tcp         0         0 127.0.0.1:48178      127.0.0.1:9090
ESTABLISHED 9140/./test_client
tcp         0         0 127.0.0.1:48174      127.0.0.1:9090
ESTABLISHED 9087/./test_client
tcp         0         0 127.0.0.1:48176      127.0.0.1:9090
ESTABLISHED 9088/./test_client
tcp         0         0 127.0.0.1:48172      127.0.0.1:9090
ESTABLISHED 9086/./test_client
tcp         0         0 127.0.0.1:9090       127.0.0.1:48174
ESTABLISHED  -
tcp         0         0 127.0.0.1:9090       127.0.0.1:48172
ESTABLISHED  -

客户端状态正常, 但是服务器端出现了 SYN_RECV 状态, 而不是 ESTABLISHED 状态 这是因为, Linux 内核协议栈为一个 tcp 连接管理使用两个队列:

  1. 半链接队列(用来保存处于 SYN_SENT 和 SYN_RECV 状态的请求)
  2. 全连接队列(accpetd 队列)(用来保存处于 established 状态,但是应用层没有 调用 accept 取走的请求)

而全连接队列的长度会受到 listen 第二个参数的影响。

全连接队列满了的时候, 就无法继续让当前连接的状态进入 established 状态了。

这个队列的长度通过上述实验可知, 是 listen 的第二个参数 + 1。

使用 TCP dump 进行抓包,分析 TCP 过程

TCPDump 是一款强大的网络分析工具,主要用于捕获和分析网络上传输的数据包。

安装 tcpdump

tcpdump 通常已经预装在大多数 Linux 发行版中。如果没有安装,可以使用包管理器 进行安装。例如 Ubuntu,可以使用以下命令安装:

Bash
sudo apt-get update
sudo apt-get install tcpdump

在 Red Hat 或 CentOS 系统中,可以使用以下命令:

Bash
sudo yum install tcpdump

常见使用

 1. 捕获所有网络接口上的 TCP 报文

Bash
$ sudo tcpdump -i any tcp

注意:-i any 指定捕获所有网络接口上的数据包,tcp 指定捕获 TCP 协议的数据 包。i 可以理解成为 interface 的意思

 

2. 捕获指定网络接口上的 TCP 报文

如果你只想捕获某个特定网络接口(如 eth0)上的 TCP 报文,可以使用以下命令:

Bash
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.18.45.153 netmask 255.255.192.0 broadcast
172.18.63.255inet6 fe80::216:3eff:fe03:959b prefixlen 64 scopeid
0x20<link>ether 00:16:3e:03:95:9b txqueuelen 1000 (Ethernet)RX packets 34367847 bytes 9360264363 (9.3 GB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 34274797 bytes 6954263329 (6.9 GB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0$ sudo tcpdump -i eth0 tcp

 

3. 捕获特定源或目的 IP 地址的 TCP 报文

使用 host 关键字可以指定源或目的 IP 地址。例如,要捕获源 IP 地址为 192.168.1.100 的 TCP 报文,可以使用以下命令:

Bash
$ sudo tcpdump src host 192.168.1.100 and tcp

要捕获目的 IP 地址为 192.168.1.200 的 TCP 报文,可以使用以下命令:

Bash
$ sudo tcpdump dst host 192.168.1.200 and tcp

同时指定源和目的 IP 地址,可以使用 and 关键字连接两个条件:

Bash
$ sudo tcpdump src host 192.168.1.100 and dst host 192.168.1.200 and tcp

 4. 捕获特定端口的 TCP 报文

使用 port 关键字可以指定端口号。例如,要捕获端口号为 80 的 TCP 报文(通常是HTTP 请求),可以使用以下命令:

Bash
$ sudo tcpdump port 80 and tcp

 5. 保存捕获的数据包到文件

使用 -w 选项可以将捕获的数据包保存到文件中,以便后续分析。例如:

Bash
$ sudo tcpdump -i eth0 port 80 -w data.pcap

这将把捕获到的 HTTP 流量保存到名为 data.pcap 的文件中。

  • 了解:pcap 后缀的文件通常与 PCAP(Packet Capture)文件格式相关,这是一 种用于捕获网络数据包的文件格式。

 6. 从文件中读取数据包进行分析

使用 -r 选项可以从文件中读取数据包进行分析。例如:
 

Bash
tcpdump -r data.pcap

这将读取 data.pcap 文件中的数据包并进行分析。

注意事项

  • 使用 tcpdump 时,请确保你有足够的权限来捕获网络接口上的数据包。通常,你 需要以 root 用户身份运行 tcpdump
  • 使用 tcpdump 的时候,有些主机名会被云服务器解释成为随机的主机名,如果不 想要,就用-n 选项。
  • 主机观察三次握手的第三次握手,不占序号。

使用 wireshark 分析 TCP 通信流程

wireshark 是 windows 下的一个网络抓包工具. 虽然 Linux 命令行中有 tcpdump 工具 同样能完成抓包, 但是 tcpdump 是纯命令行界面, 使用起来不如 wireshark 方便

下载 wireshark

https://1.na.dl.wireshark.org/win64/Wireshark-win64-2.6.3.exe

安装 wireshark

直接双击安装, 没啥太多注意的.

启用 telnet 客户端

参考 https://jingyan.baidu.com/article/95c9d20d96ba4aec4f756154.html

启动 wireshark 并设置过滤器

由于机器上的网络数据报可能较多, 只需要关注需要的. 因此需要设置过滤器 在过滤器栏中写入。

ip.addr == [服务器 ip]

则只抓取指定 ip 的数据包

或者在过滤器中写入

tcp.port == 9090

则只关注 9090 端口的数据

更多过滤器的设置, 参考

https://blog.csdn.net/donot_worry_be_happy/article/details/80786241

观察三次握手过程

启动好服务器

使用 telnet 作为客户端连接上服务器

telnet [ip] [port]

观察三个报文各自的序列号和确认序号的规律. 在

中间部分可以看到 TCP 报文详细信息:

观察确认应答 

在 telnet 中输入一个字符

可以看到客户端发送一个长度为 1 字节的数据, 此时服务器返回了一个 ACK 以及一个 9 个字节的响应(捎带应答), 然后客户端再反馈一个 ACK(注意观察 序列号和确认序号)

观察四次挥手

在 telnet 中输入 ctrl + ], 回到 telnet 控制界面, 输入 quit 退出。

实际上是 "三次挥手", 由于捎带应答, 导致其中的两次重合在了一起。

注意事项

如果使用虚拟机部署服务器, 建议使用 "桥接网卡" 的方式连接网络. NAT 方式下由于进 行了 ip 和 port 的替换。

使用云服务器测试, 更加直观方便。


http://www.ppmy.cn/news/1540507.html

相关文章

Zookeeper面试整理-Zookeeper的特性

Zookeeper 具有一些关键的特性,这些特性使其成为分布式系统中非常可靠的协调服务工具。以下是 Zookeeper 的主要特性: 1. 顺序一致性(Sequential Consistency) Zookeeper 保证了所有客户端的操作是按照严格的顺序执行的。每个客户端在对 ZNode 进行操作时,会看到与其他客户…

R语言医学数据分析实践-高级回归分析

【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言编程_夏天又到了的博客-CSDN博客 R编程环境的搭建-CSDN博客 上一节介绍了简单线性回归分析&#…

RHCE【远程连接服务器】

目录 一、远程连接服务器简介 二、加密技术简介 SSH工作过程&#xff1a; &#xff08;1&#xff09;版本协商阶段 &#xff08;2&#xff09;密钥和算法协商阶段 &#xff08;3&#xff09;认证阶段 &#xff08;4&#xff09;会话请求阶段 &#xff08;5&#xff0…

Spring Boot里的响应式和Vue里的响应式

Spring Boot 3中的响应式和Vue 3的响应式虽然都涉及到了“响应式”这一概念&#xff0c;但它们在实现和应用场景上存在显著的差异。 Spring Boot 3的响应式 定义与实现&#xff1a; 在Spring Boot 3中&#xff0c;响应式编程主要通过Spring WebFlux和Spring Data R2DBC等组件来…

NSSCTF-WEB-easy_eval

目录 前言 正文 思路 序列化构造 后渗透 思路点1:Redis 思路2:蚁剑插件绕过disable_functinons 结尾 作者的其他文章 前言 说是easy,实际很difficult 正文 思路 <?php class A{public $code "";function __call($method,$args){//最后执行命令eval($th…

系统托盘图标+快捷启动(Python)

QkStart 我把这个程序命名为QkStart 代码 # -*- coding: utf-8 -*- # Environment PyCharm # File_name QkStart |User Pfolg # 2024/10/19 22:06 import threading import time import pystray from PIL import Image from pystray import MenuItem, Menu import o…

fread和imread不同(imread读取的是图像的像素矩阵,fread会有别的信息)

clear;clc; fid fopen(草原HH极化图像.png,rb); B fread(fid,uint8); % % unit8是0——255&#xff0c;所以要保存图像&#xff0c;要先把矩阵归一化&#xff0c;然后再乘255 % height 1600; % width 2000; % img_matrix reshape(B(1:width*height), [height, width]); i…

C#中委托的应用与示例

委托 委托是指把事情托付给别人或别的机构办理。在C#语言中委托是一种特殊类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。委托是具有特定参数列表和返回类型的方法的引用的类型(不是引用对象,而是引用方法)。 可以委托将看作一个包含有序方法列表…