`
shaojiashuai123456
  • 浏览: 262165 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
社区版块
存档分类
最新评论
阅读更多

Libnids-API(中文版)
====================
libnids-1.16
====================


1. 简介
2. IP碎片重组
3. TCP流还原
4. 例子程序
5. 基本的Libnids结构和函数
6. 其它有用的技巧


1. 简介

Libnids定义的数据结构和函数的声明集中在头文件nids.h中。使用Libnids的应用程序
必须包含这个文件,并且要与Libnids.a静态库进行连接。


应用程序的Main函数一般是这样的形式:
main()
{
应用程序的私有处理,与Libnids无关;
可选择的Libnids参数的修改;
if(!nids_init())那里出了问题,结束;
出测回调函数;
nids_run();
//正常情况下不可达;
}

另外的方法将在以后提及。

2.IP碎片重组

为了接收到Libnids看到的所有的IP包(包括分片的;带有无效校验和的IP包)程序员应该
定义一个如下类型的回调函数:

void ip_frag_func(struct ip * a_packet, int len)

在调用nids_init之后,这个函数应该使用Libnids进行注册:

nids_register_ip_frag(ip_frag_func);

函数ip_frag_func 将被Libnids调用;参数a_packet将指向一个收到的数据报,len是其长度。

类似的,为了接受到适当地数据包,这些包是要被目标主机接收的(就是,没有分片的包或者已经
完成重组的分片包;头部的正确性已经校验过),应该定义一个回调函数:

void ip_func(struct ip * a_packet)

并注册它:

nids_register_ip(ip_func);

3. TCP流的重组

为了接收到一个TCP流中交换的数据,必须定义一个回调函数:

void tcp_callback(struct tcp_stream * ns, void ** param)

tcp_stream结构包含了所有的关于一个TCP连接的信息,例如:它包含两个half_stream(名为
client和server)结构类型的域,每一个描述了一侧的连接,我们将在后面解释所有的域。

tcp_stream的一个域的名字为nids_state,tcp_callback的行为依赖于这个域的值。

* ns->nids_state==NIDS_JUST_EST

这里,ns描述了一个已经建立的连接。Tcp_callback必须判断当将来这个连接中
的数据到达的时候,它是否希望被通知。所有的连接参数都是可用的(ip地址,端
口号等等)。如果这个连接是我们感兴趣的,tcp_callback函数通知Libnids它希
望接收什么数据(发到客户端的数据;发到服务器的数据;发到客户端的紧急数据;
发到服务器的紧急数据),然后函数返回。


* ns->nids_state==NIDS_DATA

这里,新的数据已经到达,half_stream结构(tcp_stream结构的成员)包含数据
缓冲区。

* nids_state域的其它值(NIDS_CLOSE, NIDS_RESET,NIDS_TIMEOUT)意味着连接
已经被关闭。Tcp_callback应给释放其所分配的资源,即使它需要。

4. 例子程序

现在,让我们看看一个简单的例子程序,这个程序在stderr中显示Libnids所监视到的所
有TCP连接所交换的数据。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include "nids.h"

#define int_ntoa(x) inet_ntoa(*((struct in_addr *)&x))

// struct tuple4 包含TCP连接的地址和端口号
// 下面的辅助函数生成一个类似10.0.0.1,1024,10.0.0.2,23的字符串

char *
adres (struct tuple4 addr)
{
static char buf[256];
strcpy (buf, int_ntoa (addr.saddr));
sprintf (buf + strlen (buf), ",%i,", addr.source);
strcat (buf, int_ntoa (addr.daddr));
sprintf (buf + strlen (buf), ",%i", addr.dest);
return buf;
}

void
tcp_callback (struct tcp_stream *a_tcp, void ** this_time_not_needed)
{
char buf[1024];
strcpy (buf, adres (a_tcp->addr)); // we put conn params into buf
if (a_tcp->nids_state == NIDS_JUST_EST)
{
// 由a_tcp描述的连接已经建立
// 这里我们决定是否希望跟踪这个流
// 例子条件: if (a_tcp->addr.dest!=23) return;
// 在本程序中我们跟踪所有的流所以。。。。。:
a_tcp->client.collect++; // 我们需要客户端接收到的数据.......
a_tcp->server.collect++; // 我们需要服务器接收到的数据.......
a_tcp->server.collect_urg++; // 我们需要服务器接收到的紧急数据.......

#ifdef WE_WANT_URGENT_DATA_RECEIVED_BY_A_CLIENT

a_tcp->client.collect_urg++; // 如果我们不增加这个值,当紧急数据到达
//时我们不会被通知。
#endif
fprintf (stderr, "%s establishedn", buf);
return;
}
if (a_tcp->nids_state == NIDS_CLOSE)
{
// 连接已经正常结束
fprintf (stderr, "%s closingn", buf);
return;
}
if (a_tcp->nids_state == NIDS_RESET)
{
// 连接已经通过RST关闭。
fprintf (stderr, "%s resetn", buf);
return;
}

if (a_tcp->nids_state == NIDS_DATA)
{
// 新的数据已经到达,必须判断其数据流向
// 判断其是否紧急数据

struct half_stream *hlf;

if (a_tcp->server.count_new_urg)
{
// 紧急数据的新字节已经到达
strcat(buf,"(urgent-&gt;)");
buf[strlen(buf)+1]=0;
buf[strlen(buf)]=a_tcp->server.urgdata;
write(1,buf,strlen(buf));
return;
}
// 我们不必必须检查是否客户端的紧急数据已经到达
// 因为我们没有增加a_tcp-&gt;client.collect_urg的值
// 因此,我们还有一些正常的数据关心

if (a_tcp->client.count_new)
{
//客户端的新数据
hlf = &a_tcp->client; // 现在我们将处理hlf变量
// 这个变量指向客户端一边的连接。
strcat (buf, "(&lt;-)"); // 数据的符号方向
}
else
{
hlf = &a_tcp-&gt;server; // 类似的
strcat (buf, "(-&gt;)");
}
fprintf(stderr,"%s",buf); // 我们打印连接参数(saddr, daddr, sport, dport)
// 和数据流向(-&gt; or &lt;-)

write(2,hlf-&gt;data,hlf-&gt;count_new); // 我们打印最新到达的数据

}
return ;
}

int
main ()
{
// 这里我们可以改变Libnids的params,例如 nids_params.n_hosts=256;
if (!nids_init ())
{
fprintf(stderr,"%sn",nids_errbuf);
exit(1);
}
nids_register_tcp (tcp_callback);
nids_run ();
return 0;
}

5. 基本的Libnids结构和函数

现在是时候仔细描述一些提到的Libnids的结构的时候了,它们在头文件nids.h中声明。

struct tuple4 // TCP连接参数
{
unsigned short source,dest; // 客户端和服务器端口号
unsigned long saddr,daddr; // 客户端和服务器IP地址
};


struct half_stream // TCP连接一侧的描述结构
{
char state; // socket 状态 (例如:TCP_ESTABLISHED )

char collect; // if &gt;0, 那么数据应该被存放到data缓冲区中。否则,
// 这个方向的数据流将被忽略
// 看一下samples/sniff.c文件如何使用这个域

char collect_urg; // 类似的,判断是否为紧急数据。

char * data; // 正常数据缓冲区

unsigned char urgdata; // one-byte buffer for urgent data

int count; // 自连接建立以来已经有多少字节已经发送到data缓冲区中

int offset; // offset (in data stream) of first byte stored in
// the "data" buffer; additional explanations
// follow

int count_new; // 多少字节将被发送到data缓冲区中last (this) time;
// if == 0, 没有新数据到达。

char count_new_urg; // if != 0,新的紧急数据到达

... // other fields are auxiliary for libnids

};


struct tcp_stream
{
struct tuple4 addr; // 连接参数(saddr, daddr, sport, dport)
char nids_state; // 连接的逻辑状态
struct half_stream client,server; // 描述连接的客户端和服务器端的结构
... // other fields are auxiliary for libnids
};

在上面的例子程序中,函数tcp_callback打印hlf-&gt;data缓冲区的数据到stderr上,
并且这些数据不再需要了。在tcp_callback返回后,默认情况下Libnids释放这些数
据占用的空间。hlf-&gt;offset域将增加丢弃的字节数,并接新的数据将存储到data缓冲区
的开始。如果上面的操作不是我们所希望的,(例如,数据处理器需要至少N字节的输入来
处理,并且迄今为止Libnids接受到的count_new&lt;N字节)应该调用程序:

void nids_discard(struct tcp_stream * a_tcp, int num_bytes)

在tcp_callback返回前。结果,在tcp_callback返回后,Libnids将丢弃data缓冲区中至
多num_bytes字节的前面的内容(更新offset域,移动剩下的数据到data缓冲区的开始位置)。
如果nids_discard函数没有被调用(像上面的例子程序),缓冲区hlf-&gt;data包含
hlf-&gt;count_new字节的内容。一般情况下,缓冲区hlf-&gt;data中的字节数等于
hlf-&gt;count-hlf-&gt;offset.

感谢函数nids_discard,程序员不得不必须把接受到的数据拷贝到一个独立的缓冲区中。
hlf-&gt;data将一直包含尽可能多的数据。可是,经常发生对每一个ibnids_callback, tcp
stream对维护其辅助数据结构的请求。例如,如果我们希望检测一个针对wu-ftpd的攻击(这个
攻击包括在服务器上建立深层目录)我们需要将Ftpd守护进程的目录存储到某一个地方。
通过Ftp客户端的CWD指令怾改变。这就是tcp_callback的第二个参数的目的。它是一个指向
每一个(libnids_callback, tcp stream)对所私有的数据的指针。

典型情况如下:

void
tcp_callback_2 (struct tcp_stream * a_tcp, struct conn_param **ptr)
{
if (a_tcp-&gt;nids_state==NIDS_JUST_EST)
{
struct conn_param * a_conn;
如果连接是我们不感兴趣的,返回;
a_conn=malloc of some data structure//内存分配
init of a_conn//初始化
*ptr=a_conn // 这个值在将来的调用中将被传递给tcp_callback_2
增加一些 "collect" 域
return;
}
if (a_tcp-&gt;nids_state==NIDS_DATA)
{
struct conn_param *current_conn_param=*ptr;
using current_conn_param and the newly received data from the net
we search for attack signatures, possibly modyfying
current_conn_param
return ;

}

函数nids_register_tcp 和 nids_register_ip*可以被调用任意多的次数。两个与
tcp_callback相似的函数允许跟踪同一个TCP流。(with acertain non-default exception).

Libnids参数可以通过全局变量nids_params的域的改变来修改。如下声明:
struct nids_prm
{
int n_tcp_streams; // 用于存储tcp_stream结构信息的Hash表的大小
// libnis将只能同时跟踪 3/4 * n_tcp_streams连接的数据流
// 默认值:1040
// 如果设置为0,Libnids将不再进行TCP流的组装
int n_hosts; // 用于存储关于IP碎片重组的信息的Hash表的大小
// 默认值: 256
char * device; // Libnids用于监听数据包的设备接口
// 默认值 :NULL, 将通过调用pcap_lookupdev函数来接决定;
// 特殊值all将致使Libnids试图通过所有的设备接口截获数据包
// (这个参数在高于2.2.0Linux 核心版本有效)
// 参见 doc/NEW_LIBPCAP
int sk_buff_size; // 结构sk_buff的大小,这个结构是由Linux核心定义的,核心用于
// 数据包排列,如果这个参数和sizeof(struct sk_buff)地值不同,
// Libnids可以通过攻击其资源管理而被绕过。见TEST文件。
// 如果你是一个喜欢妄想的人,那么检查你网络中主机的sizeof(sk_buff)
// 并调整这个参数,默认值:168
int dev_addon; // 在sk_buff结构中保留了多少字节用于存储网络接口信息;如果dev_addon==-1,
// 将在nids_init()中根据Libnids监听的接口的类型进行改正。it
// 默认值: -1.
void (*syslog)(); // 参见nids_params定义部分的描述
int syslog_level; // 如果 nids_params.syslog==nids_syslog,那么这个域将决定
// 系统守护进程syslogd报告事件所使用的等级loglevel.
// 默认值: LOG_ALERT
int scan_num_hosts;// 用于存储关于端口扫描的信息的Hash表的大小;Libndis能够检测
// 到的同时发生的端口扫描企图。如果设置为0,端口扫描检测将被关闭
// 默认值:256
int scan_num_ports;// 多少个TCP端口必须被同一个源地址扫描
// 默认值: 10
int scan_delay; // 两个端口之间最大的扫描间隔
// 用于使Libnids可以报告端口扫描企图
// 默认值:3000
void (*no_mem)(); // 当Libndis的内存资源耗尽时调用此函数
// 它应该终止当前进程
int (*ip_filter)(struct ip*); // 这个参数当IP数据包到达时才会被考虑
// 如果ip_filter返回non-zero, 处理这个包否则忽略掉
// 通过这种方式,可以只监控所选中的主机,而不是整个子网
// 默认函数: (nids_ip_filter) 一般返回值为:1
char *pcap_filter; // 用于pcap地过滤字符串,默认情况下为NULL。
// 需要了解的是这强应用到link-layer,所以象"tcp dst port 23"
// 一样的过滤器无法控制碎片传输。
int promisc; // 如果非零,Libnids读取数据包的设备将被设置为混杂模式
// 默认为:1
int one_loop_less; // 默认情况下不可用
} nids_params;

nids_params变量中的syslog域在默认情况下包含函数nids_syslog的地址,如下声明:

void nids_syslog (int type, int errnum, struct ip *iph, void *data);

函数nids_params.syslog用于报告一些不寻常的情形,例如端口扫描请求,无效TCP头
标记等等。这个域应该被分配通常的事件记录函数的地址。
函数nids_syslog(在libnids.c中定义)举例说明了如何解读传递给nids_params.syslog
的参数。
Nids_syslog记录信息道系统守护进程syslogd中。忽视像消息速率和可用磁盘空间之类的事情。

如果对UDP数据报感兴趣,应该声明:
void udp_callback(struct tuple4 * addr, char * buf, int len, struct ip
* iph);

并注册它:

nids_register_udp(udp_callback)

参数addr包含地址信息,buf指针指向UDP数据包携带的数据,len是数据长度,iph是包
含此UDP数据报的Ip包的指针。校验和已经进行过。

6. 其他有用的技巧

void nids_killtcp(struct tcp_stream * a_tcp)

通过发送RST结束一个a_tcp描述的TCP连接。


使用nids_run()存在一个不利的因素,应用程序变成了完全的包驱动,有时在没有包到达的
时候执行某些操作也是必须得。代替nids_run(),我们可以使用函数:

int nids_next()

这个函数调用 pcap_next() 而不是 pcap_loop, 就是说它之处理一个包,如果没有包可用,
程序将处于睡眠状态,Nids_next()成功时返回1;出错返回0。(nids_errbuf 包含相关联
的信息)

标准情况下,当时用nids_next()时,因各应用程序将睡眠在一个select()函数中,同时在fd_set
中引入了一个监听得socket fd. 这个fd可以通过下面的调用获得:

int nids_getfd()

它返回一个文件描述符,失败的时候返回-1。(nids_errbuf包含出错信息)。


头文件nids.h定义了常量 NIDS_MAJOR (1) 和NIDS_MINOR (16), 这些常量用于判定Libnids的
现行版本。如果HAVE_NEW_PCAP(同样在nids.h中定义) 设置为1,则Libnids已被编译为支持
通过所有设备截获数据包。(见 NEW_LIBPCAP 文件)


典型情况下,TCP流携带的数据可以被分成协议依赖(protocol-dependent)记录(say, lines of
input)。一个tcp_callback函数可以接收一定数量的数据,这些数据可以包含多余一个地记录。因此
tcp_callback函数应该对所有接受到的数据重复进行协议解析程序。这增加了代码的复杂性。

如果nids_params.one_loop_less是非零的,Libnids的行为会发生轻微的变化。如果一个callback
消耗了部分而不是全部的新到达的数据,Libnids立刻再次调用它。只有在缓冲区中不再有未处理的保
留数据,并且rcv-&gt;count_new相应减少。因而,callback能一次处理一个记录,Libnids将再次调用
它,知道没有新的数据剩余或者没有数据可以处理。不幸的,在两个以上的callback函数读取同一个
TCP流的一半的时候,这一行为导致了可怕的语法问题。所以,如果nids_params.one_loop_less如果
为非零,你不允许分配两个或者更多callback函数处理同一个TCP流的一半。不幸的是现存的接口不能
向callback函数宣布这个错误,因此你必须自己小心,你已经被警告过了。

----------------------------------------------------------------------------------------------
引自:http://hi.baidu.com/yaming/blog/item/3ca8970a79c8df1894ca6b4e.html

分享到:
评论

相关推荐

    Libnids-API(中文版)

    根据给定的文件标题、描述、标签以及部分内容,下面将详细介绍与Libnids相关的知识点。 ### 1. 简介 Libnids 是一个网络入侵检测系统的库,主要用于实现高效的网络流量分析和监控功能。它能够处理各种复杂的网络...

    libnids-API

    ### libnids-API详解 #### 1. 简介 `libnids`是一款用于网络入侵检测系统(Network Intrusion Detection System, NIDS)的开源软件库,它提供了高效的网络数据包捕获、分析和处理功能。对于那些需要对网络流量进行...

    libnids-1.23

    在实际应用中,Libnids-1.23可以通过编程接口(API)集成到自定义的安全软件中,开发者可以利用它的功能来构建自己的网络监控解决方案。例如,它可以用于开发实时的网络流量分析工具,或者创建特定领域的安全应用,...

    libnids-1.24.rar

    同时,libnids提供了丰富的API接口,方便开发者集成到自己的应用程序中。 在libnids-1.24版本中,可能包含了该库的源代码、文档、示例程序和编译脚本等资源。通过阅读源代码,我们可以深入了解libnids的实现细节,...

    libnids-1.18.tar.gz

    3. **灵活性**:libnids提供丰富的API,允许开发者根据需求定制规则和检测策略,适应各种复杂的网络环境。 4. **可扩展性**:libnids支持与其他安全工具和框架的集成,如Snort、Bro等,通过插件或模块扩展其功能。 ...

    libnids-libpcap-libnet库源码合辑

    在IT领域,网络编程是构建高效、稳定网络应用的基础,而`libnids`、`libpcap`和`libnet`是三个重要的开源库,它们分别提供了不同的功能,为网络开发人员提供了强大的工具集。下面我们将详细探讨这三个库的功能、应用...

    Libnids入门

    Libnids作为网络入侵检测领域的重要工具,其强大的数据包分析能力和灵活的API设计,使其成为网络安全领域不可或缺的一部分。通过深入理解Libnids的数据结构、状态管理及常用函数,开发者可以高效地构建定制化的网络...

    libnids使用.zip

    5. **API接口**:Libnids提供了丰富的API接口,使得开发者能够轻松地将其集成到自己的应用程序中,实现自定义的网络监控功能。 **libnids与pcap库的关系** Pcap库是libnids的基础,它负责底层的数据包捕获。Pcap库...

    利用libnids和ibcap进行tcp会话的重组

    在这个场景中,我们关注的是如何利用libnids和libcap这两个库来重组TCP会话。libnids是一个开源的网络入侵检测系统(NIDS)库,主要用于处理IP数据包,而libcap则是Linux操作系统中用于获取网络接口数据包的权限的...

    libnids课件 网络数据

    libnids提供了简洁的API供开发者使用。例如,`nids_init`函数用于初始化libnids,`nids_register_event`用于注册事件回调,`nids_process_packet`则处理接收到的数据包。通过这些接口,开发者可以构建自定义的网络...

    Http.rar_http log_http 监控_http 解析_libnids_libnids http

    HTTP(超文本传输协议)是互联网上应用最为...然后编写程序,利用libnids提供的API来监听网络流量,解析HTTP数据包,并记录相关信息到日志文件中。这样的工具对网络安全分析、故障排查以及用户行为研究有着重要的价值。

    nids.rar_NIDS_libnids_nids.lib_nids开发_visual c

    例如,通过`#include "nids.h"`,开发者可以访问libnids的API,如`nids_init`、`nids_register_event`等,这些函数用于初始化库、注册事件处理回调和处理捕获的数据包。 总的来说,这个压缩包提供了一个在Windows...

    libnids_TCP.rar_C++ TCP_build589_libnids_tcp

    使用libnids进行TCP分析时,开发者可以利用其提供的API来创建自己的网络监测应用。例如,可以监听网络接口,当检测到特定的TCP连接行为时触发事件处理。这对于网络安全、流量分析、故障排查等领域具有极大的价值。 ...

    tcp.rar_libnids

    3. **打开网络接口**: 使用WinPcap API打开网络接口,开始监听网络流量。 4. **数据包捕获**: 当数据包到达时,WinPcap会触发回调函数,此时可以调用Libnids对TCP流进行重组和分析。 5. **TCP流分析**: Libnids跟踪...

    入侵检测系统的设计与实现 课程设计

    Java的网络编程API提供了处理网络数据包的能力,同时,Java集合框架和多线程机制也能支持大规模数据处理和并发操作。 5. 系统架构与设计: 一个典型的入侵检测系统可能包括数据收集模块(负责数据包捕获)、预处理...

    libnids源码注释

    5. **API接口**: libnids提供了一系列API接口,允许开发者轻松地集成到自己的应用程序中,实现网络流量的监控和分析。 **标签解析** 1. **IP**: IP是Internet Protocol的缩写,指的是互联网协议,它是TCP/IP协议栈...

    Linux下ubuntu eu部署

    MongoDB C++驱动提供了一个更高级别的API来操作MongoDB。 1. 解压`mongo-cxx-driver-legacy-0.0-26compat-2.6.6.tar.gz`到指定目录。 2. 使用`scons`进行编译安装: ``` tar xvf mongo-cxx-driver-legacy-0.0-26...

    linux-nids-qt.zip_Linux QT_NIDS_libnet_linux-nids-_嵌入式 安全

    QT库提供了丰富的API,支持多种编程语言,如C++,使得开发者能够高效地构建功能强大的桌面和移动应用。在这个项目中,QT版本2.3.2被用来设计和实现NIDS的用户界面,提供了良好的可定制性和可扩展性。 **libpcap**:...

    libpcap入门

    在网络安全工具开发领域,特别是在Unix系统平台上,存在多种流行的C API library,比如libnet、libpcap、libnids和libicmp等。这些库从不同的层次提供了丰富的功能,帮助开发者专注于应用程序的具体功能设计与开发,...

    libnet网络编程

    libnet与libpcap和libnids并称为网络安全开发的三大法宝,它们共同为开发者提供了丰富的API,帮助他们编写出结构良好、性能稳定且具有高度可移植性的程序。 #### 二、libnet的特点 1. **高级别的抽象**: libnet...

Global site tag (gtag.js) - Google Analytics