• 沒有找到結果。

我們對於進行這類整合行計畫的經驗不多,很感謝成大總計畫給予我們的指導與 協助。本計畫的參與者利用一年的時間,在有限的經費下,做了最大的努力,對 網路攻防上進行研究與開發。由於時間等種種因素,很多技術我們尚不能完全掌 握,而且我們在測試的規模上也不夠擬真。對於這些技術,我們還必需要付出更 出的努力才能達到整合並且自動化的最終目標。

參考文獻

[1] S. M. Bellovin. Security Problems in the TCP/IP Protocol Suite. ACM Computer Communications Review, 19(2):32–48, Apr. 1989.

[2] S. M. Bellovin. ICMP Traceback Messages. Internet Draft:

draft-bellovin-itrace-00.txt, Oct. 2001.

[3] H. Burch and B. Cheswick. Tracing Anonymous Packets to Their Approximate Source. Unpublished paper, Dec. 1999.

[4] S. Deering. Internet protocol, version 6 (ipv6). RFC 2460, Dec. 1998.

[5] P. Ferguson and D. Senie. Network Ingress Filtering: Defeating Denial of Service Attacks Which Employ IP Source Address Spoofing. RFC 2267, Jan.

1998.

[6] R. Govindan and H. Tangmunarunkit. Heuristics for Internet Map Discovery.

In Proceedings of the 2000 IEEE INFOCOM Conference, Tel Aviv, Israel, Mar.

2000.

[7] C. Meadows. A Formal Framework and Evaluation Method for Network Denial of Service. In Proceedings of the 1999 IEEE Computer Security Foundations Workshop, Mordano,Italy, June 1999.

[8] O. Spatscheck and L. Peterson. Defending Against Denial of Service Attacks in Scout. In Proceedings of the 1999 USENIX/ACM Symposium on Operating System Design and Implementation, pages 59–72, Feb. 1999.

[9] R. Stone. CenterTrack: An IP Overlay Network for Tracking DoS Floods.

Proceedings of the 2000 USENIX Security Symposium, Denver, CO, July 2000.

[10] W. Theilmann and K. Rothermel. Dynamic Distance Maps of the Internet. In Proceedings of the 2000 IEEE INFOCOM Conference, Tel Aviv, Israel, Mar.

2000.

[11] Dave Dittrich. Distributed Denial of Service (DDoS) attacks/tools resource page. http://staff.washington.edu/dittrich/misc/ddos/.

[12] Stefan Savage, David Wetherall, Anna Karlin, and Tom Anderson. Practical network support for ip traceback. In Proceedings of the 2000 ACM SIGCOMM Conference, August 2000.

[13] K. Park and H. Lee. On the effectiveness of probabilistic packet marking for IP traceback under denial of service attack. In Proc. IEEE INFOCOM '01, pages 338-347, 2001.

[14] D. Song and A. Perrig. Advanced and authenticated marking schemes for IP traceback. Technical Report UCB/CSD-00-1107, University of California, Berkeley, June 2000.

[15] S. Deering and R. Hinden. Internet protocol, version 6 (IPv6) specification.

RFC 2474, Dec. 1995.

[16] D. Schnackenberg, K. Djahandari, and D. Sterne. Infrastructure for Intrusion Detection and Response. Proceedings of the DARPA Information Survivability Conference and Exposition (DISCEX), Hilton Head Island, SC, January 25-27, 2000.

[17]

J. Postel. Internet Control Message Protocol. RFC 792, Internet Engineering Task Force, September 1981.

[18] John Ioannidis, Steven M. Bellovin. Proceedings of Network and Distributed System Security Symposium, Catamaran Resort Hotel San Diego, C alifornia 6-8 February 2002.

[19] Alex C. Snoeren, Craig Partridge, Luis A. Sanchez, Christine E. Jones, Fabrice Tchakountio, Stephen T. Kent, and W. Timothy Strayer. “Hash-Based IP Traceback”. Proceedings of the ACM/SIGCOMM 2001 Conference on Applications, Technologies, Architectures, and Protocols for Computer Communication (SIGCOMM '01), pp. 3-14, San Diego, CA, August 2001.

[20] Alex C. Snoeren, Craig Partridge, Luis A. Sanchez, Christine E. Jones, Fabrice Tchakountio, Beverly Schwartz, Stephen T. Kent, and W. Timothy Strayer.

“Single-Packet IP Traceback”. IEEE/ACM Transactions on Networking (ToN), Volume 10, Number 6, December 2002. Pages 721-734.

[21] SPIE User's Guide http://www.ir.bbn.com/projects/SPIE/UsersGuide.pdf [22] Installing Freebsd, Mysql, and Snort Tutorial

http://www.snort.org/docs/FreeBSD47RELEASE-Snort-MySQLVer1-3.pdf.

計畫成果自評

I. 原訂計畫目標:

本子計畫的目標在研發對應 DoS 及 DDoS 攻擊的追蹤技術,而參與此子 計畫的台大與東華,則分別進行來源追蹤及分流攻擊偵測技術,針對這類攻 擊大流量,攻擊點多的特性,進行技術的研究及系統的實作開發。

II. 研究內容與原計畫相符程度

完全符合。

III. 預期目標達成情況與綜合自評

我們對於分流偵測與來源追蹤技術進行研究與實作,本計畫除了讓參與 計畫的研究生都有了良好的知識與實戰經驗,我們的成果還包括了最後的研 發成果展示,以及資訊安全訓練教材。對於一個整合型計畫,能在不到一年 的時間內達成這樣的成果,我們已盡了最大的努力,也謝謝成大的指導。

附錄 A : ICMP 訊息發送與流量統程式原始碼

(一):產生 ICMP 追蹤封包的程式碼 z icmpd.h

#ifndef __ICMPD_H__

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#define MD5KEY "The NBEN Project"

struct stamprecord {

struct in_addr stamper;

struct in_addr ip_src;

struct in_addr ip_dst;

unsigned long tv_sec;

unsigned long tv_usec;

};

#define UDP_DEFAULT_QUERY_PORT 36100

#define UDP_NULL 0

#define UDP_QUERY 1

#define UDP_RESPONSE 2

#define UDP_RESPONSE_NULL 0

#define UDP_RESPONSE_REC_FOUND 1

#define UDP_RESPONSE_REC_NOTFOUND 2

#define UDP_OP_SIGNATURE 0x2be2dd05

struct udpop {

unsigned int signature;

unsigned int magic;

unsigned short opcode;

unsigned short result;

struct in_addr ip_src;

struct in_addr ip_dst;

unsigned char md5sum[16];

};

#endif

z icmpd.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <unistd.h>

#include <signal.h>

#include <time.h>

#include <fcntl.h>

#include <pcap.h>

#include <sys/types.h>

/* md5 */

#ifdef LINUX

#include <openssl/md5.h>

#else

#include <md5.h>

#endif /* ntohs */

#include <netinet/in.h>

/* inet_ntoa */

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

/* ether_ntoa */

#include <sys/socket.h>

#include <net/ethernet.h>

/* ip header */

#include <netinet/in_systm.h>

#include <netinet/ip.h>

#include <netinet/udp.h>

#include "icmpd.h"

/* FreeBSD -> Linux */

#ifdef LINUX

#define MD5Init MD5_Init

#define MD5Update MD5_Update

#define MD5Final MD5_Final

#else char*

MD5(unsigned char *input, int len, unsigned char *output) { MD5_CTX md5;

MD5Init(&md5);

MD5Update(&md5, (unsigned char *) input, len);

MD5Final(output, &md5);

return(output);

}

#endif

#define MAXPKTSIZE 1600

#define ICMP_PKTSTAMP 32

pcap_t *p = NULL;

struct in_addr myid = {0};

FILE *logfp = NULL;

/* passing from parameters */

int noconsole = 0;

char *dev = NULL;

char *logfile = NULL;

int logsize = 10000; /* in entries, default 10000 */

int logpos = 0;

int maxlog = 0;

int probability = 1000, magic = 7;

int qport = UDP_DEFAULT_QUERY_PORT;

int qsocket = -1;

extern int errno;

void cbreak(int s) {

fprintf(stderr, "** break\n");

if(logfp) {

u_char icmp_type;

u_char icmp_code;

u_short icmp_sum;

/* private message */

u_int unused;

u_int stamper;

u_int srcip;

if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))==-1) return(-1);

if(setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval))==-1) { close(fd);

send_raw(struct in_addr ip_dst, u_char *raw, int len) { static int fd = -1;

struct sockaddr_in sin;

if(fd < 0) {

if((fd = init_raw())==-1) {

fprintf(stderr, "raw: cannot init raw socket.\n");

return;

} }

bzero(&sin, sizeof(sin));

sin.sin_family = AF_INET;

sin.sin_addr.s_addr = ip_dst.s_addr;

if(sendto(fd, raw, len, 0, (struct sockaddr*) &sin, sizeof(sin)) < 0) {

fprintf(stderr, "raw: sendto() failed(%d): %s.\n", errno, strerror(errno));

return;

}

#if 0

fprintf(stderr, "raw: send icmp to %s\n", inet_ntoa(ip_dst));

#endif }

unsigned short

in_cksum(unsigned short *addr, int len) { register int sum = 0;

u_short answer = 0;

register u_short *w = addr;

register int nleft = len;

while (nleft > 1) {

*(u_char *)(&answer) = *(u_char *)w ; sum += answer;

return(answer);

}

void

send_icmp(long tv_sec, long tv_usec, struct in_addr ip_src, struct in_addr ip_dst) { u_char buf[MAXPKTSIZE];

struct ip *ip;

struct icmp *icmp;

int pktsize;

pktsize = sizeof(struct ip) + sizeof(struct icmp);

bzero(buf, pktsize);

ip = (struct ip*) buf;

icmp = (struct icmp*) (buf + sizeof(struct ip));

ip->ip_hl = 5; /* 5*4 == 20 bytes */

ip->ip_v = 4;

ip->ip_tos = 0;

#ifdef LINUX

ip->ip_len = htons(pktsize);

#else

ip->ip_len = pktsize; /* in FreeBSD: do NOT use htons() */

#endif

ip->ip_id = rand() % 0x0ffff;

ip->ip_off = 0;

ip->ip_sum = in_cksum((unsigned short *) ip, sizeof(struct ip));

icmp->icmp_type = ICMP_PKTSTAMP;

icmp->icmp_code = 0;

icmp->icmp_sum = 0;

icmp->unused = 0;

icmp->stamper = myid.s_addr;

icmp->srcip = ip_src.s_addr;

icmp->dstip = ip_dst.s_addr;

icmp->tv_sec = tv_sec;

icmp->tv_usec = tv_usec;

/* md5 */

do {

MD5_CTX md5;

MD5Init(&md5);

MD5Update(&md5, (unsigned char *) icmp, sizeof(struct icmp) - 16);

MD5Update(&md5, (unsigned char*) MD5KEY, strlen(MD5KEY));

MD5Final(icmp->md5, &md5);

} while(0);

icmp->icmp_sum = in_cksum((unsigned short *) icmp, sizeof(struct icmp));

send_raw(ip_dst, buf, pktsize);

}

#endif // SEND ICMP

unsigned char *vector = NULL;

void

bloom_filter(unsigned int ip_src, unsigned int ip_dst) {

//printf("enter\n");

int i=0;

static int first = 0;

u_int src_dst_address[2];

u_int output[4];// sizeof(u_int) = 4

if (first == 0) { first = 1;

// allocate 28 bit vector

vector = malloc(1024*1024*256);

if (vector == NULL) {

printf("no enough memory space, so no bloom filter\n");

first = 0;

return;

} }

src_dst_address[0] = ip_src;

src_dst_address[1] = ip_dst;

MD5((unsigned char *)src_dst_address, 2*sizeof(u_int), (unsigned char *)output);

for (i=0; i<4; i++) {

unsigned char *position = vector;

unsigned char mask = 1;

output[i] &= 0x0fffffff;

position += ((output[i])>>3);

mask <<= (output[i] & 0x07);

(*position) |= mask;

} }

int

query_bloom(u_int src, u_int dst) {

int i;

u_int src_dst_address[2];

u_int output[4];// sizeof(u_int) = 4

if(vector) {

src_dst_address[0] = src;

src_dst_address[1] = dst;

MD5((unsigned char *)src_dst_address, 2*sizeof(u_int), (unsigned char *)output);

for (i=0; i<4; i++) {

unsigned char *position = vector;

unsigned char mask = 1;

output[i] &= 0x0fffffff;

position += ((output[i])>>3);

mask <<= (output[i] & 0x07);

if(((*position) & mask)==0)

unsigned short

process_ethernet(u_char *user, const struct pcap_pkthdr *hdr, const u_char *payload) { u_int caplen = hdr->caplen;

//u_int length = hdr->len;

struct ether_header *eptr; /* net/ethernet.h */

u_short ether_type;

if (caplen < ETHER_HDR_LEN) { /* not a ethernet packet */

if(noconsole==0)

fprintf(stdout, "* not an etherned packet, too short\n");

return -1;

}

/* lets start with the ether header... */

eptr = (struct ether_header *) payload;

ether_type = ntohs(eptr->ether_type);

return(ether_type);

}

int process_ip(u_char *user, const struct pcap_pkthdr *hdr, const u_char *payload) { const struct ip *ip;

/* jump pass the ethernet header */

ip = (struct ip*) (payload + sizeof(struct ether_header));

if (hdr->len < sizeof(struct ip)) { /* bad length, packet too short */

//fprintf(stdout, "* not an ip packet, too short\n");

return(-1);

}

if(ip->ip_v != 4) { /* bad version */

//fprintf(stdout, "* bad ip version\n");

return(-1);

}

if(ip->ip_hl < 5) { /* bad header length */

//fprintf(stdout, "* not an ip packet, header too short\n");

return(-1);

}

if(ip->ip_p==IPPROTO_UDP) { struct udphdr *udp;

struct udpop *opdata, oprep;

struct sockaddr_in sin;

udp = (struct udphdr*) (payload + sizeof(struct ether_header) + ((ip->ip_hl) <<

2));

opdata = (struct udpop*) (payload + sizeof(struct ether_header) + ((ip->ip_hl)

<< 2) + sizeof(*udp));

#if 0

if(ntohs(udp->uh_dport) > 2000)

fprintf(stderr, "got UDP from %s: dport=%d len=%d signature=0x%08x!\n", inet_ntoa(ip->ip_src),

ntohs(udp->uh_dport), ntohs(udp->uh_ulen), ntohl(opdata->signature));

#endif

if(ip->ip_dst.s_addr==myid.s_addr) if(ntohs(udp->uh_dport) == qport) { /********************/

int slen = sizeof(sin);

recvfrom(qsocket, &oprep, sizeof(oprep), 0, (struct sockaddr*) &sin,

&slen);

if(ntohs(udp->uh_ulen) == sizeof(struct udpop)+sizeof(struct udphdr)) if(ntohl(opdata->signature) == UDP_OP_SIGNATURE) {

unsigned char md5str[16];

MD5_CTX md5;

MD5Init(&md5);

MD5Update(&md5, (unsigned char *) opdata, sizeof(struct udpop) - 16);

MD5Update(&md5, (unsigned char*) MD5KEY, strlen(MD5KEY));

MD5Final(md5str, &md5);

if(memcmp(md5str, opdata->md5sum, 16)==0) { if(ntohs(opdata->opcode)==UDP_QUERY) {

int ret;

bcopy(opdata, &oprep, sizeof(oprep)-16);

oprep.opcode = htons(UDP_RESPONSE);

if(query_bloom(opdata->ip_src.s_addr, opdata->ip_dst.s_addr) >

0) {

oprep.result = htons(UDP_RESPONSE_REC_FOUND);

} else {

oprep.result = htons(UDP_RESPONSE_REC_NOTFOUND);

}

MD5Init(&md5);

MD5Update(&md5, (unsigned char *) &oprep, sizeof(oprep) - 16);

MD5Update(&md5, (unsigned char*) MD5KEY, strlen(MD5KEY));

MD5Final(md5str, &md5);

#ifndef LINUX

sin.sin_len = sizeof(sin);

#endif

sendto(qsocket, &oprep, sizeof(oprep), 0, (struct sockaddr*)

&sin, sizeof(sin));

ret = htons(oprep.result);

fprintf(stderr, "query 0x%08x->0x%08x from %s, ret=%d (%s).\n", ntohl(opdata->ip_src.s_addr),

ntohl(opdata->ip_dst.s_addr),

inet_ntoa(ip->ip_src), ret,

ret==1 ? "found" : (ret==2 ? "not found" : "unknown"));

} } }

/********************/

}

} else if(ip->ip_p==IPPROTO_ICMP) { struct icmp *icmp;

icmp = (struct icmp*) (payload + sizeof(struct ether_header) + ((ip->ip_hl) <<

2));

if(in_cksum((unsigned short *) icmp, sizeof(struct icmp))==0) if(icmp->icmp_type==ICMP_PKTSTAMP) {

char id[24], srcip[24];

MD5Update(&md5, (unsigned char *) icmp, sizeof(struct icmp) - 16);

MD5Update(&md5, (unsigned char*) MD5KEY, strlen(MD5KEY));

MD5Final(md5strx, &md5);

if(memcmp(md5str, md5strx, 16)==0) {

if(icmp->stamper==myid.s_addr) return(0);

snprintf(id, 23, inet_ntoa(rec.stamper));

snprintf(srcip, 23, inet_ntoa(rec.ip_src));

if(noconsole==0)

snprintf(srcip, 23, inet_ntoa(ip->ip_src));

fprintf(stdout, "%10ld.%-6ld %15s -> %-15s\n", hdr->ts.tv_sec, hdr->ts.tv_usec, srcip, inet_ntoa(ip->ip_dst));

#endif

/* add bloom filter here*/

bloom_filter(ip->ip_src.s_addr, ip->ip_dst.s_addr);

if((rand()%probability)==magic)

send_icmp(hdr->ts.tv_sec, hdr->ts.tv_usec, ip->ip_src, ip->ip_dst);

} while(0);

return(0);

}

void

handler(u_char *user, const struct pcap_pkthdr *hdr, const u_char *payload) { unsigned short type = process_ethernet(user, hdr, payload);

if(type == ETHERTYPE_IP) {

process_ip(user, hdr, payload);

} }

void usage(char *progname) {

fprintf(stderr, "usage: %s -i dev -m myid [-l logfile] [-s logsize] [-p prob] [-q port]

[-x]\n"

"\t-i: specify binding device\n"

"\t-m: specify router identifier\n"

"\t-l: specify log filename\n"

"\t-s: specify log filesize (in entries), default = 10000.\n"

"\t-p: specify generating probability, default = 1/1000.\n"

"\t-q: specify udp query port, default = 36100.\n"

"\t-x: no console output\n", progname);

}

int

main(int argc, char *argv[]) { int ch;

char errbuf[PCAP_ERRBUF_SIZE];

char *progname = argv[0];

srand(time(0));

while((ch = getopt(argc, argv, "i:m:s:l:p:q:x"))!=-1) { switch(ch) {

magic = rand() % probability;

break;

case '?':

fprintf(stderr, "error: no device specified.\n");

usage(progname);

return(-1);

}

if(myid.s_addr==0) {

fprintf(stderr, "error: no id specified.\n");

usage(progname);

return(-1);

}

if((p = pcap_open_live(dev, MAXPKTSIZE, 1, 1000, errbuf))==NULL) { fprintf(stderr, "pcap open failed: %s\n", errbuf);

return(-1);

}

if(qport > 0) {

int fl;

struct sockaddr_in sin;

if((qsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) { fprintf(stderr, "socket() failed: %s\n", strerror(errno));

return(-1);

}

bzero(&sin, sizeof(sin));

sin.sin_family = AF_INET;

//sin.sin_addr = myid;

sin.sin_port = htons(qport);

if(bind(qsocket, (struct sockaddr*) &sin, sizeof(sin))==-1) {

fprintf(stderr, "bind() on port %d failed: %s\n", qport, strerror(errno));

return(-1);

}

if((fl = fcntl(qsocket, F_GETFL, NULL))==-1)

fl = 0;

fcntl(qsocket, F_SETFL, fl|O_NONBLOCK);

}

if(logfile) {

struct stamprecord rec;

maxlog = logsize * sizeof(rec);

if((logfp = fopen(logfile, "r+"))==NULL) { if((logfp = fopen(logfile, "w"))==NULL) {

fprintf(stderr, "cannot open logfile\n");

goto exit_icmpd;

} }

fprintf(stderr, "logmax: %d\n", maxlog);

fseek(logfp, 0, SEEK_END);

logpos = ftell(logfp);

if(logpos >= maxlog) {

int len;

long last = 0;

fseek(logfp, 0, SEEK_SET);

while((len = fread(&rec, sizeof(rec), 1, logfp)) > 0) { if(rec.tv_sec <= last)

break;

last = rec.tv_sec;

}

logpos = ftell(logfp);

if(logpos > 0 && logpos < maxlog) logpos -= sizeof(rec);

else

logpos = 0;

fseek(logfp, 0, SEEK_SET);

}

fprintf(stderr, "log: starting from %d\n", logpos/sizeof(rec));

}

#if 0

if(errbuf[0]!='\0')

fprintf(stderr, "warning: %s\n", errbuf);

#endif

fprintf(stderr, "dev=%s id[%s] p=1/%d", dev, inet_ntoa(myid), probability);

if(logfp)

fprintf(stderr, " logfile=%s (max=%d)", logfile, logsize);

fprintf(stderr, "%s.\n", noconsole ? ", console disabled" : "");

if(qport > 0)

fprintf(stderr, "enable query on udp port %d\n", qport);

signal(SIGTERM, cbreak);

pcap_loop(p, -1, handler, NULL);

if(logfp)

fclose(logfp);

exit_icmpd:

pcap_close(p);

return(0);

}

(二):查詢封包真正來源的程式碼 z iquery.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <time.h>

#include <fcntl.h>

#include <sys/types.h>

/* md5 */

#ifdef LINUX

#include <openssl/md5.h>

#else

#include <md5.h>

#endif /* ntohs */

#include <netinet/in.h>

/* inet_ntoa */

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include "icmpd.h"

/* FreeBSD -> Linux */

#ifdef LINUX

#define MD5Init MD5_Init

#define MD5Update MD5_Update

#define MD5Final MD5_Final

#else char*

MD5(unsigned char *input, int len, unsigned char *output) { MD5_CTX md5;

MD5Init(&md5);

MD5Update(&md5, (unsigned char *) input, len);

MD5Final(output, &md5);

return(output);

}

#endif

extern int errno;

#define MAX_STAMPER 32767

#define MAX_TRIES 3

struct stamper {

struct in_addr id;

int count;

};

int totals = 0;

struct stamper all[MAX_STAMPER];

int

id_comp(const void *a, const void *b) { struct stamper *sa, *sb;

sa = (struct stamper*) a;

sb = (struct stamper*) b;

if(sa->id.s_addr == sb->id.s_addr) return(0);

if(sa->id.s_addr > sb->id.s_addr) return(1);

return(-1);

}

int

c_comp(const void *a, const void *b) { struct stamper *sa, *sb;

sa = (struct stamper*) a;

sb = (struct stamper*) b;

if(sa->count== sb->count) return(0);

if(sa->count < sb->count) return(1);

return(-1);

}

void

add_stamper(unsigned int id) { struct stamper *s, tmp;

tmp.id.s_addr = id;

tmp.count = -1;

if((s = bsearch(&tmp, all, totals, sizeof(struct stamper), id_comp))!=NULL) { s->count++;

} else {

if(totals < MAX_STAMPER) {

all[totals].id.s_addr = id;

all[totals].count = 1;

totals++;

qsort(all, totals, sizeof(struct stamper), id_comp);

} else {

fprintf(stderr, "too much stampers.\n");

} } }

void

dump_stamper(int count) {

int i;

qsort(all, totals, sizeof(struct stamper), c_comp);

fprintf(stdout, "+---+---+---+\n"

"| ## | count | stamper |\n"

"+---+---+---+\n");

for(i = 0; i < totals; i++)

fprintf(stdout, "| %5d | %8d | %-15s |\n", i+1, all[i].count, inet_ntoa(all[i].id));

fprintf(stdout, "+---+---+---+\n");

fprintf(stdout, "+ %8d entries parsed. |\n", count);

fprintf(stdout, "+---+\n");

}

int qsocket = -1;

int

do_query(unsigned int ip_src, unsigned int ip_dst, unsigned int target) {

int i;

struct udpop query, response;

struct sockaddr_in sin, rsin;

if(qsocket==-1) {

struct timeval optval;

if((qsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) { fprintf(stderr, "socket() failed: %s\n", strerror(errno));

exit(-1);

}

optval.tv_sec = 5;

optval.tv_usec = 0;

setsockopt(qsocket, SOL_SOCKET, SO_RCVTIMEO, &optval, sizeof(optval));

}

query.signature = htonl(UDP_OP_SIGNATURE);

query.magic = rand() & 0xffffffff;

query.opcode = htons(UDP_QUERY);

query.result = htons(UDP_RESPONSE_NULL);

query.ip_src.s_addr = ip_src;

query.ip_dst.s_addr = ip_dst;

do { /* MD5 */

MD5_CTX md5;

MD5Init(&md5);

MD5Update(&md5, (unsigned char *) &query, sizeof(query)-16);

MD5Update(&md5, (unsigned char*) MD5KEY, strlen(MD5KEY));

MD5Final(query.md5sum, &md5);

} while(0);

bzero(&sin, sizeof(sin));

sin.sin_family = AF_INET;

sin.sin_addr.s_addr = target;

sin.sin_port = htons(UDP_DEFAULT_QUERY_PORT);

#ifndef LINUX

sin.sin_len = sizeof(sin);

#endif

for(i = 0; i < MAX_TRIES; i++) { int slen = sizeof(rsin);

if(sendto(qsocket, &query, sizeof(query), 0, (struct sockaddr*) &sin, sizeof(sin))==-1) {

fprintf(stdout, " txx");

continue;

}

bzero(&rsin, sizeof(rsin));

if(recvfrom(qsocket, &response, sizeof(response), 0, (struct sockaddr*) &rsin,

&slen)==-1) {

fprintf(stdout, " rxx");

continue;

}

if(response.signature==htonl(UDP_OP_SIGNATURE) && response.opcode==ntohs(UDP_RESPONSE)

&& response.magic==query.magic) { return(ntohs(response.result));

} }

return(0);

}

int main(int argc, char *argv[]) { int i, ret, count = 0;

unsigned int ip_src, ip_dst;

char *p, *target = NULL;

struct stamprecord rec;

FILE *fp;

if(argc < 3) {

fprintf(stderr, "usage: %s query-pair logfile|target\n", argv[0]);

return(-1);

}

ip_src = ip_dst = 0;

if((p = strtok(argv[1], ":"))!=NULL) { ip_src = inet_addr(p);

if((p = strtok(NULL, ":"))!=NULL) { ip_dst = inet_addr(p);

fprintf(stderr, "cannot get q-src.\n");

return(-1);

}

if((fp = fopen(argv[2], "r"))==NULL) { target = strdup(argv[2]);

if(inet_addr(target)==INADDR_NONE) {

fprintf(stderr, "'%s' is neigher a file nor an invalid address.\n", argv[2]);

return(-1);

while(fread(&rec, sizeof(rec), 1, fp) > 0) { add_stamper(rec.stamper.s_addr);

count++;

}

fclose(fp);

dump_stamper(count);

srand(time(0));

for(i = 0; i < totals; i++) {

fprintf(stdout, "query %s", inet_ntoa(*((struct in_addr *) &ip_src)));

fprintf(stdout, "->%s from ", inet_ntoa(*((struct in_addr *) &ip_dst)));

fprintf(stdout, "%s ...", inet_ntoa(all[i].id));

if((ret = do_query(ip_src, ip_dst, all[i].id.s_addr)) > 0) { if(ret==UDP_RESPONSE_REC_FOUND)

fprintf(stdout, " [FOUND]\n");

else if(ret==UDP_RESPONSE_REC_NOTFOUND) fprintf(stdout, " [NOT FOUND]\n");

else

fprintf(stdout, " [UNKNOWN]\n");

} else {

fprintf(stdout, " [FAILED]\n");

} }

/***********************************/

} else {

fprintf(stdout, "query 0x%08x->0x%08x from %s ...", ntohl(ip_src), ntohl(ip_dst),

target);

if((ret = do_query(ip_src, ip_dst, inet_addr(target))) > 0) { if(ret==UDP_RESPONSE_REC_FOUND)

fprintf(stdout, " [FOUND]\n");

else if(ret==UDP_RESPONSE_REC_NOTFOUND) fprintf(stdout, " [NOT FOUND]\n");

else

fprintf(stdout, " [UNKNOWN]\n");

} else {

fprintf(stdout, " [FAILED]\n");

} }

fprintf(stdout, "done.\n");

return(0);

}

附錄 B: 分流系統程式原始碼

Packet generator

#include <netinet/ip.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <netinet/tcp.h>

#include <getopt.h>

#include <sys/types.h>

#include <netdb.h>

#include <stdlib.h>

#include <arpa/inet.h>

#include <math.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

inline long getrandom (int, int);

void random_init (void);

unsigned short ip_sum (unsigned short *, int);

unsigned short cksum (unsigned short *, int);

unsigned short checksum (unsigned short *, int);

int isip (char *);

unsigned long resolve (char *);

char rseed[65535];

int rcounter;

int main (int argc, char **argv)

{

unsigned short seqrandom = 1;

unsigned short ackrandom = 1;

unsigned short idrandom =1 ;

unsigned short sportrandom = 1;

unsigned short dportrandom = 1;

u_int16_t urgflag=0x0;

u_int16_t ackflag=0x0;

u_int16_t pshflag=0x0;

u_int16_t rstflag=0x0;

u_int16_t synflag=0x0;

u_int16_t finflag=0x0;

unsigned long count = 1;

unsigned long loop = 0;

unsigned long interval = 200; //200ns

u_int8_t ttl = 0x20;

u_int16_t id = 0x1;

u_int16_t frag = 0x4000; // DF

u_int8_t tos = 0x0;

unsigned long ipsrc = -33511232; // 192.168.0.254

unsigned long ipdst = 184789184; // 192.168.3.11

u_int16_t sport = 1234;

u_int16_t dport = 80;

u_int32_t seq = 0x1;

u_int32_t ack = 0x1020;

int c;

int digit_optind = 0;

unsigned long chsum = 0;

struct sockaddr_in pothead;

struct iphdr *iph;

struct tcphdr *tcph;

int sockfd;

char *packet;

int pktsize = sizeof (struct iphdr) + sizeof (struct tcphdr);

while (1)

{

int this_option_optind = optind ? optind : 1;

int option_index = 0;

static struct option long_options[] = {

{"help", 0, 0, 0},

{"dport", 1, 0, 0},

{"sport", 1, 0, 0},

{"seq", 1, 0, 0},

{"ack", 1, 0, 0},

{"syn", 0, 0, 0},

{"urg", 0, 0, 0},

{"rst", 0, 0, 0},

{"psh", 0, 0, 0},

{"fin", 0, 0, 0},

{0, 0, 0, 0}

};

c = getopt_long (argc, argv, "c:d:f:i:s:p:q:t:v:", long_options, &option_index);

if (c == -1)

break;

switch (c)

{

case 0:

if (strcmp (long_options[option_index].name, "help") == 0)

{

fprintf(stderr,"./transp [--option1] [-option2]\n");

fprintf(stderr,"option1:\n");

fprintf(stderr,"--sport arg : specify the source port\n");

fprintf(stderr,"--dport arg : specify the destination port\n");

fprintf(stderr,"--seq arg : specify the sequence field in TCP header\n");

fprintf(stderr,"--ack arg : specify the acknowledge field in TCP header and enable the ack

flag\n");

fprintf(stderr,"--urg : enable the urg flag in TCP header\n");

fprintf(stderr,"--psh : enable the psh flag in TCP header\n");

fprintf(stderr,"--rst : enable the rst flag in TCP header\n");

fprintf(stderr,"--syn : enable the syn flag in TCP header\n");

fprintf(stderr,"--fin : enable the fin flag in TCP header\n");

fprintf(stderr,"--help arg : you will see this\n");

fprintf(stderr,"option2:\n");

fprintf(stderr,"-c arg : how many packet do you want to transit\n");

fprintf(stderr,"-d arg : specify the destionation IP field in IP header\n");

fprintf(stderr,"-i arg : specify the identificatioin field in IP header\n");

fprintf(stderr,"-s arg : specify the source IP field in IP header\n");

fprintf(stderr,"-p arg : specify the payload length after IP header\n");

fprintf(stderr,"-q [T|R|C] : specify the tos field in IP header\n");

fprintf(stderr," T : stands for max throughput\n");

fprintf(stderr," R : stands for max relibility\n");

fprintf(stderr," C : stands for min cost\n");

fprintf(stderr,"-t arg : specify the ttl field in IP headre\n");

fprintf(stderr,"-v arg : specify the interval of each packet\n");

}

if (strcmp (long_options[option_index].name, "sport") == 0)

{ sport = atoi (optarg);

sportrandom = 0;

}

if (strcmp (long_options[option_index].name, "dport") == 0)

{ dport = atoi (optarg);

dportrandom =0;

}

if (strcmp (long_options[option_index].name, "seq") == 0)

{

seq=atoi (optarg);

seqrandom=0;

}

if (strcmp (long_options[option_index].name, "ack") == 0)

{

ack=atoi(optarg);

ackflag=0x1;

ackrandom=0;

}

if (strcmp (long_options[option_index].name, "syn") == 0)

{

synflag=1;

}

if (strcmp (long_options[option_index].name, "rst") == 0)

{

rstflag=1;

}

if (strcmp (long_options[option_index].name, "psh") == 0)

{

pshflag=1;

}

if (strcmp (long_options[option_index].name, "urg") == 0)

{

urgflag=1;

}

if (strcmp (long_options[option_index].name, "fin") == 0)

{

finflag=1;

}

break;

case 'c':

count = atoi (optarg);

break;

case 'd':

ipdst = resolve (optarg);

break;

case 'f':

if (strncmp (optarg, "R", 1) == 0)

frag = 0x8000;

else if (strncmp (optarg, "D", 1) == 0)

frag = 0x4000;

else if (strncmp (optarg, "M", 1) == 0)

frag = 0x2000;

break;

case 'i':

id = atoi (optarg);

idrandom = 0;

break;

case 's':

ipsrc = resolve (optarg);

break;

case 'p':

pktsize+=atoi(optarg);

break;

case 'q':

if (strncmp (optarg, "D", 1) == 0)

tos = 0x10;

else if (strncmp (optarg, "T", 1) == 0)

tos = 0x08;

else if (strncmp (optarg, "R", 1) == 0)

tos = 0x04;

else if (strncmp (optarg, "C", 1) == 0)

tos = 0x02;

break;

case 't':

ttl = atoi (optarg);

break;

case 'v':

interval = atoi (optarg);

break;

}

}

packet = (char *) malloc (sizeof (char) * pktsize);

sockfd = socket (AF_INET, SOCK_RAW, 255);

iph = (struct iphdr *) (packet);

tcph = (struct tcphdr *) (packet + sizeof (struct iphdr));

memset (packet, 0, pktsize);

iph->version = 4;

iph->ihl = 5;

iph->tos = tos;

iph->tot_len = htons (pktsize);

iph->id = htons (id);

iph->frag_off = htons (frag);

iph->ttl = ttl;

iph->protocol = 0x6;

// iph->saddr = inet_addr ("192.168.0.254");

iph->saddr = ipsrc;

// iph->daddr = inet_addr ("192.168.3.11");

iph->daddr = ipdst;

iph->check = ip_sum ((short int *) &iph, sizeof (iph));

tcph->source = htons (sport);

tcph->dest = htons (dport);

tcph->seq = htonl (seq);

tcph->ack_seq = htonl (ack);

tcph->doff = 5;

tcph->urg=urgflag;

tcph->ack=ackflag;

tcph->psh=pshflag;

tcph->rst=rstflag;

tcph->syn=synflag;

tcph->fin=finflag;

tcph->window = htons (1024);

chsum += htons (tcph->source);

chsum += htons (tcph->dest);

chsum += (short) (htonl (tcph->seq) >> 16);

chsum += (short) (htonl (tcph->seq) & 0x0000ffff);

chsum += (short) (htonl (tcph->ack_seq) >> 16);

chsum += (short) (htonl (tcph->ack_seq) & 0x0000ffff);

chsum += 0x5002;

chsum += htons (tcph->window);

chsum += (short) (htonl (iph->saddr) >> 16);

chsum += (short) (htonl (iph->saddr) & 0x0000ffff);

chsum += (short) (htonl (iph->daddr) >> 16);

chsum += (short) (htonl (iph->daddr) & 0x0000ffff);

chsum += iph->protocol;

chsum += 20;

chsum = (chsum >> 16) + (chsum & 0xffff);

(unsigned short) chsum += (chsum >> 16);

tcph->check = ~htons (chsum) - 512;

pothead.sin_family = AF_INET;

pothead.sin_addr.s_addr = iph->daddr;

setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, "1", sizeof ("1"));

for (loop = 0; loop < count; loop++)

{

if (seqrandom == 1)

tcph->seq = htonl (getrandom(1,65535));

if (ackrandom == 1)

tcph->ack_seq = htonl (getrandom(1,65535));

if (idrandom == 1)

iph->id = htons (getrandom(1,65535));

if (sportrandom==1)

tcph->source = htons (getrandom(1024,65535));

if (dportrandom ==1)

{

dport = getrandom(1,65535);

tcph->dest = htons (dport);

pothead.sin_port = htons (dport);

}

chsum=0;

chsum += htons (tcph->source);

chsum += htons (tcph->dest);

chsum += (short) (htonl (tcph->seq) >> 16);

chsum += (short) (htonl (tcph->seq) & 0x0000ffff);

chsum += (short) (htonl (tcph->ack_seq) >> 16);

chsum += (short) (htonl (tcph->ack_seq) & 0x0000ffff);

chsum += 0x5002;

chsum += htons (tcph->window);

chsum += (short) (htonl (iph->saddr) >> 16);

chsum += (short) (htonl (iph->saddr) & 0x0000ffff);

chsum += (short) (htonl (iph->daddr) >> 16);

chsum += (short) (htonl (iph->daddr) & 0x0000ffff);

chsum += iph->protocol;

chsum += 20;

chsum = (chsum >> 16) + (chsum & 0xffff);

(unsigned short) chsum += (chsum >> 16);

tcph->check = ~htons (chsum) - 512;

usleep (interval);

sendto (sockfd, packet, pktsize, 0, (struct sockaddr_in *)

&pothead,

sizeof (struct sockaddr_in));

}

free (packet);

exit(0);

}

unsigned short

checksum (addr, len)

unsigned short *addr;

int len;

{

register int nleft = len;

register unsigned short *w = addr;

register int sum = 0;

unsigned short answer = 0;

while (nleft > 1)

{

sum += *w++;

nleft -= 2;

}

if (nleft == 1)

{

*(unsigned char *) (&answer) = *(unsigned char *) w;

sum += answer;

}

return (sum);

}

unsigned short

ip_sum (addr, len)

unsigned short *addr;

int len;

{

register int nleft = len;

register unsigned short *w = addr;

register int sum = 0;

unsigned short answer = 0;

while (nleft > 1)

{

sum += *w++;

nleft -= 2;

}

if (nleft == 1)

{

*(unsigned char *) (&answer) = *(unsigned char *) w;

sum += answer;

}

sum = (sum >> 16) + (sum & 0xffff);

sum += (sum >> 16);

answer = ~sum;

return (answer);

}

unsigned short

cksum (unsigned short *buf, int nwords)

{

unsigned long sum;

for (sum = 0; nwords > 0; nwords--)

sum += *buf++;

sum = (sum >> 16) + (sum & 0xffff);

sum += (sum >> 16);

return ~sum;

}

int

isip (char *ip)

{

int a, b, c, d;

sscanf (ip, "%d.%d.%d.%d", &a, &b, &c, &d);

if (a < 0)

return 0;

if (a > 255)

return 0;

if (b < 0)

return 0;

if (b > 255)

return 0;

if (c < 0)

return 0;

if (c > 255)

return 0;

if (d < 0)

return 0;

if (d > 255)

return 0;

return 1;

}

unsigned long

resolve (char *host)

{

struct hostent *he;

struct sockaddr_in tmp;

if (isip (host))

return (inet_addr (host));

he = (struct hostent *) gethostbyname (host);

if (he)

{

memcpy ((caddr_t) & tmp.sin_addr.s_addr, he->h_addr,

he->h_length);

}

else

return (0);

return (tmp.sin_addr.s_addr);

}

void

random_init (void)

{

int rfd = open ("/dev/urandom", O_RDONLY);

if (rfd < 0)

rfd = open ("/dev/random", O_RDONLY);

rcounter = read (rfd, rseed, 65535);

close (rfd);

}

inline

long

getrandom (int min, int max)

{

if (rcounter < 2)

random_init ();

srand (rseed[rcounter] + (rseed[rcounter - 1] << 8));

rcounter -= 2;

return ((random () % (int) (((max) + 1) - (min))) + (min));

}

Monitor

/* monitor.php */

<?php

include("snmpconf.php");

require("xtpl.p");

$xtpl=New XTemplate("monitor.xtpl");

if (!$_COOKIE[loginsession]) {

$xtpl->parse("main.leftmain.login");

$xtpl->parse("main.leftmain");

} else {

if ($_POST["submit"]) {

switch ($_POST["function"]) { case "settime":

$nodetime=exec("/usr/local/snort-2.0.0/bin/nodetime [email protected]");

$settime=exec("/usr/local/snort-2.0.0/bin/settime root@".$_POST[ip]." ".$nodetime);

break;

case "editrule":

$fd=fopen("/usr/local/snort-2.0.0/bin/editrule","w");

fputs($fd,"#!/usr/bin/expect -f\n");

fputs($fd,"spawn ssh [lrange \$argv 0 0] sed \\'\\n");

for($i=0;$name=checkrule.$i,!empty($$name);$i++) {

if (ereg("^#",$$name)==1) fputs($fd,"s/^.*\\\(include

".str_replace('/','\\\/',str_replace('$','\\$',str_replace("#","",$$name)))."\\\)/#\\\\1/\\n");

else

fputs($fd,"s/^.*\\\(include

".str_replace('/','\\\/',str_replace('$','\\$',$$name))."\\\)/\\\\1/\\n");

}

fputs($fd,"\\' /usr/local/snort-2.0.0/bin/snort.conf >

/usr/local/snort-2.0.0/bin/snort.try\\;command cp /usr/local/snort-2.0.0/bin/snort.try /usr/local/snort-2.0.0/bin/snort.conf\nexpect {\nAre {\nsend

\"yes\\r\"\nexp_continue\n}\nroot@\n{send \"east1121\\r\"}\n}\nexpect root\nexit\n");

fclose($fd);

chmod("/usr/local/snort-2.0.0/bin/editrule",0770);

exec("/usr/local/snort-2.0.0/bin/editrule root@".$_GET[ip]);

exec("/usr/local/snort-2.0.0/bin/restartsnort root@".$_GET[ip]);

break;

case "start":

$snortstate=exec("/usr/local/snort-2.0.0/bin/snortstate root@".$_GET[ip]);

if (ereg("\/snort",$snortstate)>0)

$xtpl->assign(SNORTSTATE,$snortstate."...");

else

exec("/usr/local/snort-2.0.0/bin/startsnort root@".$_GET[ip]);

break;

} }

$xtpl->parse("main.leftmain.logout");

$menu[0][menuname]="test1";

$menu[1][menuname]="manage";

$menu[2][menuname]="time";

$menu[2][menuname]="time";

相關文件