可不是我一个人的,呵呵!首先是 Balazs Nagy 和他的 ucspi-tcp-0.88-periplimit.6.patch ; 然后是 qftang 和他的 frequencylimit 的 patch, 偶只是把这些弄到一起哦!
patch: ucspi-tcp-0.88-periplimit.6-frequencylimit.1.patch.txt
cvs diff -u -r1.1 tcpserver.c Index: tcpserver.c =================================================================== RCS file: /home/cvs/ucspi-tcp/tcpserver.c,v retrieving revision 1.1 diff -u -r1.1 tcpserver.c --- tcpserver.c 11 Jul 2004 09:09:21 -0000 1.1 +++ tcpserver.c 18 Aug 2004 09:24:52 -0000 @@ -2,6 +2,7 @@ #include #include #include "uint16.h" +#include "uint32.h" #include "str.h" #include "byte.h" #include "fmt.h" @@ -27,6 +28,7 @@ #include "rules.h" #include "sig.h" #include "dns.h" +#include <stdio.h> int verbosity = 1; int flagkillopts = 1; @@ -235,6 +237,7 @@ /* ---------------------------- parent */ #define FATAL "tcpserver: fatal: " +#define MAX_IP_TIME 4096 void usage(void) { @@ -242,6 +245,8 @@ tcpserver: usage: tcpserver \ [ -1UXpPhHrRoOdDqQv ] \ [ -c limit ] \ +[ -s perip limit ] \ +[ -f max connection per ip in one minite ] \ [ -x rules.cdb ] \ [ -B banner ] \ [ -g gid ] \ @@ -254,13 +259,165 @@ } unsigned long limit = 40; +unsigned long periplimit = 0; unsigned long numchildren = 0; +unsigned long max_freq = 20; + +typedef struct +{ + pid_t pid; + int offset; +} connections; + +typedef struct +{ + uint32 ipaddr; + unsigned long num; +} ipchildren; + +typedef struct freeip_t +{ + char ip[4]; + uint32 ipaddr; + unsigned long num; + struct freeip_t *next; +} freeip; + +typedef struct +{ + uint32 ipaddr; + unsigned long time; +} iptime; + + +connections *children; +ipchildren *numipchildren; +freeip *freeiplist = NULL; +iptime iptimebuf[MAX_IP_TIME]; int flag1 = 0; unsigned long backlog = 20; unsigned long uid = 0; unsigned long gid = 0; +void initfreeip(void) +{ + freeip *tail = NULL; + freeip *new = NULL; + char tempip[4]; + uint32 tempaddr; + char buf[BUFSIZ] = {0}; + FILE *fp; + + if (!(tail = (freeip *)malloc(sizeof(freeip)))) + strerr_die2x(111,FATAL,"out of memory"); + + uint32_unpack(localip, &tail->ipaddr); + tail->num = 100; + tail->next = NULL; + freeiplist = tail; + + if (!(new = (freeip *)malloc(sizeof(freeip)))) + strerr_die2x(111,FATAL,"out of memory"); + + if (ip4_scan("127.0.0.1", tempip)) { + uint32_unpack(tempip, &new->ipaddr); + new->num = 100; + new->next = NULL; + tail->next = new; + tail = tail->next; + } + + fp = fopen("/var/qmail/control/freeip", "r"); + if (!fp) { + strerr_die2x(111,FATAL,"can not read control file: /var/qmail/control/freeip"); + } + + while (fgets(buf, BUFSIZ, fp)) { + if (ip4_scan(buf, tempip)) { + uint32_unpack(tempip, &tempaddr); + if (isfreeip(tempaddr)) + continue; + + if (!(new = (freeip *)malloc(sizeof(freeip)))) + strerr_die2x(111,FATAL,"out of memory"); + + new->ipaddr = tempaddr; + new->num = 100; + new->next = NULL; + tail->next = new; + tail = tail->next; + } + } +} + +void dumpfreeip(void) +{ + freeip *temp = freeiplist; + char tempip[4]; + char ipstr[IP4_FMT]; + char buf[256] = {0}; + do { + uint32_pack(tempip, temp->ipaddr); + ipstr[ip4_fmt(ipstr, tempip)] = 0; + sprintf (buf, "freeip: %s, num: %d\n", ipstr, temp->num); + write(2, buf, strlen(buf)); + temp = temp->next; + } while (temp); +} + +int isfreeip(uint32 ipaddr) +{ + freeip *temp = freeiplist; + int isfree = 0; + + do { + if (temp->ipaddr == ipaddr) { + isfree = 1; + temp = NULL; + break; + } + temp = temp->next; + } while (temp); + return isfree; +} + +void freefreeip(void) +{ +} + +int isoverfrequency(uint32 ipaddr) +{ + iptime *empty_iptime = NULL; + iptime *piptime = NULL; + time_t now = time(0); + int j; + int count = 0; + int emp_pos = 0; + + for(j=0; jipaddr || piptime->time < (now - 60)) { + empty_iptime = piptime; + emp_pos = j; + } + } + if(piptime->ipaddr == ipaddr && piptime->time > (now - 60)) { + count ++; + if(empty_iptime && count >= max_freq) + break; + } + } + + if (!empty_iptime) empty_iptime = &iptimebuf[0]; + + empty_iptime->ipaddr = ipaddr; + empty_iptime->time = now; + + return (count >= max_freq) ? 1 : 0; +} + void printstatus(void) { if (verbosity < 2) return; @@ -278,6 +435,7 @@ { int wstat; int pid; + int i; while ((pid = wait_nohang(&wstat)) > 0) { if (verbosity >= 2) { @@ -286,6 +444,12 @@ strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0); } if (numchildren) --numchildren; printstatus(); + for (i=0;ifd = -1; + + if (!periplimit) + periplimit = limit; + if (limit
= limit) sig_pause(); sig_unblock(sig_child); @@ -403,9 +592,53 @@ sig_block(sig_child); if (t == -1) continue; + + for (i=0;inum) + lastempty = i; + else if (ipcount->ipaddr == ipaddr) { + ++ipcount->num; + break; + } + } + if (i == limit) { + if (lastempty) { + i = lastempty; + ipcount = &numipchildren[i]; + ipcount->ipaddr = ipaddr; + ipcount->num = 1; + } else + /* never reached */ + strerr_die2x(111,DROP,"internal problem"); + } + //if (ipcount->num > periplimit) { + if (!isfreeip(ipaddr) && (ipcount->num > periplimit)) { + remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; + strerr_warn3(DROP, "per ip limit reached for ", remoteipstr, 0); + close(t); + --ipcount->num; + continue; + } + + if (isoverfrequency(ipaddr)) { + remoteipstr[ip4_fmt(remoteipstr, remoteip)] = 0; + strerr_warn3(DROP, "frequency limit reached for ", remoteipstr, 0); + close(t); + continue; + } + + ++numchildren; printstatus(); - switch(fork()) { + switch(pid = fork()) { case 0: close(s); doit(t); @@ -420,6 +653,10 @@ case -1: strerr_warn2(DROP,"unable to fork: ",&strerr_sys); --numchildren; printstatus(); + break; + default: + children[freechild].pid = pid; + children[freechild].offset = i; } close(t); }
patch: Makefile
diff -u -r1.2 -r1.3 --- Makefile 19 Jul 2004 09:12:09 -0000 1.2 +++ Makefile 9 Aug 2004 08:06:06 -0000 1.3 @@ -757,7 +757,7 @@ alloc.h buffer.h error.h strerr.h sgetopt.h subgetopt.h pathexec.h \ socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h \ stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h \ -taia.h +taia.h uint32.h ./compile tcpserver.c time.a: \
本文地址:http://com.8s8s.com/it/it28503.htm