1. Limitations of the same IP maximum connection
use
BALAZS NAGY's Periplimit Patch implements the limit of the maximum number of connections for the same IP.
Related address:
http://js.hu/package/ucspi-tcp/
Implementation: UCSPI-TCP-0.88-periplimit.6.patch
Diff -ru ucspi-TCP-0.88-Orig / Makefile UCSPI-TCP-0.88 / Makefile
--- UCSPI-TCP-0.88-ORIG / MAKEFILE SAT Mar 18 16:18:42 2000
UCSPI-TCP-0.88 / makefile fri may 28 06:48:15 2004
@@ -753, 7 753 ,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 ipause.h TAIA.H TAI.H uint64.h /
-taia.h
TAIA.H uint32.h
./compile tcpserver.c
Time.a: /
Diff -ru ucspi-tcp-0.88-orig / tcpserver.c ucspi-TCP-0.88 / TCPSERVER.C
--- UCSPI-TCP-0.88-ORIG / TCPSERVER.C Sat Mar 18 16:18:42 2000
UCSPI-TCP-0.88 / TCPSERVER.C THU JUL 1 08:37:03 2004
@@ -2, 6 2,7 @@
#include
#include
#include "uint16.h"
# include "uint32.h"
#include "str.h"
#include "byte.h"
#include "fmt.h"
@@ -242, 6 243 ,7 @@
TCPSERVER: USAGE: TCPSERVER /
[-1uxphhrrooddqv] /
[-c limited] /
[-S Perip Limit] /
[-x rules.cdb] /
[-B banner] /
[-g gid] /
@@ -254, 8 256, 24 @@
}
UNSIGNED long limit = 40;
unsigned long periplimit = 0;
Unsigned long NumChildren = 0;
TypedEf struct
{
PID_T PID;
int offset
CONNECTIONS;
TypedEf struct
{
uint32 ipaddr;
unsigned long Num;
ipchildren;
Connections * Children;
IPCHILDREN * NUMIPCHILDREN
INT FLAG1 = 0;
Unsigned long backlog = 20; unsigned long uid = 0;
@@ -278, 6 296 ,7 @@
{
Int Wstat;
int PI;
INT I;
While ((PID = Wait_nohang (& Wstat))> 0) {
IF (verbosity> = 2) {
@@ -286, 6 305, 12 @@
STRERR_WARN4 ("TCPSERVER: END", Strnum, "Status", Strnum2,0);
}
IF (NumChildren) --NumChildren; PrintStatus ();
for (i = 0; i IF (Children [i] .pid == PID) { Children [i] .PID = 0; NumipChildren [Children [i] .offset] .num-- Break; } } } @@ -300, 10 325 ,11 @@ Int S; Int T; - while ((Opt = getopt (Argc, Argv, "DDVQqHrr1uxx: T: u: g: l: B: B: C: PPO"))! = opteof) while ((OPT = Getopt (Argc, Argv, "DDVQqHrr1uxx: T: u: g: l: B: B: C: S: PPO"))! = 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 'x': flagallownorules = 1; Break; Case 'x': fnRules = OPTARG; Break; Case 'b': banner = OPTARG; Break; @@ -334, 6 360 ,11 @@ IF (! Verbosit) Buffer_2-> fd = -1; IF (! periplimit) periplimit = limited; IF (Limit STRERR_DIE2X (111, Fatal, "Periplimit Must Be Smaller Tan Or Equal To Connection Limit); Hostname = * Argv ; if (! Hostname) USAGE (); @@ -358, 6 389 ,11 @@ SIG_CATCH (SIG_TERM, SIGTERM); SIG_IGNORE (SIG_PIPE); IF (! (ipchildren = (ipchildren *) malloc (ipchildren * limited))) STRERR_DIE2X (111, Fatal, "Out of Memory"); Byte_zero (NumipChildren, Sizeof (IPCHildren); IF (! (CHILDREN = (Connections *) Malloc (SIZEOF (CONNEOF (Connections) * Limit)))) STRERR_DIE2X (111, Fatal, "Out of Memory); IF (! stalloc_copys (& tmp, hostname)) STRERR_DIE2X (111, Fatal, "Out of Memory"; IF (DNS_IP4_QUALIFY (& Addresses, & FQDN, & TMP) == -1) @@ -396, 6 432, 13 @@ 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 4446, 43 @@ SIG_BLOCK (SIG_CHILD); IF (t == -1) Continue; for (i = 0; i IF (Children [i] .pid == 0) { freeChild = i; Break; } } uint32_unpack (remoteip, & ipaddr); for (i = 0; i ipcount = & numipchildren [i]; IF (! ipcount-> ipaddr ||! ipcount-> num) lastempty = i; Else if (ipcount-> ipaddr == ipaddr) { ipcount-> num; Break; } } IF (i == limited) { 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) { RemoteIPSTR [IP4_FMT (Remoteipstr, Remoteip)] = 0; STRERR_WARN3 (Drop, "Per IP Limit Reached For", Remoteipstr, 0); Close (T); - - IPCOUNT-> NUM; Continue; } NumChildren; PrintStatus (); - Switch (fork ()) { Switch (pid = for ()) { Case 0: Close (s); DOIT (T); @@ -420, 6 497, 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); } 2. Modify the Periplimit Patch to achieve unrestricted IP addresses (Implementation: myhan) The above PATCH is limited to all IP addresses, but when we are in use, there are often some IP addresses, such as 127.0.0.1 or native address, and do not want to be restricted. By setting the control file, you can implement an unrestricted IP address from the control file. Control file location: / var / qmail / control / freeip Control file format: Each line a complete IP address 3. Realize the limitations of the connection frequency of the same IP (Implementation: QFTANG) Implementation of 2 and 3: UCSPI-TCP-0.88-FrequencyLimit.1.patch --- TCPSERVER.C.1.2 2004-08-13 16: 50: 41.000000000 0800 TCPSERVER.C 2004-08-17 16: 11: 59.000000000 0800 @@ -28, 6 28 ,7 @@ #include "rules.h" #include "sig.h" #include "dns.h" # include INT verbosity = 1; INT flagkillopts = 1; @@ -236, 6 237 ,7 @@ / * ---------------------------- Parent * / #define fatal "TCPSERVER: FATAL:" # define max_ip_time 4096 Void Usage (Void) { @@ -244, 6 246, 7 @@ [-1uxphhrrooddqv] / [-c limited] / [-s perip limited] / [-f Max Connection Per IP in One Minite] / [-x rules.cdb] / [-B banner] / [-g gid] / @@ -258, 6 261, 7 @@ UNSIGNED long limit = 40; Unsigned long periplimit = 0; Unsigned long NumChildren = 0; unsigned long max_freq = 20; Typedef struct { @@ -271, 14 275, 143 @@ 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 * head = null; freeip * tail = null; CHAR TEMPIP [4]; CHAR BUF [256] = {0}; File * fp; if (! (! (freeip *) Malloc (Sizeof (FreeIP))))))))))) STRERR_DIE2X (111, Fatal, "Out of Memory); IF (! (freeip *) Malloc (SizeOf (FreeIP)))))))))))) STRERR_DIE2X (111, Fatal, "Out of Memory); UINT32_UNPACK (localip, & head-> ipaddr); Head-> Num = 100; Head-> next = null; IF (IP4_scan ("127.0.0.1", Tempip) { uint32_unpack (tempip, & tail-> ipaddr); TAIL-> NUM = 100; TAIL-> next = null; Head-> next = tail; } fp = fopen ("/ var / qmail / control / freeip", "r"); if (! fp) { freeiplist = head; return } While (FGETS (BUF, 256, FP)) { freeip * new; IF (iP4_scan (buf, tempip)) { New = (freeip *) Malloc (SizeOf (FreeIP)); uint32_unpack (tempip, & new-> ipaddr); new-> Num = 100; new-> next = NULL; TAIL-> Next = New; TAIL = Tail-> Next; } else { Continue; } } freeiplist = head; } 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; 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 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; @@ -325, 11 458, 12 @@ Int S; Int T; - While ((Opt = getopt (Argc, Argv, "DDVQHHRR1UXX: T: u: g: L: B: B: C: S: PPO")))! = opteof) while ((OPT = Getopt (Argc, Argv, "DDVQqHrr1uxx: T: u: g: l: B: B: C: S: f: PPO"))! = 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; @@ -394, 6 528, 8 @@ BYTE_ZERO (NumipChildren, Sizeof (IPCHildren); IF (! (CHILDREN = (Connections *)))) STRERR_DIE2X (111, Fatal, "Out of Memory"); BYTE_ZERO (Children, Sizeof (Connections) * Limit; Byte_zero (iptimebuf, sizeof (iptime) * max_ip_time); IF (! stalloc_copys (& tmp, hostname)) STRERR_DIE2X (111, Fatal, "Out of Memory"; IF (DNS_IP4_QUALIFY (& Addresses, & FQDN, & TMP) == -1) @@ -426, 6 562, 10 @@ Buffer_puts (& B, "/ N"); Buffer_flush (& B); } InitFreeip (); dumpfreeip (); CLOSE (0); Close (1); @@ -473, 13 613, 23 @@ / * NEVER Reached * / STRERR_DIE2X (111, DROP, "Internal Problem); } - IF (ipcount-> num> periplimit) { // 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 (PID = for ()) { 4. Test tool :) TCPSerTester.php #! / usr / local / bin / php -f PHP Error_Reporting (0); SET_TIME_LIMIT (6000); $ KeepConnect = FALSE; For ($ I = 0; $ I <50; $ i ) { $ fd = "fp_". $ i; // $$ fd = fsockopen ("Localhost", 110, $ Errno, $ Errstr, 30); $$ fd = fsockopen ("172.18.37", 110, $ errno, $ Errstr, 30); IF ($ FD === false) {Printf ("NO.% 2D: [Error] ErrorNO:% D, ErrorInfo:% S / N", $ I 1, $ Errno, $ Errstr); } else { Printf ("NO.% 2D: Connect Success! / N", $ I 1); $ BUF = FGETS ($$ FD, 1024); IF (Substr ($ BUF, 0, 3) == ' OK') { Printf ("/ TS:% S", $ BUF); IF ($ KeepConnect) { FWRITE ($ FD, "QUIT / R / N"); Printf ("/ tc: quit / n"); $ reply = fgets ($$ FD, 1024); Printf ("/ ts:% s", $ reply); Fclose ($ FD); Printf ("/ tconnection closed / n"); } Printf ("/ Tsleep 10 Seconds / N); Sleep (10); } else { Printf ("/ tService is not available! / n"); IF ($ KeepConnect) { Fclose ($ FD); Printf ("/ tconnection closed / n"); } Printf ("/ tsleep 15 seconds / n"); Sleep (15); } } } IF ($ KeepConnect) { Sleep (1000); } ?>