diff --git a/pillar/base/haproxy.sls b/pillar/base/haproxy.sls index 6b2259ff..28b1ae96 100644 --- a/pillar/base/haproxy.sls +++ b/pillar/base/haproxy.sls @@ -75,6 +75,7 @@ haproxy: - {{ config.server_name }} verify_host: bugs.psf.io check: "HEAD / HTTP/1.1\\r\\nHost:\\ {{ config.server_name }}" + rate_limit: {{ config.get('rate_limit', 10) }} {% endfor %} moin: diff --git a/salt/haproxy/config/haproxy.cfg.jinja b/salt/haproxy/config/haproxy.cfg.jinja index 2162c25c..d0048797 100644 --- a/salt/haproxy/config/haproxy.cfg.jinja +++ b/salt/haproxy/config/haproxy.cfg.jinja @@ -52,7 +52,6 @@ global # Lower the amount of space we reserve for header rewriting tune.maxrewrite 1024 - defaults log global @@ -117,6 +116,24 @@ frontend main bind :::80 bind 127.0.0.1:19001 # This is our TLS socket. + # Define a stick table for all services + stick-table type ipv6 size 100k expire 30s store http_req_rate(10s) + # Track all requests using a single counter + # We could use the 3 available (sc0,1,2) to maybe tier requests + # into say <=100, 101-500, >= 501 if we needed to? + http-request track-sc0 src + # then create the ACL for services in haproxy.sls that have a 'rate_limit' key, + # constrained to the host header using the domain key in haproxy.sls + # then adds a rule to deny via HTTP 429 if the respective ACL is matched and the stick table http request rate + # is higher than the 'rate_limit' from haproxy.sls pillar date + {%- for service, config in haproxy.services.items() %} + {%- if config.get('rate_limit') %} + # Rate limit config for {{ service }} + acl is_{{ service }} hdr(host) -i {% for domain in config.domains %}{{ domain }} {% endfor %} + http-request deny deny_status 429 if is_{{ service }} { sc_http_req_rate(0) gt {{ config.rate_limit }} } + {%- endif %} + {%- endfor %} + # Custom logging format, this is the same as the normal "httplog" in # HAProxy except information about the TLS connection is included. log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %sslv/%sslc\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r