前言
本文主要介绍几个在UNIX系统平台上开发网络安全工具时最常用的library。此外还提供一些如何使用这些开发库进行网络安全工具开发的设计框架和流程。希望能和对网络安全工具开发有兴趣的朋友共同交流,互相促进。
众所周知,基于socket的网络编程已成为当今不可替代的编程方法。这种编程思想将网络通讯当作“文件”描述字进行处理,对这个“网络文件”(即 socket,套接字/套接口)的操作从编程者的角度来讲与普通的文件操作(如读、写、打开、关闭等)大同小异,从而极大地简化了网络程序开发过程。
在众多的网络安全程序、工具和软件中都是基于socket设计和开发的。由于在安全程序中通常需要对网络通讯的细节(如连接双方地址/端口、服务类型、传输控制等)进行检查、处理或控制,象数据包截获、数据包头分析、数据包重写、甚至截断连接等,都几乎在每个网络安全程序中必须实现。为了简化网络安全程序的编写过程,提高网络安全程序的性能和健壮性,同时使代码更易重用与移植,最好的方法就是将最常用和最繁复的过程函数,如监听套接口的打开/关闭、数据包截获、数据包构造/发送/接收等,封装起来,以API library的方式提供给开发人员使用。
C开发库简介
在Unix系统平台上的网络安全工具开发中,目前最为流行的C API library有libnet、libpcap、libnids和libicmp等。它们分别从不同层次和角度提供了不同的功能函数。使网络开发人员能够忽略网络底层细节的实现,从而专注于程序本身具体功能的设计与开发。其中,
* libnet提供的接口函数主要实现和封装了数据包的构造和发送过程。
* libpcap提供的接口函数主要实现和封装了与数据包截获有关的过程。
* libnids提供的接口函数主要实现了开发网络入侵监测系统所必须的一些结构框架。
* libicmp等相对较为简单,它封装的是ICMP数据包的主要处理过程(构造、发送、接收等)。
利用这些C函数库的接口,网络安全工具开发人员可以很方便地编写出具有结构化强、健壮性好、可移植性高等特点的程序,如scanner、sniffer、firewall、IDS等。
libnet
libnet库的最新版本为1.0.0,它一共约7600行C源代码,33个源程序文件,12个C头文件,50余个自定义函数,提供的接口函数包含15种数据包生成器和两种数据包发送器(IP层和数据链路层)。目前只支持IPv4,不支持IPv6。已经过测试的系统平台包括:
* OpenBSD 2.6snap, 2.5, 2.4, 2.3, 2.2 (i386)
* FreeBSD 4.0-STABLE, 3.3-STABLE, 3.2-RELEASE, 3.1-CURRENT, 3.0, 2.2 (i386)
* NetBSD 1.3.2 (i386)
* BSD/OS 3.x (i386)
* BSDi 3.0 (i386)
* Linux 2.2.x, 2.0.3x, 2.1.124 (i386, alpha) (libc: 2.4.x, glibc: 2.0.x)
* Solaris 7 (SPARC, gcc 2.7.2[13], 2.8.2), 2.6 (SPARC, gcc 2.8.2),
2.5.x (SPARC, gcc 2.7.2[13])
* IRIX 6.2
* MacOS 5.3rhapsody (powerpc)
libnet提供的接口函数按其作用可分为四类:
* 内存管理(分配和释放)函数
* 地址解析函数
* 数据包构造函数
* 数据包发送函数
以下分别列出这些接口函数及其功能(其参数含义简单易懂,不再解释):
★ 内存管理函数
单数据包内存初始化:
int libnet_init_packet(u_short packet_size, u_char **buf);
单数据包内存释放:
void libnet_destroy_packet(u_char **buf);
多数据包内存初始化:
int libnet_init_packet_arena(struct libnet_arena **arena,
u_short packet_num, u_short packet_size);
访问多数据包内存中的下一个数据包:
u_char *libnet_next_packet_from_arena(struct libnet_arena **arena,
u_short packet_size);
多数据包内存释放:
void libnet_destroy_packet_arena(struct libnet_arena **arena);
★ 地址解析函数
解析主机名:
u_char *libnet_host_lookup(u_long ip, u_short use_name);
解析主机名(可重入函数):
void libnet_host_lookup_r(u_long ip, u_short use_name, u_char *buf);
域名解析:
u_long libnet_name_resolve(u_char *ip, u_short use_name);
获取接口设备IP地址:
u_long libnet_get_ipaddr(struct libnet_link_int *l,
const u_char *device, const u_char *ebuf);
获取接口设备硬件地址: