-
Notifications
You must be signed in to change notification settings - Fork 84
feat: Support runtime control of connection rate limiting via socket #930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
98f5285
b72c7bd
a0671d5
f2f888d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -230,6 +230,15 @@ end | |||||||||
| abort "Conflicting configuration: enable_redispatch works only with retries > 0" | ||||||||||
| end | ||||||||||
|
|
||||||||||
| # Safety guard: block=true without connections would cause every client with >= 1 connection to be blocked (total lockout) | ||||||||||
| if_p("ha_proxy.connections_rate_limit.table_size", "ha_proxy.connections_rate_limit.window_size") do | ||||||||||
| if p("ha_proxy.connections_rate_limit.block", false) | ||||||||||
| if !p("ha_proxy.connections_rate_limit.connections", nil) | ||||||||||
| abort "connections_rate_limit.connections must be set in the manifest as the initial threshold when block is true; otherwise rate-limiting will be silently disabled until a value is set via the runtime API." | ||||||||||
| end | ||||||||||
| end | ||||||||||
| end | ||||||||||
|
|
||||||||||
| backend_servers = [] | ||||||||||
| backend_servers_local = [] | ||||||||||
| backend_port = nil | ||||||||||
|
|
@@ -324,6 +333,12 @@ global | |||||||||
| <%- if backend_match_http_protocol && backends.length == 2 -%> | ||||||||||
| set-var proc.h2_alpn_tag str(h2) | ||||||||||
| <%- end -%> | ||||||||||
| <%- if_p("ha_proxy.connections_rate_limit.table_size", "ha_proxy.connections_rate_limit.window_size") do -%> | ||||||||||
| <%- if_p("ha_proxy.connections_rate_limit.connections") do |conn_rate_connections| -%> | ||||||||||
| set-var proc.connections_rate_limit_connections int(<%= conn_rate_connections %>) | ||||||||||
| <%- end -%> | ||||||||||
|
Comment on lines
+337
to
+339
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did I understand correctly that the existence of
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We store the value from the manifest in a process-level variable if defined. If not, it can be set via the socket later. We cannot set the default value to 0, as 0 is a very wrong threshold. |
||||||||||
| set-var proc.connections_rate_limit_block bool(<%= p("ha_proxy.connections_rate_limit.block", false) %>) | ||||||||||
| <%- end -%> | ||||||||||
| <%- if p("ha_proxy.always_allow_body_http10") %> | ||||||||||
| h1-accept-payload-with-any-method | ||||||||||
| <%- end %> | ||||||||||
|
|
@@ -437,11 +452,8 @@ frontend http-in | |||||||||
| tcp-request <%= tcp_request_phase %> reject if layer4_block | ||||||||||
| <%- if_p("ha_proxy.connections_rate_limit.table_size", "ha_proxy.connections_rate_limit.window_size") do -%> | ||||||||||
| tcp-request <%= tcp_request_phase %> track-sc0 src table st_tcp_conn_rate | ||||||||||
| <%- if_p("ha_proxy.connections_rate_limit.block", "ha_proxy.connections_rate_limit.connections") do |block, connections| -%> | ||||||||||
| <%-if block -%> | ||||||||||
| tcp-request <%= tcp_request_phase %> reject if { sc_conn_rate(0) gt <%= connections %> } | ||||||||||
| <%- end -%> | ||||||||||
| <%- end -%> | ||||||||||
| # use sub() converter as variable references are only accepted as arguments to converters | ||||||||||
| tcp-request <%= tcp_request_phase %> reject if { var(proc.connections_rate_limit_block) -m bool } { var(proc.connections_rate_limit_connections) -m int gt 0 } { sc_conn_rate(0),sub(proc.connections_rate_limit_connections) gt 0 } | ||||||||||
| <%- end -%> | ||||||||||
| <%- if_p("ha_proxy.requests_rate_limit.table_size", "ha_proxy.requests_rate_limit.window_size") do -%> | ||||||||||
| http-request track-sc1 src table st_http_req_rate | ||||||||||
|
|
@@ -571,11 +583,8 @@ frontend https-in | |||||||||
| tcp-request <%= tcp_request_phase %> reject if layer4_block | ||||||||||
| <%- if_p("ha_proxy.connections_rate_limit.table_size", "ha_proxy.connections_rate_limit.window_size") do -%> | ||||||||||
| tcp-request <%= tcp_request_phase %> track-sc0 src table st_tcp_conn_rate | ||||||||||
| <%- if_p("ha_proxy.connections_rate_limit.block", "ha_proxy.connections_rate_limit.connections") do |block, connections| -%> | ||||||||||
| <%-if block -%> | ||||||||||
| tcp-request <%= tcp_request_phase %> reject if { sc_conn_rate(0) gt <%= connections %> } | ||||||||||
| <%- end -%> | ||||||||||
| <%- end -%> | ||||||||||
| # use sub() converter as variable references are only accepted as arguments to converters | ||||||||||
| tcp-request <%= tcp_request_phase %> reject if { var(proc.connections_rate_limit_block) -m bool } { var(proc.connections_rate_limit_connections) -m int gt 0 } { sc_conn_rate(0),sub(proc.connections_rate_limit_connections) gt 0 } | ||||||||||
| <%- end -%> | ||||||||||
| <%- if_p("ha_proxy.requests_rate_limit.table_size", "ha_proxy.requests_rate_limit.window_size") do -%> | ||||||||||
| http-request track-sc1 src table st_http_req_rate | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make the two new
proc.variables more prominent, by introducing them in an unsorted list, similar to the variables and options listed in the section "Configuration Options". It was first a bit hard for me to understand why we have these proc variables now.One point about the naming:
connections_rate_limit.block->proc.conn_rate_blockconnections_rate_limit.connections->proc.conn_rate_limitIs inconsistent. If we could still change the it and accept it's breaking, I'd prefer the following variable naming:
connection_rate_limit.enabled->proc.connection_rate_limit_enabledconnection_rate_limit.connections->proc.connection_rate_limit_connectionsThis would be more consistent, and having
enabledinstead ofblockindicates that this is a boolean switch.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed variables:
connection_rate_limit.block -> proc.connection_rate_limit_block
connection_rate_limit.connections -> proc.connection_rate_limit_connections
Enhanced the documentation