可不是我一个人的,呵呵!首先是 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 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 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;iipaddr || !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);
}
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: