New configuration option "MaxConnectionsIP".
authorAlexander Barton <alex@barton.de>
Wed, 5 Nov 2003 21:41:01 +0000 (21:41 +0000)
committerAlexander Barton <alex@barton.de>
Wed, 5 Nov 2003 21:41:01 +0000 (21:41 +0000)
ChangeLog
NEWS
doc/sample-ngircd.conf
man/ngircd.conf.5
src/ngircd/conf.c
src/ngircd/conf.h
src/ngircd/conn.c

index 904d609aabdef6b67ce2a4198534ec7f4962afba..7e173e3c56bb12f1e43a0b492568d055a6e9b450 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
 ngIRCd CVS-HEAD
 
+  - New configuration variable "MaxConnectionsIP" to limit the number of
+    simultaneous connections from a single IP that the server will accept.
+    This configuration options lowers the risk of denial of service attacks
+    (DoS), the default is 5 connections per client IP.
   - Fixed build problems under Mac OS X 10.3.
   - Use "-pipe" when compiling with gcc, speeds things up a little :-)
   - Added new configuration variable "Listen" to bind all listening
@@ -468,4 +472,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: ChangeLog,v 1.213 2003/11/04 00:41:06 alex Exp $
+$Id: ChangeLog,v 1.214 2003/11/05 21:41:01 alex Exp $
diff --git a/NEWS b/NEWS
index c55b2b4eb6f52c94bbcfa8ec2f37ecdd028faae5..20f861c52eb7e8e69825d35be05b996507f7b333 100644 (file)
--- a/NEWS
+++ b/NEWS
 
 ngIRCd CVS-HEAD
 
+  - New configuration variable "MaxConnectionsIP" to limit the number of
+    simultaneous connections from a single IP that the server will accept.
+    This configuration options lowers the risk of denial of service attacks
+    (DoS), the default is 5 connections per client IP.
   - Added new configuration variable "Listen" to bind all listening
     sockets of the server to a single IP address.
        
@@ -170,4 +174,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: NEWS,v 1.58 2003/09/11 12:05:28 alex Exp $
+$Id: NEWS,v 1.59 2003/11/05 21:41:01 alex Exp $
index 354b54efa7b3fa8cf2789fe9af911023138f1062..0e4439309a9c16c7e9519a471c916d8ba7096df4 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: sample-ngircd.conf,v 1.23 2003/09/11 12:05:28 alex Exp $
+# $Id: sample-ngircd.conf,v 1.24 2003/11/05 21:41:02 alex Exp $
 
 #
 # This is a sample configuration file for the ngIRCd, which must adept to
        # Maximum number of simultaneous connection the server is allowed
        # to accept (<=0: unlimited):
        ;MaxConnections = -1
+       
+       # Maximum number of simultaneous connections from a single IP address
+       # the server will accept (<=0: unlimited):
+       ;MaxConnectionsIP = 5
 
        # Maximum number of channels a user can be member of (<=0: no limit):
        ;MaxJoins = 10
index 773287a7ee09fb43c0e995a1dfab77f38b448389..d1cf47e2d60a24a006b0f9d36ee3ea90783a1876 100644 (file)
@@ -1,5 +1,5 @@
 .\"
-.\" $Id: ngircd.conf.5,v 1.11 2003/09/11 12:05:28 alex Exp $
+.\" $Id: ngircd.conf.5,v 1.12 2003/11/05 21:41:02 alex Exp $
 .\"
 .TH ngircd.conf 5 "Mai 2003" ngircd "ngIRCd Manual"
 .SH NAME
@@ -118,6 +118,11 @@ not(!) channel-operators? Default: no.
 Maximum number of simultaneous connection the server is allowed to accept
 (<=0: unlimited). Default: -1.
 .TP
+\fBMaxConnectionsIP\fR
+Maximum number of simultaneous connections from a single IP address that
+the server will accept (<=0: unlimited). This configuration options lowers
+the risk of denial of service attacks (DoS). Default: 5.
+.TP
 \fBMaxJoins\fR
 Maximum number of channels a user can be member of (<=0: no limit).
 Default: 10.
index 0abb3c81531c40d791cef63ddc41113f3b1d2b1f..d17168c3348e731c75433478947f91084beb8f3a 100644 (file)
@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: conf.c,v 1.60 2003/09/11 12:05:28 alex Exp $";
+static char UNUSED id[] = "$Id: conf.c,v 1.61 2003/11/05 21:41:02 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -133,6 +133,8 @@ Conf_Test( VOID )
        printf( "  OperCanUseMode = %s\n", Conf_OperCanMode == TRUE ? "yes" : "no" );
        if( Conf_MaxConnections > 0 ) printf( "  MaxConnections = %ld\n", Conf_MaxConnections );
        else printf( "  MaxConnections = -1\n" );
+       if( Conf_MaxConnectionsIP > 0 ) printf( "  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP );
+       else printf( "  MaxConnectionsIP = -1\n" );
        if( Conf_MaxJoins > 0 ) printf( "  MaxJoins = %d\n", Conf_MaxJoins );
        else printf( "  MaxJoins = -1\n" );
        puts( "" );
@@ -356,6 +358,7 @@ Set_Defaults( BOOLEAN InitServers )
        Conf_OperCanMode = FALSE;
        
        Conf_MaxConnections = -1;
+       Conf_MaxConnectionsIP = 5;
        Conf_MaxJoins = 10;
 
        /* Initialize server configuration structures */
@@ -691,6 +694,16 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
                Conf_MaxConnections = atol( Arg );
                return;
        }
+       if( strcasecmp( Var, "MaxConnectionsIP" ) == 0 )
+       {
+               /* Maximum number of simoultanous connections from one IP. Values <= 0 are equal to "no limit". */
+#ifdef HAVE_ISDIGIT
+               if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MaxConnectionsIP\" is not a number!", NGIRCd_ConfFile, Line );
+               else
+#endif
+               Conf_MaxConnectionsIP = atoi( Arg );
+               return;
+       }
        if( strcasecmp( Var, "MaxJoins" ) == 0 )
        {
                /* Maximum number of channels a user can join. Values <= 0 are equal to "no limit". */
@@ -707,8 +720,8 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
                if( strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress )) >= sizeof( Conf_ListenAddress ))
                {
                        Config_Error( LOG_WARNING, "%s, line %d: Value of \"Listen\" too long!", NGIRCd_ConfFile, Line );
-                       return;
                }
+               return;
        }
 
        Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!", NGIRCd_ConfFile, Line, Var );
index 15a7093d433bb08b7033ab2135fdbf691fd47c5c..b900610b71fa838627e413a3c3bda680cf4ec668 100644 (file)
@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: conf.h,v 1.27 2003/09/11 12:05:28 alex Exp $
+ * $Id: conf.h,v 1.28 2003/11/05 21:41:02 alex Exp $
  *
  * Configuration management (header)
  */
@@ -110,6 +110,9 @@ GLOBAL LONG Conf_MaxConnections;
 /* Maximum number of channels a user can join */
 GLOBAL INT Conf_MaxJoins;
 
+/* Maximum number of connections per IP address */
+GLOBAL INT Conf_MaxConnectionsIP;
+
 
 GLOBAL VOID Conf_Init PARAMS((VOID ));
 GLOBAL VOID Conf_Rehash PARAMS((VOID ));
index 56824594e98fc22629b26f8296663b796ba78fb0..2c65f26e1f52204cffd87e16b60407d482326c6c 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: conn.c,v 1.125 2003/09/11 12:05:28 alex Exp $";
+static char UNUSED id[] = "$Id: conn.c,v 1.126 2003/11/05 21:41:02 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -87,6 +87,7 @@ LOCAL BOOLEAN Init_Socket PARAMS(( INT Sock ));
 LOCAL VOID New_Server PARAMS(( INT Server, CONN_ID Idx ));
 LOCAL VOID Read_Resolver_Result PARAMS(( INT r_fd ));
 LOCAL VOID Simple_Message PARAMS(( INT Sock, CHAR *Msg ));
+LOCAL INT Count_Connections PARAMS(( struct sockaddr_in addr ));
 
 LOCAL fd_set My_Listeners;
 LOCAL fd_set My_Sockets;
@@ -904,7 +905,7 @@ New_Connection( INT Sock )
        CONN_ID idx;
        CLIENT *c;
        POINTER *ptr;
-       LONG new_size;
+       LONG new_size, cnt;
 
        assert( Sock > NONE );
 
@@ -932,6 +933,17 @@ New_Connection( INT Sock )
 
        /* Socket initialisieren */
        Init_Socket( new_sock );
+       
+       /* Check IP-based connection limit */
+       cnt = Count_Connections( new_addr );
+       if(( Conf_MaxConnectionsIP > 0 ) && ( cnt >= Conf_MaxConnectionsIP ))
+       {
+               /* Access denied, too many connections from this IP! */
+               Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP!", inet_ntoa( new_addr.sin_addr ), cnt);
+               Simple_Message( new_sock, "ERROR :Connection refused, too many connections from your IP!" );
+               close( new_sock );
+               return;
+       }
 
        /* Freie Connection-Struktur suchen */
        for( idx = 0; idx < Pool_Size; idx++ ) if( My_Connections[idx].sock == NONE ) break;
@@ -1599,4 +1611,18 @@ Simple_Message( INT Sock, CHAR *Msg )
 } /* Simple_Error */
 
 
+LOCAL INT
+Count_Connections( struct sockaddr_in addr_in )
+{
+       INT i, cnt;
+       
+       cnt = 0;
+       for( i = 0; i < Pool_Size; i++ )
+       {
+               if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].addr.sin_addr.s_addr == addr_in.sin_addr.s_addr )) cnt++;
+       }
+       return cnt;
+} /* Count_Connections */
+
+
 /* -eof- */