Package: xinetd Version: 2.3.14-7 Severity: wishlist Tags: patch
I wanted options cpm, cph (connections per minute and per hour), to better protect services like telnet and ssh where the "normal" turnaround time is several seconds (so cps is useless). The patch below may implement these. This includes the patch for bug#523956. Cheers, Paul Szabo p...@maths.usyd.edu.au http://www.maths.usyd.edu.au/u/psz/ School of Mathematics and Statistics University of Sydney Australia --- xinetd-2.3.14/xinetd/access.c.ORIG 2005-10-06 03:15:33.000000000 +1000 +++ xinetd-2.3.14/xinetd/access.c 2009-04-15 12:11:32.000000000 +1000 @@ -62,6 +62,8 @@ { "libwrap", (int) AC_LIBWRAP }, { "load", (int) AC_LOAD }, { "connections per second", (int) AC_CPS }, + { "connections per minute", (int) AC_CPM }, + { "connections per hour", (int) AC_CPH }, { CHAR_NULL, 1 }, { "UNKNOWN", 0 } } ; @@ -113,6 +115,54 @@ xtimer_add(cps_service_restart, SC_TIME_WAIT(scp)); } +void cpm_service_stop(struct service *sp, const char *reason) +{ + struct service_config *scp = SVC_CONF( sp ) ; + time_t nowtime; + time_t waittime; + + svc_deactivate( sp ); + nowtime = time(NULL); + waittime = SC_TIME_CPM_WAIT(scp); + /* Check that reenable will not be within this same minute */ + if( (int)((nowtime+waittime)/60) == SC_TIME_CPM_LIMIT(scp) ) { + int x; + x = (SC_TIME_CPM_LIMIT(scp) + 1)*60 - nowtime; + if( x > waittime ) { /* Paranoia... */ + waittime = x; + } + } + msg(LOG_ERR, "service_stop", + "Deactivating service %s due to %s. Restarting in %d seconds.", + SC_NAME(scp), reason, (int)waittime); + SC_TIME_REENABLE(scp) = nowtime + waittime; + xtimer_add(cps_service_restart, waittime); +} + +void cph_service_stop(struct service *sp, const char *reason) +{ + struct service_config *scp = SVC_CONF( sp ) ; + time_t nowtime; + time_t waittime; + + svc_deactivate( sp ); + nowtime = time(NULL); + waittime = SC_TIME_CPH_WAIT(scp); + /* Check that reenable will not be within this same hour */ + if( (int)((nowtime+waittime)/3600) == SC_TIME_CPH_LIMIT(scp) ) { + int x; + x = (SC_TIME_CPH_LIMIT(scp) + 1)*3600 - nowtime; + if( x > waittime ) { /* Paranoia... */ + waittime = x; + } + } + msg(LOG_ERR, "service_stop", + "Deactivating service %s due to %s. Restarting in %d seconds.", + SC_NAME(scp), reason, (int)waittime); + SC_TIME_REENABLE(scp) = nowtime + waittime; + xtimer_add(cps_service_restart, waittime); +} + /* * Returns OK if the IP address in sinp is acceptable to the access control @@ -286,18 +336,13 @@ /* CPS handler */ if( SC_TIME_CONN_MAX(scp) != 0 ) { - int time_diff; nowtime = time(NULL); - time_diff = nowtime - SC_TIME_LIMIT(scp) ; - if( SC_TIME_CONN(scp) == 0 ) { + if( nowtime == SC_TIME_LIMIT(scp) && SC_TIME_CONN(scp) > 0 ) { + /* Count connections during this very same second */ SC_TIME_CONN(scp)++; - SC_TIME_LIMIT(scp) = nowtime; - } else if( time_diff < SC_TIME_CONN_MAX(scp) ) { - SC_TIME_CONN(scp)++; - if( time_diff == 0 ) time_diff = 1; - if( SC_TIME_CONN(scp)/time_diff > SC_TIME_CONN_MAX(scp) ) { - cps_service_stop(sp, "excessive incoming connections"); + if( SC_TIME_CONN(scp) > SC_TIME_CONN_MAX(scp) ) { + cps_service_stop(sp, "excessive incoming connections per second"); return(AC_CPS); } } else { @@ -306,6 +351,38 @@ } } + /* CPM handler */ + if( SC_TIME_CPM_CONN_MAX(scp) != 0 ) { + nowtime = (int)(time(NULL)/60); + if( nowtime == SC_TIME_CPM_LIMIT(scp) && SC_TIME_CPM_CONN(scp) > 0 ) { + /* Count connections during this very same minute */ + SC_TIME_CPM_CONN(scp)++; + if( SC_TIME_CPM_CONN(scp) > SC_TIME_CPM_CONN_MAX(scp) ) { + cpm_service_stop(sp, "excessive incoming connections per minute"); + return(AC_CPM); + } + } else { + SC_TIME_CPM_LIMIT(scp) = nowtime; + SC_TIME_CPM_CONN(scp) = 1; + } + } + + /* CPH handler */ + if( SC_TIME_CPH_CONN_MAX(scp) != 0 ) { + nowtime = (int)(time(NULL)/3600); + if( nowtime == SC_TIME_CPH_LIMIT(scp) && SC_TIME_CPH_CONN(scp) > 0 ) { + /* Count connections during this very same hour */ + SC_TIME_CPH_CONN(scp)++; + if( SC_TIME_CPH_CONN(scp) > SC_TIME_CPH_CONN_MAX(scp) ) { + cph_service_stop(sp, "excessive incoming connections per hour"); + return(AC_CPH); + } + } else { + SC_TIME_CPH_LIMIT(scp) = nowtime; + SC_TIME_CPH_CONN(scp) = 1; + } + } + #ifdef HAVE_LOADAVG if ( SC_MAX_LOAD(scp) != 0 ) { if ( xgetloadavg() >= SC_MAX_LOAD(scp) ) { --- xinetd-2.3.14/xinetd/access.h.ORIG 2004-01-03 08:07:42.000000000 +1100 +++ xinetd-2.3.14/xinetd/access.h 2009-04-15 12:11:30.000000000 +1000 @@ -39,7 +39,9 @@ AC_PROCESS_LIMIT, /* total process limit would be exceeded */ AC_LIBWRAP, AC_LOAD, - AC_CPS + AC_CPS, + AC_CPM, + AC_CPH } access_e ; @@ -48,6 +50,8 @@ extern const struct name_value access_code_names[]; void cps_service_stop(struct service *sp, const char *reason); +void cpm_service_stop(struct service *sp, const char *reason); +void cph_service_stop(struct service *sp, const char *reason); access_e access_control(struct service *sp, const connection_s *cp,const mask_t *check_mask); access_e parent_access_control(struct service *sp,const connection_s *cp); --- xinetd-2.3.14/xinetd/attr.h.ORIG 2005-10-06 03:15:33.000000000 +1000 +++ xinetd-2.3.14/xinetd/attr.h 2009-04-15 12:11:29.000000000 +1000 @@ -48,19 +48,21 @@ #define A_BANNER_FAIL 30 #define A_MAX_LOAD 31 #define A_CPS 32 -#define A_SVCDISABLE 33 -#define A_RLIMIT_AS 34 -#define A_RLIMIT_CPU 35 -#define A_RLIMIT_DATA 36 -#define A_RLIMIT_RSS 37 -#define A_RLIMIT_STACK 38 -#define A_V6ONLY 39 -#define A_DENY_TIME 40 -#define A_UMASK 41 -#define A_ENABLED 42 -#define A_DISABLED 43 -#define A_MDNS 44 -#define A_LIBWRAP 45 +#define A_CPM 33 +#define A_CPH 34 +#define A_SVCDISABLE 35 +#define A_RLIMIT_AS 36 +#define A_RLIMIT_CPU 37 +#define A_RLIMIT_DATA 38 +#define A_RLIMIT_RSS 39 +#define A_RLIMIT_STACK 40 +#define A_V6ONLY 41 +#define A_DENY_TIME 42 +#define A_UMASK 43 +#define A_ENABLED 44 +#define A_DISABLED 45 +#define A_MDNS 46 +#define A_LIBWRAP 47 /* * SERVICE_ATTRIBUTES is the number of service attributes and also --- xinetd-2.3.14/xinetd/confparse.c.ORIG 2009-04-14 09:17:39.000000000 +1000 +++ xinetd-2.3.14/xinetd/confparse.c 2009-04-15 12:14:16.000000000 +1000 @@ -191,6 +191,20 @@ SC_TIME_REENABLE(scp) = 0; } + /* Would not these be zero anyway? */ + if ( ! SC_SPECIFIED( scp, A_CPM ) ) + { + SC_TIME_CPM_CONN_MAX(scp) = 0; + SC_TIME_CPM_WAIT(scp) = 0; + } + + /* Would not these be zero anyway? */ + if ( ! SC_SPECIFIED( scp, A_CPH ) ) + { + SC_TIME_CPH_CONN_MAX(scp) = 0; + SC_TIME_CPH_WAIT(scp) = 0; + } + #ifdef HAVE_LOADAVG if ( ! SC_SPECIFIED( scp, A_MAX_LOAD ) ) { SC_MAX_LOAD(scp) = SC_SPECIFIED( def, A_MAX_LOAD ) ? SC_MAX_LOAD(def) : 0; --- xinetd-2.3.14/xinetd/parse.c.ORIG 2005-10-06 03:15:33.000000000 +1000 +++ xinetd-2.3.14/xinetd/parse.c 2009-04-15 12:11:26.000000000 +1000 @@ -79,6 +79,8 @@ { "banner_success", A_BANNER_SUCCESS, 1, banner_success_parser }, { "banner_fail", A_BANNER_FAIL, 1, banner_fail_parser }, { "cps", A_CPS, 2, cps_parser }, + { "cpm", A_CPM, 2, cpm_parser }, + { "cph", A_CPH, 2, cph_parser }, { "disable", A_SVCDISABLE, 1, svcdisable_parser }, #ifdef HAVE_LOADAVG { "max_load", A_MAX_LOAD, 1, max_load_parser }, --- xinetd-2.3.14/xinetd/parsers.c.ORIG 2005-10-06 07:45:41.000000000 +1000 +++ xinetd-2.3.14/xinetd/parsers.c 2009-04-15 12:11:25.000000000 +1000 @@ -580,6 +580,80 @@ return(OK); } +status_e cpm_parser( pset_h values, + struct service_config *scp, + enum assign_op op ) +{ + char *cpm = (char *) pset_pointer(values, 0); + char *waittime = (char *) pset_pointer(values, 1); + unsigned int waittime_int, conn_max; + + if( cpm == NULL || waittime == NULL ) { + parsemsg(LOG_ERR, "cpm_parser", "NULL options specified in cpm"); + return( FAILED ); + } + if( parse_ubase10(cpm, &conn_max) ) { + parsemsg(LOG_ERR, "cpm_parser", "cpm argument not a number"); + SC_TIME_CPM_CONN_MAX(scp) = 0; + SC_TIME_CPM_WAIT(scp) = 0; + return( FAILED ); + } + if( parse_ubase10(waittime, &waittime_int) ) { + parsemsg(LOG_ERR, "cpm_parser", "cpm time argument not a number"); + SC_TIME_CPM_CONN_MAX(scp) = 0; + SC_TIME_CPM_WAIT(scp) = 0; + return( FAILED ); + } + SC_TIME_CPM_WAIT(scp) = waittime_int; + SC_TIME_CPM_CONN_MAX(scp) = conn_max; + + if( SC_TIME_CPM_CONN_MAX(scp) < 0 || SC_TIME_CPM_WAIT(scp) < 0 ) { + parsemsg(LOG_ERR, "cpm_parser", "cpm arguments invalid"); + SC_TIME_CPM_CONN_MAX(scp) = 0; + SC_TIME_CPM_WAIT(scp) = 0; + return( FAILED ); + } + + return(OK); +} + +status_e cph_parser( pset_h values, + struct service_config *scp, + enum assign_op op ) +{ + char *cph = (char *) pset_pointer(values, 0); + char *waittime = (char *) pset_pointer(values, 1); + unsigned int waittime_int, conn_max; + + if( cph == NULL || waittime == NULL ) { + parsemsg(LOG_ERR, "cph_parser", "NULL options specified in cph"); + return( FAILED ); + } + if( parse_ubase10(cph, &conn_max) ) { + parsemsg(LOG_ERR, "cph_parser", "cph argument not a number"); + SC_TIME_CPH_CONN_MAX(scp) = 0; + SC_TIME_CPH_WAIT(scp) = 0; + return( FAILED ); + } + if( parse_ubase10(waittime, &waittime_int) ) { + parsemsg(LOG_ERR, "cph_parser", "cph time argument not a number"); + SC_TIME_CPH_CONN_MAX(scp) = 0; + SC_TIME_CPH_WAIT(scp) = 0; + return( FAILED ); + } + SC_TIME_CPH_WAIT(scp) = waittime_int; + SC_TIME_CPH_CONN_MAX(scp) = conn_max; + + if( SC_TIME_CPH_CONN_MAX(scp) < 0 || SC_TIME_CPH_WAIT(scp) < 0 ) { + parsemsg(LOG_ERR, "cph_parser", "cph arguments invalid"); + SC_TIME_CPH_CONN_MAX(scp) = 0; + SC_TIME_CPH_WAIT(scp) = 0; + return( FAILED ); + } + + return(OK); +} + status_e id_parser( pset_h values, struct service_config *scp, enum assign_op op ) --- xinetd-2.3.14/xinetd/parsers.h.ORIG 2005-10-06 03:15:33.000000000 +1000 +++ xinetd-2.3.14/xinetd/parsers.h 2009-04-15 12:11:24.000000000 +1000 @@ -43,6 +43,8 @@ status_e banner_success_parser(pset_h, struct service_config *, enum assign_op) ; status_e banner_fail_parser(pset_h, struct service_config *, enum assign_op) ; status_e cps_parser(pset_h, struct service_config *, enum assign_op) ; +status_e cpm_parser(pset_h, struct service_config *, enum assign_op) ; +status_e cph_parser(pset_h, struct service_config *, enum assign_op) ; status_e enabled_parser(pset_h, struct service_config *, enum assign_op) ; status_e svcdisable_parser(pset_h, struct service_config *, enum assign_op); #ifdef HAVE_LOADAVG --- xinetd-2.3.14/xinetd/sconf.c.ORIG 2005-10-06 03:15:33.000000000 +1000 +++ xinetd-2.3.14/xinetd/sconf.c 2009-04-15 12:11:22.000000000 +1000 @@ -314,6 +314,14 @@ tabprint( fd, tab_level+1, "CPS = max conn:%lu wait:%lu\n", SC_TIME_CONN_MAX(scp), SC_TIME_WAIT(scp) ); + if ( SC_SPECIFIED( scp, A_CPM ) ) + tabprint( fd, tab_level+1, "CPM = max conn:%lu wait:%lu\n", + SC_TIME_CPM_CONN_MAX(scp), SC_TIME_CPM_WAIT(scp) ); + + if ( SC_SPECIFIED( scp, A_CPH ) ) + tabprint( fd, tab_level+1, "CPH = max conn:%lu wait:%lu\n", + SC_TIME_CPH_CONN_MAX(scp), SC_TIME_CPH_WAIT(scp) ); + if ( SC_SPECIFIED( scp, A_PER_SOURCE ) ) tabprint( fd, tab_level+1, "PER_SOURCE = %d\n", SC_PER_SOURCE(scp) ); --- xinetd-2.3.14/xinetd/sconf.h.ORIG 2005-10-06 03:15:33.000000000 +1000 +++ xinetd-2.3.14/xinetd/sconf.h 2009-04-15 12:11:20.000000000 +1000 @@ -139,6 +139,14 @@ time_t sc_time_conn_max ; time_t sc_time_wait ; time_t sc_time_reenable ; + time_t sc_time_cpm_limit ; + time_t sc_time_cpm_conn ; + time_t sc_time_cpm_conn_max ; + time_t sc_time_cpm_wait ; + time_t sc_time_cph_limit ; + time_t sc_time_cph_conn ; + time_t sc_time_cph_conn_max ; + time_t sc_time_cph_wait ; rlim_t sc_rlim_as; rlim_t sc_rlim_cpu; rlim_t sc_rlim_data; @@ -212,6 +220,15 @@ #define SC_TIME_CONN_MAX( scp ) (scp)->sc_time_conn_max #define SC_TIME_WAIT( scp ) (scp)->sc_time_wait #define SC_TIME_REENABLE( scp ) (scp)->sc_time_reenable +#define SC_TIME_CPM_LIMIT( scp ) (scp)->sc_time_cpm_limit +#define SC_TIME_CPM_CONN( scp ) (scp)->sc_time_cpm_conn +#define SC_TIME_CPM_CONN_MAX( scp ) (scp)->sc_time_cpm_conn_max +#define SC_TIME_CPM_WAIT( scp ) (scp)->sc_time_cpm_wait +#define SC_TIME_CPH_LIMIT( scp ) (scp)->sc_time_cph_limit +#define SC_TIME_CPH_CONN( scp ) (scp)->sc_time_cph_conn +#define SC_TIME_CPH_CONN_MAX( scp ) (scp)->sc_time_cph_conn_max +#define SC_TIME_CPH_WAIT( scp ) (scp)->sc_time_cph_wait + #define SC_UMASK( scp ) (scp)->sc_umask #define SC_DENY_TIME( scp ) (scp)->sc_deny_time #define SC_MDNS_NAME( scp ) (scp)->sc_mdns_name --- xinetd-2.3.14/xinetd/xinetd.conf.man.ORIG 2009-04-14 09:17:39.000000000 +1000 +++ xinetd-2.3.14/xinetd/xinetd.conf.man 2009-04-15 12:14:16.000000000 +1000 @@ -490,13 +490,41 @@ also be specified in the defaults section. .TP .B cps -Limits the rate of incoming connections. Takes two arguments. +Limits the rate of incoming connections per second. Takes two arguments. The first argument is the number of connections per second to handle. If the rate of incoming connections is higher than this, the service will be temporarily disabled. The second argument is the number of seconds to wait before re-enabling the service after it has been disabled. -The default for this setting is 50 incoming connections and the interval -is 10 seconds. +Connections are counted within each wall-clock second, from any +sources. Service is disabled for all sources. +The default for this setting is 50 incoming connections per second and +the interval is 10 seconds. +.TP +.B cpm +Limits the rate of incoming connections per minute. Takes two arguments. +The first argument is the number of connections per minute to handle. +If the rate of incoming connections is higher than this, the service +will be temporarily disabled. The second argument is the number of +seconds to wait before re-enabling the service after it has been +disabled. +Connections are counted within each wall-clock minute, from any +sources. Time to disable is given in seconds, and will be increased +if would re-enable within the same wall-clock minute; service +is disabled for all sources. +There is no default cpm limit (i.e. is unlimited). +.TP +.B cph +Limits the rate of incoming connections per hour. Takes two arguments. +The first argument is the number of connections per hour to handle. +If the rate of incoming connections is higher than this, the service +will be temporarily disabled. The second argument is the number of +seconds to wait before re-enabling the service after it has been +disabled. +Connections are counted within each wall-clock hour, from any +sources. Time to disable is given in seconds, and will be increased +if would re-enable within the same wall-clock hour; service +is disabled for all sources. +There is no default cph limit (i.e. is unlimited). .TP .B max_load Takes a floating point value as the load at which the service will -- System Information: Debian Release: 4.0 APT prefers oldstable APT policy: (500, 'oldstable') Architecture: i386 (i686) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.24-pk03.03-svr Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org