新版nDPI开发自定义协议

1 篇文章 0 订阅

一、前言
最近因项目需要用到nDPI采集流量进行报文深度检测,主要在nDPI基础上进行协议扩展,根据官网用户手册描述有两种方式支持协议扩展,在此通过nDPI示例程序ndpiReader进行展示。
在ndpiReader中增加自定义协议的方式如下:
1、是通过编辑example/protos.txt文件来使ndpiReader匹配相应的协议,但是这种的匹配条件有限,只能通过端口、host和IP地址来定义新协议。
2、通过在源码中注册自定义协议以及自己编写自定义协议的匹配逻辑,来自定义协议。这种方法需要编码,但是协议自定义匹配方式更为灵活。

二、开发自定义协议
1、修改protos.txt
此种方法网上介绍的资料很多,在此省略。
2、修改源码
以下说明基于nDPI 最新版本3.4版本中的源码添加自定义协议。为了方便说明,假设我们需要自定义的协议名字叫做ONEONEPROTOCOL。顾名思义,当应用层协议中的数据全为1,那么就认为这是ONEONEPROTOCOL协议。
详细步骤如下:
1)添加新的协议ID
首先,每一个协议都必须在头文件ndpi_protocol_ids.h中有一个对应的协议ID的定义,ID号数字不能随便写,需要在现有的ID编号后新增。

 // Reddragon
  NDPI_PROTOCOL_ONEONEPROTOCOL        = 254, /* all of the tcp payload is 1*/

2)编写协议源文件
在定义完协议ID后,我们必须在src/lib/protocols/文件夹中创建自定义协议的源文件:oneoneprotocol.c。该文件用来识别协议格式。

#include "ndpi_protocol_ids.h"
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_ONEONEPROTOCOL
#include "ndpi_api.h"

void ndpi_search_oneoneprotocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
    struct ndpi_packet_struct *packet = &flow->packet;
    u_int nIndex = 0;
    u_int count = 0;
    u_int16_t dport = 0;
    
    NDPI_LOG_DBG(ndpi_struct, "search oneoneprotocol\n");
    printf("\n packet_len = %d\n", packet->payload_packet_len);
    
    while(nIndex < packet->payload_packet_len) {
        printf("\n nIndex = %d, payloadValue = %d \n", nIndex, packet->payload[nIndex]);
        if (packet->payload[nIndex] == 0x31){
            count++;
        }
        nIndex++;
    }

    if(count == packet->payload_packet_len){
        printf("\n count = %d, found oneoneprotocol \n", count);
        NDPI_LOG_INFO(ndpi_struct, "found oneoneprotocol\n");
        ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_ONEONEPROTOCOL, NDPI_PROTOCOL_UNKNOWN);
        return;
    }

    NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}

void init_oneoneprotocol_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id,
                             NDPI_PROTOCOL_BITMASK *detection_bitmask)
{
    ndpi_set_bitmask_protocol_detection(
        "oneoneprotocol", ndpi_struct, detection_bitmask, *id,
                                        NDPI_PROTOCOL_ONEONEPROTOCOL,
                                        ndpi_search_oneoneprotocol,
                                        NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITH_PAYLOAD,
                                        SAVE_DETECTION_BITMASK_AS_UNKNOWN,
                                        ADD_TO_DETECTION_BITMASK);
    *id += 1;
}

3)添加你的协议到nDPI
在ndpi_main.c中注册,依葫芦画瓢在1508行后面添加ndpi_set_proto_defaults函数。

        // oneoneprotocol
  ndpi_set_proto_defaults(ndpi_str, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ONEONEPROTOCOL, 1 /* no subprotocol */,
        no_master,
        no_master, "ONEONEPROTOCOL", NDPI_PROTOCOL_CATEGORY_CHAT,
        ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
        ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);

通过适当的宏并将他们设置到检测模块中来启用协议。在ndpi_set_protocol_detection_bitmask2函数3362行后面添加我们的函数:init_oneoneprotocol_dissector(ndpi_str, &a, detection_bitmask)。

  // ONEONEPROTOCOL
  init_oneoneprotocol_dissector(ndpi_str, &a, detection_bitmask);

4)完成
三、自测
在虚拟机linux上通过nc工具监听11011端口,windows通过NetAssist工具选择TCP Client连接到linux主机端口,发生数字111,ndpiReader抓包测试。测试结果如下图所示。
在这里插入图片描述

本文主要步骤参考如下链接,原文测试很多细节有误,特重新测试发布。详细介绍可参考原链接。
参考连接:
https://blog.csdn.net/ACMer_L/article/details/107594060

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据你提供的代码片段,可以看出你正在使用 `nDPI` 库对 `DPDK` 抓取的数据包进行协议识别,并将识别结果写入到新的 pcap 文件中。 在代码中,`$READER` 变量指向了一个文件路径,这个路径代表了 `nDPI` 库提供的用于读取和解析数据包的程序。 首先,脚本中的 `build_results` 函数遍历了指定目录中所有以 `.pcap` 扩展名结尾的文件(通过 `PCAPS` 变量保存文件名列表),并使用 `$READER` 执行命令对每个 pcap 文件进行处理。 命令 `$READER -q -i pcap/$f -w result/$f.out` 的含义如下: - `-q` 参数表示以静默模式运行,即不输出额外的信息。 - `-i pcap/$f` 参数指定要读取的 pcap 文件路径。 - `-w result/$f.out` 参数指定要写入的结果文件路径。 这个命令的作用是将输入的 pcap 文件通过 nDPI 库进行解析,并将识别结果写入到 `result/$f.out` 文件中。 接下来,`check_results` 函数对已经生成的结果文件进行检查。它使用相似的逻辑遍历 `PCAPS` 列表中的每个 pcap 文件: - 首先,检查对应的结果文件是否存在。 - 如果结果文件存在,首先执行命令 `$READER -q -i pcap/$f -w /tmp/reader.out`,将输入文件通过 nDPI 库处理,并将结果写入到临时文件 `/tmp/reader.out` 中。 - 接着,使用 `diff` 命令比较结果文件和临时文件的差异,使用 `wc -l` 命令统计差异行数,并将结果存储在 `NUM_DIFF` 变量中。 - 如果差异行数为 0,则打印 `"$f OK"` 表示结果一致。 - 否则,打印 `"$f ERROR"` 表示结果不一致,并打印执行的命令和差异的内容。 - 最后,删除临时文件 `/tmp/reader.out`。 整个脚本的目的是使用 `nDPI` 库对抓取的数据包进行协议识别,生成对应的结果文件,并在检查阶段验证识别结果是否正确。如果识别结果与期望结果不一致,则输出错误信息,并将退出状态码设为 1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值