Commit Diff


commit - 20d002e155fdd370fc86f715f884963f803c9d60
commit + 2981fe9eb707b340107b5131018805ee2a469950
blob - 904d609aabdef6b67ce2a4198534ec7f4962afba
blob + 7e173e3c56bb12f1e43a0b492568d055a6e9b450
--- ChangeLog
+++ ChangeLog
@@ -12,6 +12,10 @@
 
 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 $
blob - c55b2b4eb6f52c94bbcfa8ec2f37ecdd028faae5
blob + 20f861c52eb7e8e69825d35be05b996507f7b333
--- NEWS
+++ NEWS
@@ -12,6 +12,10 @@
 
 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 $
blob - 354b54efa7b3fa8cf2789fe9af911023138f1062
blob + 0e4439309a9c16c7e9519a471c916d8ba7096df4
--- doc/sample-ngircd.conf
+++ doc/sample-ngircd.conf
@@ -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
@@ -76,6 +76,10 @@
 	# 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
blob - 773287a7ee09fb43c0e995a1dfab77f38b448389
blob + d1cf47e2d60a24a006b0f9d36ee3ea90783a1876
--- man/ngircd.conf.5
+++ man/ngircd.conf.5
@@ -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.
blob - 0abb3c81531c40d791cef63ddc41113f3b1d2b1f
blob + d17168c3348e731c75433478947f91084beb8f3a
--- src/ngircd/conf.c
+++ src/ngircd/conf.c
@@ -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 );
blob - 15a7093d433bb08b7033ab2135fdbf691fd47c5c
blob + b900610b71fa838627e413a3c3bda680cf4ec668
--- src/ngircd/conf.h
+++ src/ngircd/conf.h
@@ -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,7 +110,10 @@ 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 ));
 GLOBAL INT Conf_Test PARAMS((VOID ));
blob - 56824594e98fc22629b26f8296663b796ba78fb0
blob + 2c65f26e1f52204cffd87e16b60407d482326c6c
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
@@ -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;
@@ -1597,6 +1609,20 @@ Simple_Message( INT Sock, CHAR *Msg )
 	(VOID)send( Sock, Msg, strlen( Msg ), 0 );
 	(VOID)send( Sock, "\r\n", 2, 0 );
 } /* 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- */