mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-23 02:25:40 +08:00
connlim / noconnlim commands added to support connection / connectio rate limits
This commit is contained in:
parent
e076fff33c
commit
ff91a6fe72
@ -795,6 +795,31 @@ if you want, for example, to limit all speed ecept access to POP3 you can use
|
||||
.br
|
||||
before the rest of bandlim rules.
|
||||
|
||||
.br
|
||||
.B connlim
|
||||
<rate> <period> <userlist> <sourcelist> <targetlist> <targetportlist> <operationlist>
|
||||
.br
|
||||
.B noconnlim
|
||||
<userlist> <sourcelist> <targetlist> <targetportlist> <operationlist>
|
||||
.br
|
||||
connlim sets connections rate limit per time period for traffic
|
||||
pattern controlled by ACL. Period is in seconds. If period is 0,
|
||||
connlim limits a number of parallel connections.
|
||||
.br
|
||||
connlim 100 60 * 127.0.0.1
|
||||
.br
|
||||
allows 100 connections per minute for 127.0.0.1.
|
||||
.br
|
||||
connlim 20 0 * 127.0.0.1
|
||||
.br
|
||||
allows 20 simulationeous connections for 127.0.0.1.
|
||||
.br
|
||||
Like with bandlimin, if individual limit is required per client, separate
|
||||
rule mustbe added for every client. Like with nobanlimin, noconnlim adds an
|
||||
exception.
|
||||
|
||||
|
||||
|
||||
.br
|
||||
.B counter
|
||||
<filename> <reporttype> <repotname>
|
||||
|
@ -515,6 +515,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
|
||||
|
||||
pthread_mutex_init(&config_mutex, NULL);
|
||||
pthread_mutex_init(&bandlim_mutex, NULL);
|
||||
pthread_mutex_init(&connlim_mutex, NULL);
|
||||
pthread_mutex_init(&hash_mutex, NULL);
|
||||
pthread_mutex_init(&tc_mutex, NULL);
|
||||
pthread_mutex_init(&pwl_mutex, NULL);
|
||||
|
69
src/auth.c
69
src/auth.c
@ -437,6 +437,60 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int startconnlims (struct clientparam *param){
|
||||
struct connlim * ce;
|
||||
time_t delta;
|
||||
uint64_t rating;
|
||||
int ret = 0;
|
||||
|
||||
pthread_mutex_lock(&connlim_mutex);
|
||||
for(ce = conf.connlimiter; ce; ce = ce->next) {
|
||||
if(ACLmatches(ce->ace, param)){
|
||||
if(ce->ace->action == NOCONNLIM)break;
|
||||
if(!ce->period){
|
||||
if(ce->rate <= ce->rating) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
ce->rating++;
|
||||
continue;
|
||||
}
|
||||
delta = conf.time - ce->basetime;
|
||||
if(ce->period <= delta || ce->basetime > conf.time){
|
||||
ce->basetime = conf.time;
|
||||
ce->rating = 0x100000;
|
||||
continue;
|
||||
}
|
||||
rating = delta? ((ce->rating * (ce->period - delta)) / ce->period) + 0x100000 : ce->rating + 0x100000;
|
||||
if (rating > (ce->rate<<20)) {
|
||||
ret = 2;
|
||||
break;
|
||||
}
|
||||
ce->rating = rating;
|
||||
ce->basetime = conf.time;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&connlim_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void stopconnlims (struct clientparam *param){
|
||||
struct connlim * ce;
|
||||
|
||||
pthread_mutex_lock(&connlim_mutex);
|
||||
for(ce = conf.connlimiter; ce; ce = ce->next) {
|
||||
if(ACLmatches(ce->ace, param)){
|
||||
if(ce->ace->action == NOCONNLIM)break;
|
||||
if(!ce->period && ce->rating){
|
||||
ce->rating--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&connlim_mutex);
|
||||
}
|
||||
|
||||
static void initbandlims (struct clientparam *param){
|
||||
struct bandlim * be;
|
||||
int i;
|
||||
@ -464,7 +518,7 @@ static void initbandlims (struct clientparam *param){
|
||||
|
||||
unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nbytesout){
|
||||
unsigned sleeptime = 0, nsleeptime;
|
||||
unsigned long sec;
|
||||
time_t sec;
|
||||
unsigned msec;
|
||||
unsigned now;
|
||||
int i;
|
||||
@ -504,7 +558,7 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
|
||||
param->bandlims[i]->nexttime = 0;
|
||||
continue;
|
||||
}
|
||||
now = ((sec - param->bandlims[i]->basetime) * 1000000) + msec;
|
||||
now = (unsigned)((sec - param->bandlims[i]->basetime) * 1000000) + msec;
|
||||
nsleeptime = (param->bandlims[i]->nexttime > now)?
|
||||
param->bandlims[i]->nexttime - now : 0;
|
||||
sleeptime = (nsleeptime > sleeptime)? nsleeptime : sleeptime;
|
||||
@ -521,7 +575,7 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
|
||||
param->bandlimsout[i]->nexttime = 0;
|
||||
continue;
|
||||
}
|
||||
now = ((sec - param->bandlimsout[i]->basetime) * 1000000) + msec;
|
||||
now = (unsigned)((sec - param->bandlimsout[i]->basetime) * 1000000) + msec;
|
||||
nsleeptime = (param->bandlimsout[i]->nexttime > now)?
|
||||
param->bandlimsout[i]->nexttime - now : 0;
|
||||
sleeptime = (nsleeptime > sleeptime)? nsleeptime : sleeptime;
|
||||
@ -571,6 +625,8 @@ int alwaysauth(struct clientparam * param){
|
||||
struct trafcount * tc;
|
||||
int countout = 0;
|
||||
|
||||
|
||||
if(conf.connlimiter && param->remsock == INVALID_SOCKET && startconnlims(param)) return 95;
|
||||
res = doconnect(param);
|
||||
if(!res){
|
||||
initbandlims(param);
|
||||
@ -610,7 +666,7 @@ int checkACL(struct clientparam * param){
|
||||
struct ace* acentry;
|
||||
|
||||
if(!param->srv->acl) {
|
||||
return alwaysauth(param);
|
||||
return 0;
|
||||
}
|
||||
for(acentry = param->srv->acl; acentry; acentry = acentry->next) {
|
||||
if(ACLmatches(acentry, param)) {
|
||||
@ -868,11 +924,12 @@ struct auth authfuncs[] = {
|
||||
{authfuncs+5, strongauth, checkACL, "strong"},
|
||||
{authfuncs+6, cacheauth, checkACL, "cache"},
|
||||
#ifndef NORADIUS
|
||||
#define AUTHOFFSET 1
|
||||
{authfuncs+7, radauth, checkACL, "radius"},
|
||||
{authfuncs+8, NULL, NULL, "none"},
|
||||
#else
|
||||
{authfuncs+7, NULL, NULL, "none"},
|
||||
#define AUTHOFFSET 0
|
||||
#endif
|
||||
{authfuncs+7+AUTHOFFSET, NULL, NULL, "none"},
|
||||
{NULL, NULL, NULL, ""}
|
||||
};
|
||||
|
||||
|
@ -71,6 +71,7 @@ struct extparam conf = {
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
#ifdef __FreeBSD__
|
||||
8192,
|
||||
#else
|
||||
|
73
src/conf.c
73
src/conf.c
@ -19,6 +19,7 @@
|
||||
#endif
|
||||
|
||||
pthread_mutex_t bandlim_mutex;
|
||||
pthread_mutex_t connlim_mutex;
|
||||
pthread_mutex_t tc_mutex;
|
||||
pthread_mutex_t pwl_mutex;
|
||||
pthread_mutex_t hash_mutex;
|
||||
@ -1093,6 +1094,7 @@ static int h_ace(int argc, unsigned char **argv){
|
||||
struct ace *acl = NULL;
|
||||
struct bandlim * nbl;
|
||||
struct trafcount * tl;
|
||||
struct connlim * ncl;
|
||||
|
||||
if(!strcmp((char *)argv[0], "allow")){
|
||||
res = ALLOW;
|
||||
@ -1125,6 +1127,13 @@ static int h_ace(int argc, unsigned char **argv){
|
||||
else if(!strcmp((char *)argv[0], "nocountout")){
|
||||
res = NOCOUNTOUT;
|
||||
}
|
||||
else if(!strcmp((char *)argv[0], "connlim")){
|
||||
res = CONNLIM;
|
||||
offset = 2;
|
||||
}
|
||||
else if(!strcmp((char *)argv[0], "noconnlim")){
|
||||
res = NOCONNLIM;
|
||||
}
|
||||
acl = make_ace(argc - (offset+1), argv + (offset + 1));
|
||||
if(!acl) {
|
||||
fprintf(stderr, "Unable to parse ACL entry, line %d\n", linenum);
|
||||
@ -1155,6 +1164,32 @@ static int h_ace(int argc, unsigned char **argv){
|
||||
acei->next = acl;
|
||||
}
|
||||
break;
|
||||
case CONNLIM:
|
||||
case NOCONNLIM:
|
||||
ncl = myalloc(sizeof(struct connlim));
|
||||
if(!ncl) {
|
||||
fprintf(stderr, "No memory to create connection limit filter\n");
|
||||
return(3);
|
||||
}
|
||||
memset(ncl, 0, sizeof(struct connlim));
|
||||
ncl->ace = acl;
|
||||
if(acl->action == CONNLIM) {
|
||||
sscanf((char *)argv[1], "%u", &ncl->rate);
|
||||
sscanf((char *)argv[2], "%u", &ncl->period);
|
||||
}
|
||||
pthread_mutex_lock(&connlim_mutex);
|
||||
if(!conf.connlimiter){
|
||||
conf.connlimiter = ncl;
|
||||
}
|
||||
else {
|
||||
struct connlim * cli;
|
||||
|
||||
for(cli = conf.connlimiter; cli->next; cli = cli->next);
|
||||
cli->next = ncl;
|
||||
}
|
||||
pthread_mutex_unlock(&connlim_mutex);
|
||||
break;
|
||||
|
||||
case BANDLIM:
|
||||
case NOBANDLIM:
|
||||
|
||||
@ -1460,22 +1495,24 @@ struct commands commandhandlers[]={
|
||||
{commandhandlers+44, "nocountin", h_ace, 1, 0},
|
||||
{commandhandlers+45, "countout", h_ace, 4, 0},
|
||||
{commandhandlers+46, "nocountout", h_ace, 1, 0},
|
||||
{commandhandlers+47, "plugin", h_plugin, 3, 0},
|
||||
{commandhandlers+48, "logdump", h_logdump, 2, 3},
|
||||
{commandhandlers+49, "filtermaxsize", h_filtermaxsize, 2, 2},
|
||||
{commandhandlers+50, "nolog", h_nolog, 1, 1},
|
||||
{commandhandlers+51, "weight", h_nolog, 2, 2},
|
||||
{commandhandlers+52, "authcache", h_authcache, 2, 3},
|
||||
{commandhandlers+53, "smtpp", h_proxy, 1, 0},
|
||||
{commandhandlers+54, "icqpr", h_proxy, 4, 0},
|
||||
{commandhandlers+55, "msnpr", h_proxy, 4, 0},
|
||||
{commandhandlers+56, "delimchar",h_delimchar, 2, 2},
|
||||
{commandhandlers+57, "authnserver", h_authnserver, 2, 2},
|
||||
{commandhandlers+58, "stacksize", h_stacksize, 2, 2},
|
||||
{commandhandlers+59, "force", h_force, 1, 1},
|
||||
{commandhandlers+60, "noforce", h_noforce, 1, 1},
|
||||
{commandhandlers+47, "connlim", h_ace, 4, 0},
|
||||
{commandhandlers+48, "noconnlim", h_ace, 1, 0},
|
||||
{commandhandlers+49, "plugin", h_plugin, 3, 0},
|
||||
{commandhandlers+50, "logdump", h_logdump, 2, 3},
|
||||
{commandhandlers+51, "filtermaxsize", h_filtermaxsize, 2, 2},
|
||||
{commandhandlers+52, "nolog", h_nolog, 1, 1},
|
||||
{commandhandlers+53, "weight", h_nolog, 2, 2},
|
||||
{commandhandlers+54, "authcache", h_authcache, 2, 3},
|
||||
{commandhandlers+55, "smtpp", h_proxy, 1, 0},
|
||||
{commandhandlers+56, "icqpr", h_proxy, 4, 0},
|
||||
{commandhandlers+57, "msnpr", h_proxy, 4, 0},
|
||||
{commandhandlers+58, "delimchar",h_delimchar, 2, 2},
|
||||
{commandhandlers+59, "authnserver", h_authnserver, 2, 2},
|
||||
{commandhandlers+60, "stacksize", h_stacksize, 2, 2},
|
||||
{commandhandlers+51, "force", h_force, 1, 1},
|
||||
{commandhandlers+62, "noforce", h_noforce, 1, 1},
|
||||
#ifndef NORADIUS
|
||||
{commandhandlers+61, "radius", h_radius, 3, 0},
|
||||
{commandhandlers+63, "radius", h_radius, 3, 0},
|
||||
#endif
|
||||
{specificcommands, "", h_noop, 1, 0}
|
||||
};
|
||||
@ -1644,6 +1681,7 @@ void freepwl(struct passwords *pwl){
|
||||
void freeconf(struct extparam *confp){
|
||||
struct bandlim * bl;
|
||||
struct bandlim * blout;
|
||||
struct connlim * cl;
|
||||
struct trafcount * tc;
|
||||
struct passwords *pw;
|
||||
struct ace *acl;
|
||||
@ -1674,6 +1712,10 @@ void freeconf(struct extparam *confp){
|
||||
confp->bandlimiterout = NULL;
|
||||
confp->bandlimfunc = NULL;
|
||||
pthread_mutex_unlock(&bandlim_mutex);
|
||||
pthread_mutex_lock(&connlim_mutex);
|
||||
cl = confp->connlimiter;
|
||||
confp->connlimiter = NULL;
|
||||
pthread_mutex_unlock(&connlim_mutex);
|
||||
|
||||
pthread_mutex_lock(&pwl_mutex);
|
||||
pw = confp->pwl;
|
||||
@ -1731,6 +1773,7 @@ void freeconf(struct extparam *confp){
|
||||
freepwl(pw);
|
||||
for(; bl; bl = (struct bandlim *) itfree(bl, bl->next)) freeacl(bl->ace);
|
||||
for(; blout; blout = (struct bandlim *) itfree(blout, blout->next))freeacl(blout->ace);
|
||||
for(; cl; cl = (struct connlim *) itfree(cl, cl->next)) freeacl(cl->ace);
|
||||
|
||||
if(counterd != -1) {
|
||||
close(counterd);
|
||||
|
@ -38,6 +38,8 @@
|
||||
#define NOCOUNTIN 6
|
||||
#define COUNTOUT 7
|
||||
#define NOCOUNTOUT 8
|
||||
#define CONNLIM 9
|
||||
#define NOCONNLIM 10
|
||||
|
||||
#define UDPBUFSIZE 16384
|
||||
#define TCPBUFSIZE 8192
|
||||
@ -206,6 +208,9 @@ void freeparam(struct clientparam * param);
|
||||
void clearstat(struct clientparam * param);
|
||||
void dumpcounters(struct trafcount *tl, int counterd);
|
||||
|
||||
int startconnlims (struct clientparam *param);
|
||||
void stopconnlims (struct clientparam *param);
|
||||
|
||||
|
||||
|
||||
extern struct auth authfuncs[];
|
||||
@ -319,6 +324,7 @@ struct property;
|
||||
extern unsigned char tmpbuf[8192];
|
||||
extern pthread_mutex_t config_mutex;
|
||||
extern pthread_mutex_t bandlim_mutex;
|
||||
extern pthread_mutex_t connlim_mutex;
|
||||
extern pthread_mutex_t hash_mutex;
|
||||
extern pthread_mutex_t tc_mutex;
|
||||
extern pthread_mutex_t pwl_mutex;
|
||||
|
@ -961,6 +961,7 @@ void freeparam(struct clientparam * param) {
|
||||
}
|
||||
myfree(param->filters);
|
||||
}
|
||||
if(conf.connlimiter && (param->res != 95 || param->remsock != INVALID_SOCKET)) stopconnlims(param);
|
||||
#endif
|
||||
if(param->clibuf) myfree(param->clibuf);
|
||||
if(param->srvbuf) myfree(param->srvbuf);
|
||||
|
@ -299,11 +299,21 @@ struct ace {
|
||||
struct bandlim {
|
||||
struct bandlim *next;
|
||||
struct ace *ace;
|
||||
unsigned basetime;
|
||||
unsigned rate;
|
||||
time_t basetime;
|
||||
unsigned nexttime;
|
||||
unsigned rate;
|
||||
};
|
||||
|
||||
struct connlim {
|
||||
struct connlim *next;
|
||||
struct ace *ace;
|
||||
time_t basetime;
|
||||
uint64_t rating;
|
||||
unsigned period;
|
||||
unsigned rate;
|
||||
};
|
||||
|
||||
|
||||
typedef enum {NONE, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, ANNUALLY, NEVER} ROTATION;
|
||||
|
||||
struct schedule {
|
||||
@ -528,6 +538,7 @@ struct extparam {
|
||||
struct ace * acl;
|
||||
char * conffile;
|
||||
struct bandlim * bandlimiter, *bandlimiterout;
|
||||
struct connlim * connlimiter;
|
||||
struct trafcount * trafcounter;
|
||||
struct srvparam *services;
|
||||
int stacksize,
|
||||
|
Loading…
Reference in New Issue
Block a user