RELATEED CONSULTING
相关咨询
选择下列产品马上在线沟通
服务时间:9:30-18:00
你可能遇到了下面的问题
关闭右侧工具栏
[CODE] tcpserver完整的patch
  • 作者:xiaoxiao
  • 发表时间:2020-12-23 11:00
  • 来源:未知

可不是我一个人的,呵呵!首先是 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 <sys/param.h> #include <netdb.h> #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; j<MAX_IP_TIME; j++) { + piptime = &iptimebuf[j]; + if(!empty_iptime) { + if( !piptime->ipaddr || 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;i<limit;++i) + if (children[i].pid == pid) { + children[i].pid=0; + numipchildren[children[i].offset].num--; + break; + } } } @@ -300,10 +464,12 @@ int s; int t; - while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof) + while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:s:f:pPoO")) != opteof) switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; + case 's': scan_ulong(optarg,&periplimit); break; + case 'f': scan_ulong(optarg,&max_freq);break; case 'X': flagallownorules = 1; break; case 'x': fnrules = optarg; break; case 'B': banner = optarg; break; @@ -334,6 +500,11 @@ if (!verbosity) buffer_2->fd = -1; + + if (!periplimit) + periplimit = limit; + if (limit<periplimit) + strerr_die2x(111,FATAL,"periplimit must be smaller than or equal to connection limit"); hostname = *argv++; if (!hostname) usage(); @@ -358,6 +529,13 @@ sig_catch(sig_term,sigterm); sig_ignore(sig_pipe); + if (!(numipchildren = (ipchildren*)malloc(sizeof(ipchildren)*limit))) + strerr_die2x(111,FATAL,"out of memory"); + byte_zero(numipchildren,sizeof(ipchildren)*limit); + if (!(children = (connections*)malloc(sizeof(connections)*limit))) + strerr_die2x(111,FATAL,"out of memory"); + byte_zero(children,sizeof(connections)*limit); + byte_zero(iptimebuf,sizeof(iptime)*MAX_IP_TIME); if (!stralloc_copys(&tmp,hostname)) strerr_die2x(111,FATAL,"out of memory"); if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1) @@ -390,12 +568,23 @@ buffer_puts(&b,"/n"); buffer_flush(&b); } + + initfreeip(); + + dumpfreeip(); close(0); close(1); printstatus(); for (;;) { + uint32 ipaddr; + pid_t pid; + int i; + int lastempty = 0; + int freechild = 0; + ipchildren *ipcount; + while (numchildren >= limit) sig_pause(); sig_unblock(sig_child); @@ -403,9 +592,53 @@ sig_block(sig_child); if (t == -1) continue; + + for (i=0;i<limit;++i) { + if (children[i].pid == 0) { + freechild = i; + break; + } + } + uint32_unpack(remoteip,&ipaddr); + for (i=0;i<limit;++i) { + ipcount = &numipchildren[i]; + if (!ipcount->ipaddr || !ipcount->num) + 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); }