当前位置: 首页 > news >正文

C语言实现TcpDump

一、

在 C 语言中实现 TCP 抓包功能,通常可以使用 libpcap 库。libpcap 是一个广泛使用的网络抓包库,它提供了捕获网络数据包的接口。
libpcap 是一个广泛使用的 C 语言库,用于捕获和过滤网络数据包。它提供了一个通用接口,用于访问数据链路层的协议,使用户能够在各种平台上实现网络流量捕获功能。

二、准备

安装 libpcap:在 Linux 系统中,可以使用以下命令安装

sudo apt-get install libpcap-dev

或者
下载、编译源码

git clone https://github.com/the-tcpdump-group/libpcap

可以查看官方文档

https://www.tcpdump.org/

三、代码

#include <stdio.h>
#include <stdlib.h>
#include <pcap/pcap.h>//头文件包含

#define SNAP_LEN 65535
#define PROMISC  1
#define TIMEOUT  1000             // ms
#define BUFSIZE  4 * 1024 * 1024  // 4MB

typedef struct {
    pcap_dumper_t *dumper;  // 用于保存数据包的句柄
    time_t start_time;       // 记录当前文件的起始时间
    long written_bytes;      // 当前文件已写入的字节数
    int file_index;          // 文件索引,用于防止同一秒生成两个文件
} capture_context_t;

void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
    capture_context_t *ctx = (capture_context_t *)user;
    time_t now = time(NULL);
    long packet_size = h->caplen;

    // 更新写入字节数
    ctx->written_bytes += packet_size;

    // 计算是否需要切换文件
    if (difftime(now, ctx->start_time) >= MAX_DURATION_SEC ||
        ctx->written_bytes >= MAX_FILE_SIZE) {

        // 关闭旧文件
        pcap_dump_close(ctx->dumper);

        // 打开新文件
        char filename[256];
        ctx->file_index += 1;
        generate_filename(filename, sizeof(filename), ctx->file_index);
        ctx->dumper = pcap_dump_open(ctx->handle, filename);
        ctx->start_time = now;
        ctx->written_bytes = 0;

        printf("🆕 Switched to new file: %s\n", filename);
    }

    // 写入当前包
    pcap_dump((u_char *)ctx->dumper, h, bytes);
}

int main() {
    char errbuf[PCAP_ERRBUF_SIZE];//错误打印的
    pcap_t *handle;
    pcap_dumper_t *dumper;
    struct bpf_program fp;
    bpf_u_int32 net = 0, mask = 0;

	//查找当前系统中一个默认的抓包网络设备名,需要确认是否有权限
    const char *dev = pcap_lookupdev(errbuf);
    if (!dev) {
        fprintf(stderr, "Device not found: %s\n", errbuf);
        return 1;
    }

    const char *filter_exp = "tcp port 80"; // 设置过滤器的规则,可以换成 "udp", "ip", "host 192.168.1.1", 等等
    const char *outfile = "output.pcap";    // 输出文件

    printf("Using device: %s\n", dev);

	// 获取网络地址 & 掩码(用于过滤器编译)
    if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
        fprintf(stderr, " Could not get netmask for %s: %s\n", dev, errbuf);
        net = 0;
        mask = 0;
    }

	//创建并配置抓包句柄
    handle = pcap_create(dev, errbuf);
    if (!handle) {
        fprintf(stderr, " pcap_create failed: %s\n", errbuf);
        return 1;
    }

	//设置抓包长度
    pcap_set_snaplen(handle, SNAP_LEN);
    //混杂模式,当网络接口处于混杂模式时,它会接收所有经过的数据包,而不仅仅是发送给它的包。
    pcap_set_promisc(handle, PROMISC);
    //设置捕获数据包的超时时间,以毫秒为单位,表示在没有接收到数据包的情况下,等待的最长时间
    pcap_set_timeout(handle, TIMEOUT);
    //设置缓冲区大小,增大缓冲区可以提高捕获性能,尤其是在高流量环境中,可以防止数据包丢失。
    pcap_set_buffer_size(handle, BUFSIZE);

	//激活刚刚设置的参数
    if (pcap_activate(handle) != 0) {
        fprintf(stderr, " pcap_activate failed: %s\n", pcap_geterr(handle));
        return 1;
    }

	//编译 BPF(Berkeley Packet Filter)过滤器表达式,将过滤规则转化为库格式
    if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
        fprintf(stderr, " Couldn't parse filter: %s\n", pcap_geterr(handle));
        return 1;
    }

	//应用过滤规则
    if (pcap_setfilter(handle, &fp) == -1) {
        fprintf(stderr, " Couldn't install filter: %s\n", pcap_geterr(handle));
        return 1;
    }

    // 打开输出文件
    dumper = pcap_dump_open(handle, outfile);
    if (!dumper) {
        fprintf(stderr, " Couldn't open dump file: %s\n", pcap_geterr(handle));
        return 1;
    }

    capture_context_t ctx = { .dumper = dumper };

    printf(" Saving packets to: %s\n", outfile);
    //抓多少包,抓到的包怎么处理packet_handler
    pcap_loop(handle, 10, packet_handler, (u_char *)&ctx); // 抓 10 个包
 
    // 清理资源
    pcap_dump_close(dumper);
    pcap_freecode(&fp);
    pcap_close(handle);

    printf(" Capture complete. Output saved to: %s\n", outfile);
    return 0;
}

相关文章:

  • MATLAB在工程领域的实际应用案例
  • 【 antd 】Form表单组件,“change“ 不生效
  • RK3588芯片NPU的使用:Windows11 Docker中运行PPOCRv4例子
  • 人工智能100问☞第1问:人工智能(AI)的定义是什么?
  • [D1,2]回溯刷题
  • python面试技巧
  • Android 应用蓝牙连接通信实现
  • 巧*书重大更新!商务标智能编写,标书一次成型!
  • 函数式编程在 Java:Function、BiFunction、UnaryOperator 你真的会用?
  • 研发效能实践:BDD(行为驱动开发)深度解毒手册:从「撕逼大会」到「人见人爱」的协作秘笈
  • chrome提示https不安全, 不能记住账号密码怎么办? 可以利用js输入账号
  • SQL:DML的基本语法
  • android wifi通过命令行打开2.4G热点
  • 网络安全·第二天·ARP协议安全分析
  • 从代码学习深度学习 - 注意力汇聚:注意力评分函数(加性和点积注意力) PyTorch 版
  • SQL问题分析与诊断(8)——其他工具和技术
  • ECMAScript 7~10 新特性
  • RLAgent note
  • 数据结构与算法-动态规划-线性动态规划,0-1背包,多重背包,完全背包,有依赖的背包,分组背包,背包计数,背包路径
  • 取消echarts地图悬浮时默认黄色高亮
  • 郑州付费系统网站开发建设/单页网站制作教程
  • 外国炫酷网站设计/个人推广网站
  • 长沙百姓网招聘信息/seowhy教研室
  • 郑州关键词seo/搜索引擎seo关键词优化
  • dw做的网站如何上传/整站关键词排名优化
  • 基于.net平台网站内容管理系统研究与实现/深圳营销策划公司十强