dynamic connections. Also, if any of the server maxconn, or maxqueue is 0, then
this acl clearly does not make sense - in which case the value returned will be -1.
+fe_sess_rate <integer>
+fe_sess_rate(frontend) <integer>
+ Returns true when the session creation rate on the current or the named
+ frontend matches the specified values or ranges, expressed in new sessions
+ per second. This is used to limit the connection rate to acceptable ranges in
+ order to prevent abuse of service at the earliest moment. This can be
+ combined with layer 4 ACLs in order to force the clients to wait a bit for
+ the rate to go down below the limit.
+
+ Example :
+ # This frontend limits incoming mails to 10/s with a max of 100
+ # concurrent connections. We accept any connection below 10/s, and
+ # force excess clients to wait for 100 ms. Since clients are limited to
+ # 100 max, there cannot be more than 10 incoming mails per second.
+ frontend mail
+ bind :25
+ mode tcp
+ maxconn 100
+ acl too_fast fe_sess_rate ge 10
+ tcp-request inspect-delay 100ms
+ tcp-request content accept if ! too_fast
+ tcp-request content accept if WAIT_END
+
+be_sess_rate <integer>
+be_sess_rate(backend) <integer>
+ Returns true when the sessions creation rate on the backend matches the
+ specified values or ranges, in number of new sessions per second. This is
+ used to switch to an alternate backend when an expensive or fragile one
+ reaches too high a session rate, or to limite abuse of service (eg. prevent
+ sucking of an online dictionary).
+
+ Example :
+ # Redirect to an error page if the dictionary is requested too often
+ backend dynamic
+ mode http
+ acl being_scanned be_sess_rate gt 100
+ redirect location /denied.html if being_scanned
+
2.3.5.2) Matching contents at Layer 4
-------------------------------------
return 1;
}
+/* set test->i to the number of connections per second reaching the frontend */
+static int
+acl_fetch_fe_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
+ struct acl_expr *expr, struct acl_test *test)
+{
+ test->flags = ACL_TEST_F_VOL_TEST;
+ if (expr->arg_len) {
+ /* another proxy was designated, we must look for it */
+ for (px = proxy; px; px = px->next)
+ if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str))
+ break;
+ }
+ if (!px)
+ return 0;
+
+ test->i = read_freq_ctr(&px->fe_sess_per_sec);
+ return 1;
+}
+
+/* set test->i to the number of connections per second reaching the backend */
+static int
+acl_fetch_be_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
+ struct acl_expr *expr, struct acl_test *test)
+{
+ test->flags = ACL_TEST_F_VOL_TEST;
+ if (expr->arg_len) {
+ /* another proxy was designated, we must look for it */
+ for (px = proxy; px; px = px->next)
+ if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+ break;
+ }
+ if (!px)
+ return 0;
+
+ test->i = read_freq_ctr(&px->be_sess_per_sec);
+ return 1;
+}
+
/* Note: must not be declared <const> as its list will be overwritten */
static struct acl_kw_list acl_kws = {{ },{
{ "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int, ACL_USE_NOTHING },
{ "connslots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING },
+ { "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING },
+ { "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING },
{ NULL, NULL, NULL, NULL },
}};