📄 550.htm
字号:
// 和数据流方向 <br>
write(2,hlf->data,hlf->count_new); // 输出显示接收到的新数据 <br>
} <br>
return ; <br>
} <br>
int <br>
main () <br>
{ <br>
// 此处可自定义libnids的全局变量,如: <br>
// nids_params.n_hosts=256; <br>
if (!nids_init () ) <br>
{ <br>
fprintf(stderr,"%s\n",nids_errbuf); <br>
exit(1); <br>
} <br>
nids_register_tcp (tcp_callback); <br>
nids_run (); <br>
// NOT REACHED <br>
return 0; <br>
} <br>
---------------------------END OF CODE------------------------------------ <br>
五、libnids的数据结构及接口函数 <br>
libnids库的所有数据结构及接口函数都在"nids.h"头文件中声明。 <br>
struct tuple4 // TCP连接参数 <br>
{ <br>
unsigned short source,dest; // 客户端和服务器端的端口号 <br>
unsigned long saddr,daddr; // 客户端和服务器端的IP地址 <br>
}; <br>
struct half_stream // TCP连接一端的数据结构 <br>
{ <br>
char state; // 套接字状态(如TCP_ESTABLISHED) <br>
char collect; // 如果大于0,则保存其数据到缓冲区中,否则忽略 <br>
char collect_urg; // 如果大于0,则保存紧急数据,否则忽略 <br>
char * data; // 正常数据的缓冲区 <br>
unsigned char urgdata; // 紧急数据缓冲区 <br>
int count; // 自从连接建立以来保存到"data"缓冲区的数据字节 <br>
// 数总和 <br>
int offset; // 保存到"data"缓冲区的首字节数据偏移量 <br>
int count_new; // 最近一次接收到的数据字节数;如果为0,则无数 <br>
// 到达 <br>
char count_new_urg; // 如果非0,表示有新的紧急数据到达 <br>
... // libnids库使用的辅助字段 <br>
}; <br>
struct tcp_stream <br>
{ <br>
struct tuple4 addr; // TCP连接参数(saddr, daddr, sport, dport) <br>
char nids_state; // TCP连接的逻辑状态 <br>
struct half_stream client,server; // 描述客户端与服务器端的数据结构 <br>
... // libnids库使用的辅助字段 <br>
}; <br>
在上面的实例程序中,回调函数tcp_callback输出显示hlf->data缓冲区中的数据到 <br>
标准输出设备上。这些数据在tcp_callback函数返回后,由libnids自动释放这些数据所 <br>
占用的内存空间。同时,hlf->offset字段将增加被丢弃数据的字节数,而新接收到的数 <br>
据则存放到"data"缓冲区的起始处。 <br>
如果在其它应用中不进行如上例的操作(例如,数据处理过程至少需要N个字节的输 <br>
入数据,而libnids只接收到的数据字节数count_new<N),则需要在tcp_callback函数返 <br>
回前调用如下函数: <br>
void nids_discard(struct tcp_stream * a_tcp, int num_bytes) <br>
此时,当回调函数tcp_callback返回后linids将"data"缓冲区的前num_bytes字节数据, <br>
同时计算调整offset字段的数值,并将剩余数据移动到缓冲区的起始处。 <br>
如果始终不调用nids_discard()函数(如上面实例),hlf->data缓冲区中将包含hlf <br>
->count_new字节数据。通常情况下,在hlf->data缓冲区中的数据字节数等于hlf->cou <br>
nt - hlf->offset。 <br>
有了nids_discard()函数,程序员就不必拷贝接收到的数据到另外的缓冲区中,hl <br>
f->data缓冲区将总是尽可能保存足够的数据。然后,有时会有保留数据包特定数据的需 <br>
要。例如,我们希望能监测到针对wu-ftpd服务器的"CWD"溢出攻击,就需要跟踪检查ft <br>
p客户端发送的"CWD"命令。此时就需要tcp_callback回调函数具有第二个参数了。此参 <br>
数是某TCP连接私有数据的指针。处理过程如下: <br>
void <br>
tcp_callback_2 (struct tcp_stream * a_tcp, struct conn_param **ptr) <br>
{ <br>
if (a_tcp->nids_state==NIDS_JUST_EST) <br>
{ <br>
struct conn_param * a_conn; <br>
if the connection is uninteresting, return; <br>
a_conn=malloc of some data structure <br>
init of a_conn <br>
*ptr=a_conn // this value will be passed to tcp_callback_2 in future <br>
<br>
// calls <br>
increase some of "collect" fields <br>
return; <br>
} <br>
if (a_tcp->nids_state==NIDS_DATA) <br>
{ <br>
struct conn_param *current_conn_param=*ptr; <br>
using current_conn_param and the newly received data from the net <br>
we search for attack signatures, possibly modyfying <br>
current_conn_param <br>
return ; <br>
} <br>
... <br>
} <br>
nids_register_tcp和nids_register_ip*函数可被任意次调用。在同一个TCP连接中 <br>
使用两种不同的回调函数是允许的。 <br>
libnids库定义了一个全局变量结构nids_params,其声明如下: <br>
struct nids_prm <br>
{ <br>
int n_tcp_streams; // 存放tcp_stream结构的hash表大小。 <br>
// 缺省值:1024 <br>
int n_hosts; // 存放IP分片信息的hash表大小 <br>
// 缺省值:256 <br>
char * device; // libnids监听的接口设备名 <br>
// 缺省值 == NULL,即由pcap_lookupdev函数确定 <br>
int sk_buff_size; // (Linux内核)sk_buff结构大小 <br>
// 缺省值:168 <br>
int dev_addon; // sk_buff为网络接口保留的字节数 <br>
// 如果dev_addon==-1,则由nids_init函数确定 <br>
// 缺省值:-1 <br>
void (*syslog)(); // 日志函数指针 <br>
int syslog_level; // 如果nids_params.syslog==nids_syslog,则此字段值 <br>
// 将确定日志等级loglevel <br>
// 缺省值:LOG_ALERT <br>
int scan_num_hosts;// 存放端口扫描信息的hash表大小。 <br>
// 如果为0,则关闭端口扫描监测功能。 <br>
// 缺省值:256 <br>
int scan_num_ports;// 来自同一IP地址所扫描的TCP端口数上限 <br>
// 缺省值:10 <br>
int scan_delay; // 在两次端口扫描中的间隔时间上限(毫秒) <br>
// 缺省值:3000 <br>
void (*no_mem)(); // 内存不足时被调用,此时应终止当前进程 <br>
int (*ip_filter)(struct ip*); // 当接收到一个IP数据包时调用。如返回值 <br>
// 非零,则处理该数据包,否则忽略。 <br>
// 缺省为(nids_ip_filter)且总返回1 <br>
char *pcap_filter; // 传递给pcap过滤器的字符串。 <br>
// 缺省值:NULL <br>
} nids_params; <br>
nids_params的syslog字段缺省时指向nids_syslog函数,声明如下: <br>
void nids_syslog (int type, int errnum, struct ip *iph, void *data); <br>
<br>
nids_params.syslog函数用于记录异常情况,如端口扫描企图,无效TCP头标志等。 <br>
该字段应指向自定义的日志处理函数。nids_syslog()仅作为一个例子。nids_syslog() <br>
函数向系统守护服务syslogd发送日志消息。 <br>
使用nids_run有一个缺陷:应用程序将完全由数据包驱动(运行)。有时需要在没有 <br>
数据包到达时也能处理一些任务,则作为nids_run()函数的替代,程序员可使用如下函 <br>
数: <br>
int nids_next() <br>
此函数将调用pcap_next()函数(而不是pcap_loop()函数)。(详细资料请参阅《网络安全 <br>
工具开发函数库介绍之二 ——libpcap》。) nids_next()函数成功时返回1,出错时返 <br>
回0,且nids_errbuf缓冲区存放相应错误消息。 <br>
典型地,当使用nids_next()函数时,应用程序调用I/O复用函数select()阻塞,监 <br>
听套接字fd在“读”描述字集合fd_set中设置。该套接字可通过如下函数获得: <br>
int nids_getfd() <br>
成功时返回一个文件描述字,出错时返回-1,且nids_errbuf缓冲区存放相应错误消息。 <br>
<br>
<<< 待续 >>> <br>
绿色兵团版权所有。未经允许,不得转载! <br>
=== 说难不难,说易不易。=== <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="517.htm">上一层</a>][<a href="551.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -