Libnids是基于Libpcap和Libnet而开发的,是一个用于网络入侵检测开发的专业编程接口,利用Libndis可以构建网络入侵检测系统。
Libnids有哪些功能
分析源码会发现,Libnids的主要功能包括捕获网络数据包,IP碎片重组、TCP数据流重组以及端口扫描攻击检测、异常数据包检测等等。
这里要说一下,Libnids是基于libpcap来捕获数据包,可以设定过滤规则。对于IP碎片重组,Libnids是参考Linux内核中的IP重组而实现的。
Libnids有TCP数据流重组功能,这在一些开发包中所不具备的,在Libnids中利用TCP数据流重组,可以分析基于TCP协议的各种应用层协议。
Libnids可以做什么
对于Libnids可以用在一下这几个方面
1、网络嗅探
2、协议分析
3、入侵检测
下面对这几个方面进行简单的描述。
网络嗅探
网络嗅探可以称为网络监视,主要是检测网络信息,查看网络内容。
如果你是网络管理员,想知道网络的运行状况,想检测网络出现的状况,可以使用网络嗅探技术来实现。
对于网络非法攻击者来说,为了获取敏感信息,可以使用网络嗅探技术来实现。获取密码、用户、账户等。这些都是基于Libnids获取的,所以说Libnids是一把双刃剑。
网络协议
Libndis是在Libpcap基础上开发的,所以他具备libpcap的功能,可以实现各种协议解析。我们在利用libnids分析基于TCP协议的各种协议时,不仅可以分析各种单个TCP数据包,而且可以分析整个TCP连接过程。
入侵检测
Libnids的设计是作为入侵检测系统的一个部件设计的,它实现了入侵检测系统中非常基础的功能。例如:数据包捕获、协议分析接口等。
Libnids还准备针对入侵检测系统的特性,实现了TCP数据流的重组功能,这对于分析针对TCP协议的各种攻击是很有帮助的。
Libnids安装
我们了解libnids可以做什么以后,接下来,我们来安装Libnids开发包。由于Libnids必须支持libpcap、libnet,所以我们得安装好这两个包。这里就不多说了,这里只给安装libnids安装。
安装libnids需要四个步骤,分别是:
tar zxvf libnids-1.24.tar.gz
./configure
make
make install
首先解压缩,执行如下命令:
然后进入Libnids解压缩目录,执行如下配置命令:
执行编译命令
执行安装命令
常用的Libnids函数
基本函数
- int nids_init (void);
此函数的功能是对Libnids进行初始化,这是所有设计基于Libnids的程序最开始调用的函数。它的主要内容包含打开网络接口、打开文件、编译过滤规则、设置过滤规则、判断网络链路类型,进行必要的初始化工作。
- int nids_run()
此函数的功能是运行Libnids,进入循环捕获数据包状态,它实际上是调用Libpcap函数pcap_loop()来循环捕获数据包。
- int nids_getfd()
此函数的功能是获得文件描述符号。
-
int nids_dispatch(int cnt)
此函数的功能就是调用Libpcap中的捕获数据包函数 pcap_dispatch() -
int nids_next()
此函数的功能是调用Libpcap中的捕获数据包函数 pcap_next()
IP常用函数
- void nids_register_ip_frag(void (*x))
此函数的功能是注册一个能够检测所有IP数据包的回调函数,包括IP碎片。例如:
nids_register_ip_frag(ip_frag_func);
注册一个回调函数ip_frag_func定义类型如下:
void ip_frag_func(struct ip * a_packet, int len)
此函数可以检测所有IP数据包,包括IP碎片。
TCP常用函数
- void nids_register_tcp (void (*));
此函数是注册一个TCP链接的回调函数。回调函数的定义如下:
void tcp_callback (struct tcp_stream *a_tcp, void ** this_time_not_needed)
a_tcp表示一个TCP连接的所有信息,this_time_not_needed是要传递的连接参数信息。
- void nids_killtcp(struct tcp_stream *a_tcp)
此函数的功能是终止TCP连接,它实际上是调用Libnet的函数进行构造数据包,然后发送出去。
- void nids_discard(struct tcp_stream * a_tcp, int num)
此函数的功能是丢弃num字节TCP数据。
UDP常用函数
- void nids_register_udp (void (*));
此函数的功能是注册一个分析UDP协议的回调函数,回调函数的类型定义如下:
- void udp_callback(struct tuple4 * addr, char * buf, int len, struct
ip * iph);
此回调函数中就可以对UDP数据包进行分析了。
Libnids的使用
显示tcp连接
下面我们写一个程序,显示TCP连接过程,并对它们的传输数据进行 详细的分析。
#include <sys/types.h>
#include <dnet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <fcntl.h>
#include <nids.h>
char ascii_string[10000];
char *char_to_ascii(char ch)
{
char *string;
ascii_string[0] = 0;
string = ascii_string;
if (isgraph(ch))
{
*string++ = ch;
}
else if (ch == ' ')
{
*string++ = ch;
}
else if (ch == '\n' || ch == '\r')
{
*string++ = ch;
}
else
{
*string++ = '.';
}
*string = 0;
return ascii_string;
}
void tcp_protocol_callback(struct tcp_stream *tcp_connection, void **arg)
{
int i;
char address_string[1024];
char content[65535];
char content_urgent[65535];
struct tuple4 ip_and_port = tcp_connection->addr;
strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
sprintf(address_string + strlen(address_string), " : %i", ip_and_port.source);
strcat(address_string, " <---> ");
strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
sprintf(address_string + strlen(address_string), " : %i", ip_and_port.dest);
strcat(address_string, "\n");
switch (tcp_connection->nids_state) /* 判断LIBNIDS的状态 */
{
case NIDS_JUST_EST:
tcp_connection->client.collect++;
tcp_connection->server.collect++;
tcp_connection->server.collect_urg++;
tcp_connection->client.collect_urg++;
printf("%sTCP连接建立\n", address_string);
return ;
case NIDS_CLOSE:
printf("--------------------------------\n");
printf("%sTCP连接正常关闭\n", address_string);
return ;
case NIDS_RESET:
printf("--------------------------------\n");
printf("%sTCP连接被RST关闭\n", address_string);
return ;
case NIDS_DATA:
{
struct half_stream *hlf;
if (tcp_connection->server.count_new_urg)
{
printf("--------------------------------\n");
strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
sprintf(address_string + strlen(address_string), " : %i", ip_and_port.source);
strcat(address_string, " urgent---> ");
strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
sprintf(address_string + strlen(address_string), " : %i", ip_and_port.dest);
strcat(address_string, "\n");
address_string[strlen(address_string) + 1] = 0;
address_string[strlen(address_string)] = tcp_connection->server.urgdata;
printf("%s", address_string);
return ;
}
if (tcp_connection->client.count_new_urg)
{
printf("--------------------------------\n");
strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
sprintf(address_string + strlen(address_string), " : %i", ip_and_port.source);
strcat(address_string, " <--- urgent ");
strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
sprintf(address_string + strlen(address_string), " : %i", ip_and_port.dest);
strcat(address_string, "\n");
address_string[strlen(address_string) + 1] = 0;
address_string[strlen(address_string)] = tcp_connection->client.urgdata;
printf("%s", address_string);
return ;
}
if (tcp_connection->client.count_new)
{
hlf = &tcp_connection->client;
strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
sprintf(address_string + strlen(address_string), ":%i", ip_and_port.source);
strcat(address_string, " <--- ");
strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
sprintf(address_string + strlen(address_string), ":%i", ip_and_port.dest);
strcat(address_string, "\n");
printf("--------------------------------\n");
printf("%s", address_string);
memcpy(content, hlf->data, hlf->count_new);
content[hlf->count_new] = '\0';
printf("客户端接收数据\n");
for (i = 0; i < hlf->count_new; i++)
{
printf("%s", char_to_ascii(content[i]));
}
printf("\n");
}
else
{
hlf = &tcp_connection->server;
strcpy(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.saddr))));
sprintf(address_string + strlen(address_string), ":%i", ip_and_port.source);
strcat(address_string, " ---> ");
strcat(address_string, inet_ntoa(*((struct in_addr*) &(ip_and_port.daddr))));
sprintf(address_string + strlen(address_string), ":%i", ip_and_port.dest);
strcat(address_string, "\n");
printf("--------------------------------\n");
printf("%s", address_string);
memcpy(content, hlf->data, hlf->count_new);
content[hlf->count_new] = '\0';
printf("服务器端接收数据\n");
for (i = 0; i < hlf->count_new; i++)
{
printf("%s", char_to_ascii(content[i]));
}
printf("\n");
}
}
default:
break;
}
return ;
}
int main(int argc ,char **argv)
{
if (!nids_init())
/* Libnids初始化 */
{
printf("出现错误:%s\n", nids_errbuf);
exit(1);
}
nids_register_tcp((void*)tcp_protocol_callback);
nids_run();
/* Libnids进入循环捕获数据包状态 */
return 0;
}
此程序主要分析当建立TCP数据流进行重组,显示TCP连接状态,并对TCP的传输数据进行详细分析并输出。
总结
Libnids是一个入侵检测系统开发包,可以构造入侵检测系统的基本框架,还可以用于网络监控系统,网络数据包分析系统等。
欢迎关注微信公众号【程序猿编码】,欢迎添加本人微信号(17865354792),交个朋友,咱们一起学习进步!