数据结构的定义,源代码来自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 };