certain resources such as statistics. Note that it is the TCP-level source
address which is used, and not the address of a client behind a proxy.
+src_count <integer>
+src_count(backend) <integer>
+ Returns the number of occurrences of the source IPv4 address in the current
+ backend's stick-table or in the designated stick-table. If the address is not
+ found, zero is returned.
+
src_port <integer>
Applies to the client's TCP source port. This has a very limited usage.
+src_update_count <integer>
+src_update_count(backend) <integer>
+ Creates or updates the entry associated to the source IPv4 address in the
+ current backend's stick-table or in the designated stick-table. This table
+ must be configured to store the "conn_cum" data type, otherwise the match
+ will be ignored. The current count is incremented by one, and the expiration
+ timer refreshed. The updated count is returned, so this match can't return
+ zero. This is used to reject service abusers based on their source address.
+
+ Example :
+ # This frontend limits incoming SSH connections to 3 per 10 second for
+ # each source address, and rejects excess connections until a 10 second
+ # silence is observed. At most 20 addresses are tracked.
+ listen ssh
+ bind :22
+ mode tcp
+ maxconn 100
+ stick-table type ip size 20 expire 10s store conn_cum
+ tcp-request content reject if { src_update_count gt 3 }
+ server local 127.0.0.1:22
+
srv_is_up(<server>)
srv_is_up(<backend>/<server>)
Returns true when the designated server is UP, and false when it is either
#include <proto/protocols.h>
#include <proto/proto_tcp.h>
#include <proto/proxy.h>
+#include <proto/stick_table.h>
#include <proto/stream_sock.h>
+#include <proto/task.h>
#ifdef CONFIG_HAP_CTTPROXY
#include <import/ip_tproxy.h>
return 1;
}
+/* set test->i to the number of connections from the session's source address
+ * in the table pointed to by expr.
+ */
+static int
+acl_fetch_src_count(struct proxy *px, struct session *l4, void *l7, int dir,
+ struct acl_expr *expr, struct acl_test *test)
+{
+ struct stksess *ts;
+
+ /* right now we only support IPv4 */
+ if (l4->cli_addr.ss_family != AF_INET)
+ return 0;
+
+ if (expr->arg_len) {
+ /* another table was designated, we must look for it */
+ for (px = proxy; px; px = px->next)
+ if (strcmp(px->id, expr->arg.str) == 0)
+ break;
+ }
+ if (!px)
+ return 0; /* table not found */
+
+ static_table_key.key = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr;
+ test->flags = ACL_TEST_F_VOL_TEST;
+ test->i = 0;
+ if ((ts = stktable_lookup_key(&px->table, &static_table_key)) != NULL) {
+ void *ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CUM);
+ if (!ptr)
+ return 0; /* parameter not stored */
+ test->i = stktable_data_cast(ptr, conn_cum);
+ }
+
+ return 1;
+}
+
+/* set test->i to the number of connections from the session's source address
+ * in the table pointed to by expr, after updating it.
+ */
+static int
+acl_fetch_src_update_count(struct proxy *px, struct session *l4, void *l7, int dir,
+ struct acl_expr *expr, struct acl_test *test)
+{
+ struct stksess *ts;
+ void *ptr;
+
+ /* right now we only support IPv4 */
+ if (l4->cli_addr.ss_family != AF_INET)
+ return 0;
+
+ if (expr->arg_len) {
+ /* another table was designated, we must look for it */
+ for (px = proxy; px; px = px->next)
+ if (strcmp(px->id, expr->arg.str) == 0)
+ break;
+ }
+ if (!px)
+ return 0;
+
+ static_table_key.key = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr;
+ if ((ts = stktable_lookup_key(&px->table, &static_table_key)) == NULL) {
+ /* entry does not exist, initialize a new one */
+ ts = stksess_new(&px->table, &static_table_key);
+ if (!ts)
+ return 0;
+ stktable_store(&px->table, ts);
+ }
+ else if (px->table.expire) {
+ /* if entries can expire, let's update the entry and the table */
+ ts->expire = tick_add(now_ms, MS_TO_TICKS(px->table.expire));
+ px->table.exp_task->expire = px->table.exp_next = tick_first(ts->expire, px->table.exp_next);
+ task_queue(px->table.exp_task);
+ }
+
+ ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CUM);
+ if (!ptr)
+ return 0; /* parameter not stored in this table */
+
+ test->i = ++stktable_data_cast(ptr, conn_cum);
+ test->flags = ACL_TEST_F_VOL_TEST;
+ return 1;
+}
static struct cfg_kw_list cfg_kws = {{ },{
{ CFG_LISTEN, "tcp-request", tcp_parse_tcp_req },
{ "src", acl_parse_ip, acl_fetch_src, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP },
{ "dst", acl_parse_ip, acl_fetch_dst, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP },
{ "dst_port", acl_parse_int, acl_fetch_dport, acl_match_int, ACL_USE_TCP_PERMANENT },
+ { "src_count", acl_parse_int, acl_fetch_src_count,acl_match_int, ACL_USE_TCP4_PERMANENT },
+ { "src_update_count", acl_parse_int, acl_fetch_src_update_count, acl_match_int, ACL_USE_TCP4_PERMANENT },
{ NULL, NULL, NULL, NULL },
}};