Skip to content

Conversation

@rudrakhp
Copy link
Member

@rudrakhp rudrakhp commented Jan 4, 2026

Commit Message: [api] support rate limit action based on cidr match
Additional Description: Proposed API changes to support rate limit actions on remote address match. This includes additions of a new rate limit action RemoteAddressMatch as well as inclusion of a CIDR matcher in the MaskedRemoteAddress action.
Risk Level: Low (doesn't break/affect existing usecases)
Testing: N/A (API changes only)
Docs Changes: N/A
Release Notes: N/A
Platform Specific Features: N/A
[Optional Runtime guard:]
Related #36442
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
Optional API Considerations:

  • RemoteAddressMatch rate limit action will cater to most usecases, including for request's remote address using %DOWNSTREAM_REMOTE_ADDRESS%.
  • But address matcher is required as an additional param in MaskedRemoteAddress rate limit action as this usecases can't be directly supported in RemoteAddressMatch.
  • Reusing existing type.matcher.v3.AddressMatcher. Might need to implement invert_match in existing usage at FilterStateIpRangeMatcher::match.

@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to (api/envoy/|docs/root/api-docs/).
envoyproxy/api-shepherds assignee is @adisuissa
CC @envoyproxy/api-watchers: FYI only for changes made to (api/envoy/|docs/root/api-docs/).

🐱

Caused by: #42845 was opened by rudrakhp.

see: more, trace.

Copy link
Member

@agrawroh agrawroh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curios, why can't we use the existing Dynamic Metadata for this? It should be trivial to write Dynamic Metadata for Remote Address and use that instead right?

@rudrakhp
Copy link
Member Author

rudrakhp commented Jan 5, 2026

@agrawroh the challenge here is not to apply rate limits to remote address ,in fact we already have the RemoteAddress rate limit action for this and can also use GenericKey with CEL without any dynamic metadata. But the usecase here is to apply different rate limits to remote addresses matching on some CIDRs. See the referred issue #36442 and also the related envoyproxy/gateway#4385 issue.

@rudrakhp rudrakhp requested a review from agrawroh January 5, 2026 04:05
Copy link
Member

@wbpcode wbpcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution and some comments are added.

Comment on lines +2221 to +2229
// [#not-implemented-hide:]
// Specifies an address matcher that controls whether the rate limit action is applied.
// The matcher checks the remote address (trusted address from
// :ref:`x-forwarded-for <config_http_conn_man_headers_x-forwarded-for>`)
// against the specified CIDR ranges. The rate limit action will be applied if
// the remote address matches any of the CIDR ranges (or does not match any if
// ``invert_match`` is set to true in the address matcher). If this field is not
// specified, the rate limit action will be applied to all remote addresses.
type.matcher.v3.AddressMatcher address_matcher = 3;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wbpcode While the original use case can be handled by RemoteAddressMatcher:

I have usecase that I should add ratelimiting to all addresses (0.0.0.0/0) EXCEPT few "whitelisted ips".

It cannot handle a slightly modified usecase where the rate limit bucket needs to be shared among IPs with common prefix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will suggest to use the RemoteAddressMatch to cover this case and it should be possible?

Copy link
Member Author

@rudrakhp rudrakhp Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wbpcode here is a more concrete usecase that I don't see how to solve using RemoteAddressMatcher, please do correct me if I am wrong:
To apply rate limiting based on a masked network prefix while exempting specific CIDR ranges from being aggregated into that limit.
E.g.

  • [This is not possible in RemoteAddressMatcher] When processing traffic from remote addresses 10.1.1.2, 10.1.1.15 or 10.1.10.23, it must generate the same descriptor so as to consume from the same 10.1.0.0/16 rate limit bucket.
  • But it must also have a whitelist so this descriptor is not created for 10.1.2.0/24 and bypasses rate limit. So if remote address is 10.1.2.58, although it is in the 10.1.0.0/16 range, rate limit descriptor will be skipped.

Comment on lines +2474 to +2520
// The following descriptor entry is appended to the descriptor:
//
// .. code-block:: cpp
//
// ("remote_address_match", "<descriptor_value>")
// [#not-implemented-hide:]
message RemoteAddressMatch {
// Descriptor value of entry.
//
// The same :ref:`format specifier <config_access_log_format>` as used for
// :ref:`HTTP access logging <config_access_log>` applies here, however
// unknown specifier values are replaced with the empty string instead of ``-``.
//
// .. note::
//
// The format string can contain multiple valid substitution fields. If multiple substitution
// fields are present, their results will be concatenated to form the final descriptor value.
// If it contains no substitution fields, the value will be used as is.
// All substitution fields will be evaluated and their results concatenated.
// If the final concatenated result is empty and ``default_value`` is set, the ``default_value`` will be used.
// If ``default_value`` is not set and the result is empty, this descriptor will be skipped
// and not included in the rate limit call.
//
// For example, ``static_value`` will be used as is since there are no substitution fields.
// ``%REQ(:method)%`` will be replaced with the HTTP method, and
// ``%REQ(:method)%%REQ(:path)%`` will be replaced with the concatenation of the HTTP method and path.
// ``%CEL(request.headers['user-id'])%`` will use CEL to extract the user ID from request headers.
//
string descriptor_value = 1 [(validate.rules).string = {min_len: 1}];

// The key to use in the descriptor entry.
//
// Defaults to ``remote_address_match``.
string descriptor_key = 2;

// An optional value to use if the final concatenated ``descriptor_value`` result is empty.
string default_value = 3;

// Specifies an address matcher that controls whether the rate limit action is applied.
// The matcher checks the remote address (trusted address from
// :ref:`x-forwarded-for <config_http_conn_man_headers_x-forwarded-for>`)
// against the specified CIDR ranges. The rate limit action will be applied if
// the remote address matches any of the CIDR ranges (or does not match any if
// ``invert_match`` is set to true in the address matcher).
type.matcher.v3.AddressMatcher address_matcher = 4
[(validate.rules).message = {required: true}];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I want.

@rudrakhp rudrakhp requested a review from wbpcode January 6, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants