ImageVerifierCode 换一换
格式:DOCX , 页数:34 ,大小:40.09KB ,
资源ID:16468495      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/16468495.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(入侵检测linux下课程设计指导书3Word格式.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

入侵检测linux下课程设计指导书3Word格式.docx

1、数据包常规的传输路径依次为网卡、设备驱动层、数据链路层、IP层、传输层、最后到达应用程序。而包捕获机制是在数据链路层增加一个旁路处理,对发送和接收到的数据包做过滤/缓冲等相关处理,最后直接传递到应用程序。值得注意的是,包捕获机制并不影响操作系统对数据包的网络栈处理。对用户程序而言,包捕获机制提供了一个统一的接口,使用户程序只需要简单的调用若干函数就能获得所期望的数据包。这样一来,针对特定操作系统的捕获机制对用户透明,使用户程序有比较好的可移植性。包过滤机制是对所捕获到的数据包根据用户的要求进行筛选,最终只把满足过滤条件的数据包传递给用户程序。libpcap应用程序框架libpcap提供了系统独

2、立的用户级别网络数据包捕获接口,并充分考虑到应用程序的可移植性。libpcap可以在绝大多数类unix平台下工作,参考资料 A 中是对基于 libpcap 的网络应用程序的一个详细列表。在windows平台下,一个与libpcap 很类似的函数包 winpcap 提供捕获功能,其官方网站是http:/winpcap.polito.it/。libpcap 软件包可从 http:/www.tcpdump.org/ 下载,然后依此执行下列三条命令即可安装,但如果希望libpcap能在Linux上正常工作,则必须使内核支持packet协议,也即在编译内核时打开配置选项 CONFIG_PACKET(选项

3、缺省为打开)。./configure./make./make installlibpcap源代码由20多个C文件构成,但在Linux系统下并不是所有文件都用到。可以通过查看命令make的输出了解实际所用的文件。本文所针对的libpcap版本号为0.8.3,网络类型为常规以太网。libpcap应用程序从形式上看很简单,下面是一个简单的程序框架:char * device; /* 用来捕获数据包的网络接口的名称 */pcap_t * p; /* 捕获数据包句柄,最重要的数据结构 */struct bpf_program fcode; /* BPF 过滤代码结构 */* 第一步:查找可以捕获数据包的

4、设备 */device = pcap_lookupdev(errbuf);/* 第二步:创建捕获句柄,准备进行捕获 */p = pcap_open_live(device, 8000, 1, 500, errbuf);/* 第三步:如果用户设置了过滤条件,则编译和安装过滤代码 */pcap_compile(p, &fcode, filter_string, 0, netmask);pcap_setfilter(p, &fcode);/* 第四步:进入(死)循环,反复捕获数据包 */for( ; ; )while(ptr = (char *)(pcap_next(p, &hdr) = NULL)

5、; /* 第五步:对捕获的数据进行类型转换,转化成以太数据包类型 */eth = (struct libnet_ethernet_hdr *)ptr;/* 第六步:对以太头部进行分析,判断所包含的数据包类型,做进一步的处理 */if(eth-ether_type = ntohs(ETHERTYPE_IP) ether_type = ntohs(ETHERTYPE_ARP) /* 最后一步:关闭捕获句柄,一个简单技巧是在程序初始化时增加信号处理函数,以便在程序退出前执行本条代码 */pcap_close(p);检查网络设备libpcap 程序的第一步通常是在系统中找到合适的网络接口设备。网络接口

6、在Linux网络体系中是一个很重要的概念,它是对具体网络硬件设备的一个抽象,在它的下面是具体的网卡驱动程序,而其上则是网络协议层。Linux中最常见的接口设备名eth0和lo。Lo 称为回路设备,是一种逻辑意义上的设备,其主要目的是为了调试网络程序之间的通讯功能。eth0对应了实际的物理网卡,在真实网络环境下,数据包的发送和接收都要通过 eht0。如果计算机有多个网卡,则还可以有更多的网络接口,如eth1,eth2 等等。调用命令ifconfig可以列出当前所有活跃的接口及相关信息,注意对eth0的描述中既有物理网卡的MAC地址,也有网络协议的IP地址。查看文件/proc/net/dev也可获

7、得接口信息。libpcap调用pcap_lookupdev()函数获得可用网络接口的设备名。首先利用函数 getifaddrs() 获得所有网络接口的地址,以及对应的网络掩码、广播地址、目标地址等相关信息,再利用 add_addr_to_iflist()、add_or_find_if()、get_instance() 把网络接口的信息增加到结构链表 pcap_if 中,最后从链表中提取第一个接口作为捕获设备。其中 get_instanced()的功能是从设备名开始,找第一个是数字的字符,做为接口的实例号。网络接口的设备号越小,则排在链表的越前面,因此,通常函数最后返回的设备名为 eth0。虽然

8、 libpcap 可以工作在回路接口上,但显然 libpcap 开发者认为捕获本机进程之间的数据包没有多大意义。在检查网络设备操作中,主要用到的数据结构和代码如下: /* libpcap 自定义的接口信息链表 pcap.h */struct pcap_if struct pcap_if *next;char *name; /* 接口设备名 */char *description; /* 接口描述 */*接口的 IP 地址, 地址掩码, 广播地址,目的地址 */struct pcap_addr addresses;bpf_u_int32 flags; /* 接口的参数 */;char * pca

9、p_lookupdev(register char * errbuf) pcap_if_t *alldevs; pcap_findalldevs(&alldevs, errbuf); strlcpy(device, alldevs-name, sizeof(device);打开网络设备当设备找到后,下一步工作就是打开设备以准备捕获数据包。libpcap的包捕获是建立在具体的操作系统所提供的捕获机制上,而Linux系统随着版本的不同,所支持的捕获机制也有所不同。2.0 及以前的内核版本使用一个特殊的socket类型SOCK_PACKET,调用形式是socket(PF_INET, SOCK_PAC

10、KET, int protocol),但 Linux 内核开发者明确指出这种方式已过时。Linux 在 2.2及以后的版本中提供了一种新的协议簇 PF_PACKET 来实现捕获机制。PF_PACKET 的调用形式为 socket(PF_PACKET, int socket_type, int protocol),其中socket类型可以是 SOCK_RAW和SOCK_DGRAM。SOCK_RAW 类型使得数据包从数据链路层取得后,不做任何修改直接传递给用户程序,而 SOCK_DRRAM 则要对数据包进行加工(cooked),把数据包的数据链路层头部去掉,而使用一个通用结构 sockaddr_l

11、l 来保存链路信息。使用 2.0 版本内核捕获数据包存在多个问题:首先,SOCK_PACKET 方式使用结构 sockaddr_pkt来保存数据链路层信息,但该结构缺乏包类型信息;其次,如果参数 MSG_TRUNC 传递给读包函数 recvmsg()、recv()、recvfrom() 等,则函数返回的数据包长度是实际读到的包数据长度,而不是数据包真正的长度。libpcap 的开发者在源代码中明确建议不使用 2.0 版本进行捕获。相对2.0版本SOCK_PACKET方式,2.2版本的PF_PACKET方式则不存在上述两个问题。在实际应用中,用户程序显然希望直接得到原始的数据包,因此使用 SOC

12、K_RAW 类型最好。但在下面两种情况下,libpcap 不得不使用SOCK_DGRAM类型,从而也必须为数据包合成一个伪链路层头部(sockaddr_ll)。某些类型的设备数据链路层头部不可用:例如 Linux 内核的 PPP 协议实现代码对 PPP 数据包头部的支持不可靠。在捕获设备为any时:所有设备意味着libpcap对所有接口进行捕获,为了使包过滤机制能在所有类型的数据包上正常工作,要求所有的数据包有相同的数据链路头部。打开网络设备的主函数是 pcap_open_live()pcap-Linux.c,其任务就是通过给定的接口设备名,获得一个捕获句柄:结构 pcap_t。pcap_t

13、是大多数libpcap函数都要用到的参数,其中最重要的属性则是上面讨论到的三种 socket方式中的某一种。首先我们看看pcap_t的具体构成。struct pcap pcap-int.h int fd; /* 文件描述字,实际就是 socket */ /* 在 socket 上,可以使用 select() 和 poll() 等 I/O 复用类型函数 */ int selectable_fd; int snapshot; /* 用户期望的捕获数据包最大长度 */ int linktype; /* 设备类型 */ int tzoff; /* 时区位置,实际上没有被使用 */ int offset

14、; /* 边界对齐偏移量 */ int break_loop; /* 强制从读数据包循环中跳出的标志 */ struct pcap_sf sf; /* 数据包保存到文件的相关配置数据结构 */ struct pcap_md md; /* 具体描述如下 */ int bufsize; /* 读缓冲区的长度 */ u_char buffer; /* 读缓冲区指针 */ u_char *bp; int cc; u_char *pkt; /* 相关抽象操作的函数指针,最终指向特定操作系统的处理函数 */ int (*read_op)(pcap_t *, int cnt, pcap_handler, u

15、_char *); int (*setfilter_op)(pcap_t *, struct bpf_program *); int (*set_datalink_op)(pcap_t *, int); int (*getnonblock_op)(pcap_t *, char *); int (*setnonblock_op)(pcap_t *, int, char *); int (*stats_op)(pcap_t *, struct pcap_stat *); void (*close_op)(pcap_t *); /*如果 BPF 过滤代码不能在内核中执行,则将其保存并在用户空间执行

16、*/ struct bpf_program fcode; /* 函数调用出错信息缓冲区 */ char errbufPCAP_ERRBUF_SIZE + 1; /* 当前设备支持的、可更改的数据链路类型的个数 */ int dlt_count; /* 可更改的数据链路类型号链表,在 Linux 下没有使用 */ int *dlt_list; /* 数据包自定义头部,对数据包捕获时间、捕获长度、真实长度进行描述 pcap.h */ struct pcap_pkthdr pcap_header;/* 包含了捕获句柄的接口、状态、过滤信息 pcap-int.h */struct pcap_md /*

17、 捕获状态结构 pcap.h */struct pcap_stat stat; int use_bpf; /* 如果为1,则代表使用内核过滤*/ u_long TotPkts; u_long TotAccepted; /* 被接收数据包数目 */ u_long TotDrops; /* 被丢弃数据包数目 */ long TotMissed; /* 在过滤进行时被接口丢弃的数据包数目 */ long OrigMissed; /*在过滤进行前被接口丢弃的数据包数目*/#ifdef Linux int sock_packet; /* 如果为 1,则代表使用 2.0 内核的 SOCK_PACKET 模

18、式 */ int timeout; /* pcap_open_live() 函数超时返回时间*/ int clear_promisc; /* 关闭时设置接口为非混杂模式 */ int cooked; /* 使用 SOCK_DGRAM 类型 */ int lo_ifindex; /* 回路设备索引号 */ char *device; /* 接口设备名称 */ /* 以混杂模式打开 SOCK_PACKET 类型 socket 的 pcap_t 链表*/struct pcap *next;#endif函数pcap_open_live()的调用形式是 pcap_t * pcap_open_live(c

19、onst char *device, int snaplen, int promisc, int to_ms, char *ebuf),其中如果 device 为 NULL 或,则对所有接口捕获,snaplen 代表用户期望的捕获数据包最大长度,promisc 代表设置接口为混杂模式(捕获所有到达接口的数据包,但只有在设备给定的情况下有意义),to_ms 代表函数超时返回的时间。本函数的代码比较简单,其执行步骤如下:* 为结构pcap_t分配空间并根据函数入参对其部分属性进行初试化。* 分别利用函数 live_open_new() 或 live_open_old() 尝试创建 PF_PACKE

20、T 方式或 SOCK_PACKET 方式的socket,注意函数名中一个为new,另一个为old。 * 根据 socket 的方式,设置捕获句柄的读缓冲区长度,并分配空间。 * 为捕获句柄pcap_t设置Linux系统下的特定函数,其中最重要的是读数据包函数和设置过滤器函数。(注意到这种从抽象模式到具体模式的设计思想在 Linux 源代码中也多次出现,如VFS文件系统) handle-read_op = pcap_read_Linux; handle-setfilter_op = pcap_setfilter_Linux;下面我们依次分析 2.2 和 2.0 内核版本下的socket创建函数。

21、static intlive_open_new(pcap_t *handle, const char *device, int promisc, int to_ms, char *ebuf)/* 如果设备给定,则打开一个 RAW 类型的套接字,否则,打开 DGRAM 类型的套接字 */sock_fd = device ? socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL);/* 取得回路设备接口的索引 */handle-md.lo_ifindex = ifac

22、e_get_id(sock_fd, lo, ebuf);/* 如果设备给定,但接口类型未知或是某些必须工作在加工模式下的特定类型,则使用加工模式 */if (device) /* 取得接口的硬件类型 */arptype = iface_get_arptype(sock_fd, device, ebuf);/* Linux 使用 ARPHRD_xxx 标识接口的硬件类型,而 libpcap 使用DLT_xxx来标识。本函数是对上述二者的做映射变换,设置句柄的链路层类型为DLT_xxx,并设置句柄的偏移量为合适的值,使其与链路层头部之和为 4 的倍数,目的是边界对齐 */map_arphrd_to

23、_dlt(handle, arptype, 1);/* 如果接口是前面谈到的不支持链路层头部的类型,则退而求其次,使用 SOCK_DGRAM 模式 */if (handle-linktype = xxx) close(sock_fd);sock_fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL);/* 获得给定的设备名的索引 */device_id = iface_get_id(sock_fd, device, ebuf); /* 把套接字和给定的设备绑定,意味着只从给定的设备上捕获数据包 */iface_bind(sock_fd, devi

24、ce_id, ebuf); else /* 现在是加工模式 */md.cooked = 1;/* 数据包链路层头部为结构 sockaddr_ll, SLL 大概是结构名称的简写形式 */linktype = DLT_Linux_SLL; device_id = -1; /* 设置给定设备为混杂模式 */if (device & promisc) memset(&mr, 0, sizeof(mr);mr.mr_ifindex = device_id;mr.mr_type = PACKET_MR_PROMISC;setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_

25、MEMBERSHIP, mr, sizeof(mr);/* 最后把创建的 socket 保存在句柄 pcap_t 中 */fd = sock_fd; /* 2.0 内核下函数要简单的多,因为只有唯一的一种 socket 方式 */live_open_old(pcap_t *handle, const char *device, int promisc,/* 首先创建一个SOCK_PACKET类型的 socket */fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL);/* 2.0 内核下,不支持捕获所有接口,设备必须给定 */if (!devi

26、ce) strncpy(ebuf, pcap_open_live: The device isnt supported on 2.0.x-kernel systems, PCAP_ERRBUF_SIZE);break;/* 把 socket 和给定的设备绑定 */iface_bind_old(handle-fd, device, ebuf);/*以下的处理和 2.2 版本下的相似,有所区别的是如果接口链路层类型未知,则 libpcap 直接退出 */arptype = iface_get_arptype(handle-fd, device, ebuf);map_arphrd_to_dlt(ha

27、ndle, arptype, 0);linktype = -1) snprintf(ebuf, PCAP_ERRBUF_SIZE, unknown arptype %d, arptype);if (promisc) ifr, 0, sizeof(ifr);strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name);ioctl(handle-fd, SIOCGIFFLAGS, &ifr);ifr.ifr_flags |= IFF_PROMISC;fd, SIOCSIFFLAGS, &比较上面两个函数的代码,还有两个细节上的区别。首先是 socket 与接口绑定所使用的结构:老式的绑定使用了结构 sockaddr,而新式的则使用了 2.2 内核中定义的通用链路头部层结构sockaddr_ll。iface_bind_old(int fd, const char *device, char *ebuf)struct sockaddr saddr;saddr, 0,

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1