数据结构的定义,源代码来自libnids-1.24版本,虽然libnids貌似更新的不频繁,但是基本是跟Linux内核的TCP/IP协议栈实现类似的,所以十分有用
1:报警类型
对IP,TCP,UDP数据包异常以及扫描的检测,不同的方式提供不同的报警类型
23 enum
24 {
25 NIDS_WARN_IP = 1, //表示IP数据包异常
26 NIDS_WARN_TCP, //表示TCP数据包异常
27 NIDS_WARN_UDP, //表示UDP数据包异常
28 NIDS_WARN_SCAN //表示有扫描攻击发生
29 };
31 enum
32 {
33 NIDS_WARN_UNDEFINED = 0, //表示未定义
34 NIDS_WARN_IP_OVERSIZED, //表示IP数据包超长
35 NIDS_WARN_IP_INVLIST, //表示无效的碎片队列
36 NIDS_WARN_IP_OVERLAP, //表示发生重叠
37 NIDS_WARN_IP_HDR, //表示无效的IP首部,IP数据包异常
38 NIDS_WARN_IP_SRR, //表示源路由IP数据包
39 NIDS_WARN_TCP_TOOMUCH, //表示TCP数据个数太多,因为在Libnids中在同一时刻
//捕获的TCP个数最大值为TCP连接参数的哈希表长度的3/4
40 NIDS_WARN_TCP_HDR, //表示无效的TCP首部,TCP数据包发生异常
41 NIDS_WARN_TCP_BIGQUEUE, //表示TCP接收的队列数据过多
42 NIDS_WARN_TCP_BADFLAGS //表示错误标记
43 };
2:TCP连接状态
45 # define NIDS_JUST_EST 1 //TCP连接建立,在此状态下可以决定是否对此TCP连接 //进行数据分析,可以决定是否捕获TCP客户端或者服务器接收的数据或者紧急数据 46 # define NIDS_DATA 2 //TCP连接接收数据的状态;在这个状态可以判断是否有 //新的数据到达,如果有就可以把数据储存起来,可以在这个状态之中来分析TCP传输的数据, //此数据就存储在half_stream数据结构的缓存之中 47 # define NIDS_CLOSE 3 //TCP连接正常关闭 48 # define NIDS_RESET 4 //TCP连接被重置关闭 49 # define NIDS_TIMED_OUT 5 //TCP连接超时关闭 50 # define NIDS_EXITING 6 //libnids正在退出,这个状态下可以最后一次使用存储 //在half_stream数据结构中的缓存数据
而其实TCP状态一共有11种
enum {
TCP_ESTABLISHED = 1, //表示ESTABLISHED状态,TCP连接建立,开始传输数据
TCP_SYN_SENT, //表示SYN_SENT状态,主动打开
TCP_SYN_RECV, //表示SYN_RECV状态,接收SYN
TCP_FIN_WAIT1, //表示FIN_WAIT_1状态
TCP_FIN_WAIT2, //表示FIN_WAIT_2状态
TCP_TIME_WAIT, //表示TIME_WAIT状态
TCP_CLOSE, //表示CLOSED状态
TCP_CLOSE_WAIT, //表示CLOSE_WAIT状态
TCP_LAST_ACK, //表示LAST_ACk状态
TCP_LISTEN, //表示LISTEN状态
TCP_CLOSING //表示CLOSING状态
}
3:校验和
libnids里实现了是否计算校验和功能
#define NIDS_DO_CHKSUM 0 //表示需要计算校验和 #define NIDS_DONT_CHKSUM 1 //表示不需要计算校验和
4:四元组
tuple4描述了四元组
55 struct tuple4
56 {
57 u_short source; //源端口
58 u_short dest; //目的端口
59 u_int saddr; //源IP地址
60 u_int daddr; //目的IP地址
61 };
这里描述的不仅仅是TCP协议分析,UDP也是一样的
5:half_stream
这个数据结构描述在TCP连接中某一端的所有信息,可以是客户端,也可以是服务端
63 struct half_stream
64 {
65 char state; //套接字的状态,也就是上面说的TCP连接状态
66 char collect; //collect表示有数据到达,大于0此数据存放在data缓冲区中;
//也可以表示不存储此数据到data中,不大于0,忽略
67 char collect_urg; //collect_urg表示是否有紧急数据到达,大于0存放在urgdata
//中,也可以不存储到urgdata中,小于0,忽略
68
69 char *data; //用来存储正常接收到的数据
70 int offset; //用来存储在data缓冲区中数据的第一个字节的偏移量
71 int count; //从TCP连接开始已经存储到data缓冲区中的数据的字节数
72 int count_new; //有多少新的数据存储到data中,如为0,表示没新数据到达
73 int bufsize; //数据区最大长度
74 int rmem_alloc; //该TCP连接所有数据的长度和,包括list队列里的
75
76 int urg_count; //如果不为0,新的紧急数据到达
77 u_int acked;
78 u_int seq;
79 u_int ack_seq;
80 u_int first_data_seq;
81 u_char urgdata; //存储紧急数据
82 u_char count_new_urg; //是否有紧急数据到达,如果不为0,有新的紧急数据到达
83 u_char urg_seen; //有新的URG数据,不是以前的重复数据
84 u_int urg_ptr; //指向URG数据在流中的位置
85 u_short window; //窗口大小
86 u_char ts_on;
87 u_char wscale_on;
88 u_int curr_ts;
89 u_int wscale;
90 struct skbuff *list;
//当收到的TCP包中SEQ比期望的SEQ大时,则将数据先保存到此双向链表中,
//为了访问方便,此链表按包中的SEQ从小到大排序,链尾为含最大SEQ的TCP包
91 struct skbuff *listtail; //ptr to tail of list
92 };
虽然数据结构half_stream的成员十分多,但特别注意的不太多;state非常重要,描述了当前TCP的连接状态,只有知道了TCP连接状态之后,才能进行下一步的动作;data用来存储接收到的正常的网络数据信息;urgdata存储接收到的紧急数据;count_new判断是否有新的正常数据到达;count_new_urg判断是否有新的紧急数据到达;输出新到达的数据内容,正常数据存储在data中,紧急数据存储在urgdata中
6:tcp_stream
描述了一个TCP连接的所有信息,这应该是最重要的一个数据结构
94 struct tcp_stream
95 {
96 struct tuple4 addr; //TCP连接的四元组信息
97 char nids_state; //TCP连接的逻辑状态(6种)
98 struct lurker_node *listeners; //给TCP处理的回调函数使用,其中一成员指向回调函数
99 struct half_stream client; //客户端信息
100 struct half_stream server; //服务器信息
101 struct tcp_stream *next_node;
102 struct tcp_stream *prev_node;
103 int hash_index;
104 struct tcp_stream *next_time;
105 struct tcp_stream *prev_time;
106 int read; //本次读取数据缓冲区的数据的长度
107 struct tcp_stream *next_free; //指向下一个空闲TCP结构
108 void *user;
109 };
7:nids_prm
描述了全局变量参数信息
111 struct nids_prm
112 {
113 int n_tcp_streams; //用来存放tcp_stream数据结构的哈希表的大小,默认1040;
//在同一时刻libnids捕获的TCP数据包的最大个数必须是此参数值的3/4
114 int n_hosts; //存放IP碎片信息哈希表的大小,默认256
115 char *device; //网络接口,在此接口上捕获数据,默认NULL;libnids用
//pcap_lookupdev查找可用的网络接口,如果是all表示捕获所有网络接口的数据
116 char *filename; //存储网络数据包文件,必须是libpcap格式
117 int sk_buff_size; //数据结构sk_buff的大小;sk_buff是linux内核中用来
//进行数据包排队操作的,默认值为168
118 int dev_addon; //在数据结构sk_buff中用于网络接口上信息的字节数;如果
//是-1(默认),那么libnids会根据不同的网络接口进行修正
119 void (*syslog) (); //函数指针,默认为nids_syslog()函数;在syslog函数中可以
//检测入侵攻击,比如网络扫描,以及一些异常比如无效TCP标记等情况
120 int syslog_level; //日志等级,默认为LOG_ALERT
121 int scan_num_hosts; //存储端口扫描信息哈希表的大小;表示libnids要检测的同时
//扫描的端口数据;如果为0,libnids就不提供端口扫描功能;默认为256
122 int scan_delay; //在扫描检测中,两端口扫描的间隔时间,单位毫秒,默认3000
123 int scan_num_ports; //想通源地址必须扫描的TCP端口数目,默认为10
124 void (*no_mem) (char *); //函数指针,当libnids发生内存溢出时被调用
125 int (*ip_filter) (); //函数指针,函数用来分析IP数据包;当有IP数据包到达时,
//函数被调用;如果此函数返回非零值,此数据包就被处理;如果返回0,此IP数据包就被丢弃;
//默认值为nids_ip_filter函数,总是返回1
126 char *pcap_filter; //过滤规则;默认NULL,表示捕获所有的数据包,这里可以
//自行设置过滤规则,只捕获感兴趣的开发包
127 int promisc; //网卡模式;非零表示混杂模式,为零非混杂模式,默认为1
128 int one_loop_less; //初始值为0
129 int pcap_timeout; //捕获数据返回的时间,单位毫秒;表示的就是libpcap函数
//中的pcap_open_live函数的timeout参数,默认值为1024
130 int multiproc;
131 int queue_limit;
132 int tcp_workarounds;
133 pcap_t *pcap_desc;
134 };
在libnids.c里有定义和初始化
90 struct nids_prm nids_params = {
91 1040, /* n_tcp_streams */
92 256, /* n_hosts */
93 NULL, /* device */
94 NULL, /* filename */
95 168, /* sk_buff_size */
96 -1, /* dev_addon */
97 nids_syslog, /* syslog() */
98 LOG_ALERT, /* syslog_level */
99 256, /* scan_num_hosts */
100 3000, /* scan_delay */
101 10, /* scan_num_ports */
102 nids_no_mem, /* no_mem() */
103 nids_ip_filter, /* ip_filter() */
104 NULL, /* pcap_filter */
105 1, /* promisc */
106 0, /* one_loop_less */
107 1024, /* pcap_timeout */
108 0, /* multiproc */
109 20000, /* queue_limit */
110 0, /* tcp_workarounds */
111 NULL /* pcap_desc */
112 };
