HAProxy: Check stick-table contains required key

106 Views Asked by At

I want to set limit of new users' connections if amount of active users exceeded the required threshold. Users connect to the load balancer via http. I use stick-table to limit the amount of users (by unique header):

frontend echo
    bind *:8881
    mode http

    # user is active if seds any request every 30s or often
    stick-table type string size 100k expire 30s store gpc0_rate(10s) 
    # track keys if table size less than limit
    http-request track-sc0 req.hdr(Client-ID) if { table_cnt lt 100 } 
    # limit of new not active users
    http-request deny deny_status 429 if { table_cnt ge 100 } { <❓check that "Client-ID" keys's value exists in the table> }

    use_backend echo

The main idea is deny requests from all new user if Client-ID header's value is not present in the table. It's possible?

1

There are 1 best solutions below

0
tbielaszewski On BEST ANSWER

You are close to solution. You need in_table converter:

Uses the string representation of the input sample to perform a look up in the specified table. If the key is not found in the table, a boolean false is returned. Otherwise a boolean true is returned. This can be used to verify the presence of a certain key in a table tracking some elements (e.g. whether or not a source IP address or an Authorization header was already seen).

In your case it would be one more acl: acl clientid_in_table req.hdr(client-id),in_table and your config becomes (i prefer naming my ACLs for clarity):

frontend echo
    bind *:8881
    mode http

    # user is active if seds any request every 30s or often
    stick-table type string size 100k expire 30s store gpc0_rate(10s) 
    # ACL to check if client-id is in table
    acl clientid_in_table req.hdr(client-id),in_table
    # track keys if table size less than limit
    http-request track-sc0 req.hdr(Client-ID) if { table_cnt lt 100 } 
    # limit of new not active users
    http-request deny deny_status 429 if { table_cnt ge 100 } !clientid_in_table

    use_backend echo

No idea what it does if header is missing in request, but you can deny it on that basis as well if needed.