基于libnids的TCP数据流的还原(多线程实现)

 我们知道,libnids本身可以实现TCP数据流的重组,但是如果一个TCP流数据量比较大的时候,就会分成好多个TCP报文段,这些报文段在网络中的传播可能是乱序的,利用libnids可以帮助我们按顺序接收到这些报文段,即实现TCP报文段的重组。

    但是我们如何把这些顺序的报文段重新还原成一个完整的数据文件,也是要考虑的一个问题,因为在很多时候,单个的报文段对我们的意义不大,我们需要一个完整的数据,这样才有助于我们进一步分析网络中的数据内容。

    下面的程序实现了基于libnids的TCP数据流的还原,我使用了多线程来控制数据的处理,主要的数据结构是一个带头结点的双向链表队列,队列中的每个结点存储一个完整的TCP数据流的内容,另外还有两个元素,分别是指向前导和后续结点的结构体指针。结构体定义如下:

    struct buf{

        char *buffer;

        struct buf *prev;

        struct buf *next;

    };

    头结点:  struct buf *head;

    多线程对该链表的操作:

    向链表中放数据:void put_function(int size, char *data)

                    {

                          pthread_mutex_lock(&mutex);

                          meke_new_item(size, data);

                          buffer_has_item++;

                          pthread_mutex_unlock(&mutex);

                          sleep(1);

                    }

    mutex为互斥锁,size为data的大小,data为完整的数据流,buffer_has_item为当前链表中结点的数目。

    从链表中去数据的操作:(这是一个线程函数,在执行pthread_create是创建)

    void get_function(void)

    {

          while(1){

                  pthread_mutex_lock(&mutex);

                  if(buffer_has_item > 0){

                           consume_item();

                           buffer_has_item--;

                  }

                  pthread_mutex_unlock(&mutex);

                  sleep(1);

          }

    }

    创建新的节点并把它挂到队列当中:

    void make_new_item(int size, char *data)

    {

          struct buf *con;

          if(!(con = (struct buf *)malloc(sizeof(struct buf)))){

                 assert("con malloc fail!");

          }

          if(!(con->buffer = (char *)malloc(size*sizeof(char)))){

                  assert("con buffer malloc fail!");

          }

          memset(con->buffer, 0, size*sizeof(char));

          memcpy(con->buffer, data, size*sizeof(char));

          con->prev = NULL;

          con->next = NULL;

          if(head->next == NULL){

                head->next = con;

                head->prev = con;

                con->prev = head;

          }else{

                con->prev = head->prev;

                head->prev->next = con;

                head->prev = con;

                con->next = NULL;

          }

     }

     处理还原之后的数据:

     void consume_item()

     {

          int k;

          struct buf *p;

          if(head->next){

                

                 printf("%s", head->next->buffer);

                 p = head->next;

                 if(head->next->next){

                       head->next = head->next->next;

                       head->next->preb = head;

                 }else{

                        head->next = NULL;

                        head->prev = NULL;

                  }

                  if(p){

                        free(p);

                        p = NULL;

                   }

           }

     }

     链表初始化(可以把整个程序的初始化都放在这里进行):

     void init_dlink()

     {

           if(!(head = (struct buf *)malloc(sizeof(struct buf)))){

                     assert("head malloc fail!");

            }

            head->next = NULL;

            head->prev = NULL;

      }

      head的定义是一个全局变量,struct buf *head;

      在主函数当中,要创建线程,注册libnids回调函数:

      int main(int argc, char *argc[])

      {

            pthread_t thread;

            init_dlink();

            pthread_mutex_init(&mutex, NULL);

            if(!nids_init())P{

                  assert("nids init fail!");

            }

            pthread_create(&thread, NULL, (void *)get_function, NULL);

            nids_register_tcp(tcp_protocol_callback);

            nids_tun();

            return 0;

       }

       在回调函数当中,我们可以组织实现TCP数据流的还原,并把还原之后的数据添加到链表当中:

       void tcp_protocol_callback(struct tcp_stream *tcp_connection, void **arg)

       {

            switch(tcp_connection->nids_state){

                   .....................

                   case NIDS_DATA:{

                         ................

                         if(tcp_connection->client.count_new){

                               

                                ..............

                               

                                put_function(sum_len, content);

                         }

                   }

            }

        }

    至此,就完成了还原TCP数据流的多线程处理。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我会尽力回答您的问题。首先,Libnids是一个基于网络的入侵检测系统库,它可以用来监听网络流量并提取网络流量中的协议数据单元(PDU)。它包括一个用于解析 TCP/IP 流量的 TCP/IP 协议分析器和一个用于检测 TCP/IP 流量的入侵检测引擎。 基于Libnids库的入侵检测程序的设计与实现需要以下步骤: 1. 安装Libnids库和相关依赖。Libnids库是一个C语言库,可以从官方网站上下载和安装。 2. 编写C语言程序,调用Libnids库的API。在程序中,需要使用Libnids库提供的函数来进行协议分析和入侵检测。 3. 实现入侵检测引擎。可以使用Libnids库提供的协议分析器来解析TCP/IP流量,然后根据预定义的规则进行入侵检测。 4. 显示入侵检测结果。可以使用图形界面或命令行来显示入侵检测结果。 以下是一个简单的基于Libnids库的入侵检测程序的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <nids.h> /* 入侵检测回调函数 */ void tcp_callback(struct tcp_stream *tcp, void **arg) { /* 判断TCP流状态 */ if (tcp->nids_state == NIDS_JUST_EST) { printf("New TCP connection from %s:%d\n", inet_ntoa(*((struct in_addr *)&tcp->addr.saddr)), ntohs(tcp->addr.source)); } else if (tcp->nids_state == NIDS_CLOSE) { printf("TCP connection closed\n"); } /* 检测HTTP请求 */ if (tcp->nids_state == NIDS_DATA && tcp->server.count_new) { char *data = (char *)tcp->server.data; int len = tcp->server.count_new; /* 判断是否为HTTP请求 */ if (len > 4 && strncmp(data, "GET ", 4) == 0) { printf("HTTP GET request detected: %.*s\n", len, data); } } } int main(int argc, char **argv) { /* 初始化Libnids库 */ if (!nids_init()) { printf("Libnids initialization failed\n"); exit(1); } /* 设置TCP回调函数 */ nids_register_tcp(tcp_callback, NULL); /* 开始监听网络流量 */ nids_run(); return 0; } ``` 在这个示例程序中,我们使用Libnids库中的nids_init()函数来初始化Libnids库,并使用nids_register_tcp()函数来注册TCP回调函数。回调函数tcp_callback()会在每个TCP连接状态变化时被调用,我们可以在回调函数中编写入侵检测的代码。在这个示例程序中,我们检测HTTP请求,如果检测到HTTP GET请求,就会打印出请求的内容。 当程序运行时,它会监听网络流量,并在检测到HTTP GET请求时打印出请求的内容。您可以根据自己的需要修改回调函数tcp_callback()来实现更复杂的入侵检测功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值