Skip to content
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

listener: filter chain unified matchers #18871

Closed
Closed
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6a37223
[wip] Add filter chain match predicate order
kyessenov Nov 2, 2021
8aa165f
spelling
kyessenov Nov 2, 2021
cfdb93a
review
kyessenov Nov 5, 2021
a13ed92
review
kyessenov Nov 5, 2021
621fcbf
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Nov 8, 2021
2228fef
review
kyessenov Nov 8, 2021
b610420
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Nov 12, 2021
f45bc06
review
kyessenov Nov 15, 2021
bada313
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Nov 15, 2021
3f8f8e4
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Nov 17, 2021
937f7a8
review
kyessenov Nov 17, 2021
9fd0f34
review
kyessenov Nov 17, 2021
595eb18
add move note
kyessenov Nov 22, 2021
7d7909a
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Nov 22, 2021
9a56f14
merge fix
kyessenov Nov 29, 2021
262d084
merge
kyessenov Nov 29, 2021
76e5040
more review
kyessenov Dec 1, 2021
3b92ec5
typo
kyessenov Dec 1, 2021
03fbfc6
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Dec 15, 2021
ddeeaf9
update
kyessenov Dec 15, 2021
be4636d
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Jan 7, 2022
72b978e
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Feb 1, 2022
e981df6
review
kyessenov Feb 1, 2022
a9b056a
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Feb 2, 2022
987a2fd
Merge remote-tracking branch 'upstream/main' into extensible_filter_c…
kyessenov Feb 17, 2022
0185225
try validation
kyessenov Feb 18, 2022
d1c8f75
verify example
kyessenov Feb 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/envoy/config/listener/v3/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ api_proto_package(
"//envoy/type/v3:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
"@com_github_cncf_udpa//xds/core/v3:pkg",
"@com_github_cncf_udpa//xds/type/matcher/v3:pkg",
],
)
27 changes: 26 additions & 1 deletion api/envoy/config/listener/v3/listener.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package envoy.config.listener.v3;
import "envoy/config/accesslog/v3/accesslog.proto";
import "envoy/config/core/v3/address.proto";
import "envoy/config/core/v3/base.proto";
import "envoy/config/core/v3/extension.proto";
import "envoy/config/core/v3/socket_option.proto";
import "envoy/config/listener/v3/api_listener.proto";
import "envoy/config/listener/v3/listener_components.proto";
Expand All @@ -14,6 +15,7 @@ import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "xds/core/v3/collection_entry.proto";
import "xds/type/matcher/v3/matcher.proto";

import "envoy/annotations/deprecation.proto";
import "udpa/annotations/security.proto";
Expand All @@ -35,7 +37,7 @@ message ListenerCollection {
repeated xds.core.v3.CollectionEntry entries = 1;
}

// [#next-free-field: 32]
// [#next-free-field: 34]
message Listener {
option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.Listener";

Expand Down Expand Up @@ -119,6 +121,29 @@ message Listener {
// :ref:`FAQ entry <faq_how_to_setup_sni>`.
repeated FilterChain filter_chains = 3;

// A filter chain matcher resolving the filter chain name based on the connection properties.
// The following inputs are supported by the matcher:
Copy link
Member

Choose a reason for hiding this comment

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

More docs here and some examples? Also discuss how various fields would now be ignored/deprecated for review clarity?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added blurb about about not using old field if this is enabled. Will follow up with worked out example once we agree on the structure.

//
// 1. :ref:`DestinationPort <envoy_v3_api_msg_config.listener.v3.DestinationPortInput>`.
// 2. :ref:`DestinationIP <envoy_v3_api_msg_config.listener.v3.DestinationIPInput>`.
// 3. :ref:`SNI <envoy_v3_api_msg_config.listener.v3.SNIInput>`.
// 4. :ref:`TransportProtocol <envoy_v3_api_msg_config.listener.v3.TransportProtocolInput>`.
// 5. :ref:`ApplicationProtocol <envoy_v3_api_msg_config.listener.v3.ApplicationProtocolInput>`.
// 6. :ref:`DirectSourceIP <envoy_v3_api_msg_config.listener.v3.DirectSourceIPInput>`.
// 7. :ref:`SourceType <envoy_v3_api_msg_config.listener.v3.SourceTypeInput>`.
// 8. :ref:`SourceIP <envoy_v3_api_msg_config.listener.v3.SourceIPInput>`.
// 9. :ref:`SourcePort <envoy_v3_api_msg_config.listener.v3.SourcePortInput>`.
//
// If specified, all :ref:`filter_chains <envoy_v3_api_field_config.listener.v3.Listener.filter_chains>` must
// have a non-empty :ref:`name <envoy_v3_api_field_config.listener.v3.FilterChain.name>` and empty :ref:`filter_chain_match <envoy_v3_api_msg_config.listener.v3.FilterChain.filter_chain_match>`.
// [#not-implemented-hide:]
Copy link
Member

Choose a reason for hiding this comment

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

I see this configuration as being one of the ones that will be very difficult for users to actually piece together without examples. Can we make sure that somehow we wire up the extension docs system here so that this somehow lists out all supported match inputs and relevant typed configs, etc.? We need to guide users much more specifically on how to use this new field.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree, we need more examples. I can add some but I'd really need #19493 merged first for protos to become available. There is an issue with cncf/xds protos not being documented.

repeated xds.type.matcher.v3.Matcher filter_chain_matcher = 32;

// Defines the discovery service configuration for filter chains indexed by the filter chain name.
// The set of filter chain names must be disjoint from the filter chain names in the field :ref:`filter_chains <envoy_v3_api_field_config.listener.v3.Listener.filter_chains>`.
Copy link
Member

Choose a reason for hiding this comment

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

I'm having a hard time parsing this. Can you expand?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we should drop ECDS parts from this discussion. Is it OK that I just drop this config source aspect for now?

// [#not-implemented-hide:]
map<string, core.v3.ExtensionConfigSource> filter_chain_discovery = 33;

// If a connection is redirected using *iptables*, the port on which the proxy
// receives it might be different from the original destination address. When this flag is set to
// true, the listener hands off redirected connections to the listener associated with the
Expand Down
163 changes: 163 additions & 0 deletions api/envoy/config/listener/v3/listener_components.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "xds/type/matcher/v3/matcher.proto";

import "envoy/annotations/deprecation.proto";
import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";
Expand Down Expand Up @@ -357,3 +359,164 @@ message ListenerFilter {
// for further examples.
ListenerFilterChainMatchPredicate filter_disabled = 4;
}

// Matcher input that allows matching connections by by the destination port.
message DestinationPortInput {
}

// Matcher input that allows matching connections by by the destination IP address.
message DestinationIPInput {
}

// Matcher input that allows matching connections by by the source IP address.
message SourceIPInput {
}

// Matcher input that allows matching connections by by the directly connected source IP address (this
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Matcher input that allows matching connections by by the directly connected source IP address (this
// Matcher input that allows matching connections by the directly connected source IP address (this

Copy link
Member

Choose a reason for hiding this comment

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

(Same typo exists elsewhere in this file)

// will only be different from the source IP address when using a listener
// filter that overrides the source address, such as the :ref:`Proxy Protocol
// listener filter <config_listener_filters_proxy_protocol>`).
message DirectSourceIPInput {
}

// Matcher input that allows matching connections by by the source port.
message SourcePortInput {
}

// Matcher input that allows matching connections by by the connection source IP type.
// Specifies the connection source IP match type. The values include:
//
// * ``any`` - any connection source,
// * ``local`` - matches a connection originating from the same host,
// * ``external`` - matches a connection originating from a different host
message SourceTypeInput {
}

// Matcher input that allows matching connections by by the server names of a new connection, when detected by one of the listener filters.
message SNIInput {
}

// Matcher input that allows matching connections by by the transport protocol.
// This value will be compared against the transport protocol of a new connection, when
// it's detected by one of the listener filters.
//
// Suggested values include:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Suggested values include:
// Standard values include:

(Or something like that, same below for ALPN)

//
// * ``raw_buffer`` - default, used when no transport protocol is detected,
// * ``tls`` - set by :ref:`envoy.filters.listener.tls_inspector <config_listener_filters_tls_inspector>`
// when TLS protocol is detected.
message TransportProtocolInput {
}

// Matcher input that allows matching connections by by the application protocol (e.g. ALPN for TLS protocol).
// This values will be compared against the application
// protocols of a new connection, when detected by one of the listener filters.
//
// Suggested values include:
//
// * ``http/1.1`` - set by :ref:`envoy.filters.listener.tls_inspector
// <config_listener_filters_tls_inspector>` and :ref:`envoy.filters.listener.http_inspector
// <config_listener_filters_http_inspector>`,
// * ``h2`` - set by :ref:`envoy.filters.listener.tls_inspector <config_listener_filters_tls_inspector>` and :ref:`envoy.filters.listener.http_inspector <config_listener_filters_http_inspector>`
//
// .. attention::
//
// Currently, :ref:`TLS Inspector <config_listener_filters_tls_inspector>` provides
// application protocol detection based on the requested
// `ALPN <https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation>`_ values.
//
// However, the use of ALPN is pretty much limited to the HTTP/2 traffic on the Internet,
// and matching on values other than ``h2`` is going to lead to a lot of false negatives,
// unless all connecting clients are known to use ALPN.
message ApplicationProtocolInput {
}

// Matches a specific port against a set of possibly overlapping port ranges.
Copy link
Member

Choose a reason for hiding this comment

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

For each of the new matchers, can you document the match complexity and/or the rough implementation? I think it's important that the user understand the time complexity of multiple values, where there are specific rules like most specific matches, etc. (This comment applies here and elsewhere)

// TODO(kuat) Move to cncf/xds.
message PortMatcher {
// Specifies an optional list of port ranges and a match action.
message PortRangeMatcher {
// Optional set of port ranges. An empty set matches any port.
repeated type.v3.Int32Range ranges = 1;

// Match action to apply when the port is within one of the port ranges.
xds.type.matcher.v3.Matcher.OnMatch on_match = 2;
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved

// Indicates whether this match option should be considered if there is a
// matcher for the specific port value. For example, consider a matcher
// for the port range [1, 1000] applied to a specific port 80. If there
// is another matcher for the specific port 80 that fully matches, then
// the specific port matcher is selected. However, if the specific port
// matcher does not fully match, then the behavior depends on whether the
// range matcher [1, 1000] is exclusive. Exclusive port matchers do not
// apply when there is a more specific port match. Non-exclusive port
// matchers may apply when the nested match conditions are satisfied for
// the range matcher but not for the specific port value nested matcher.
//
// The order of range matchers is important since it dictates the order
// of matching in case of overlapping port ranges.
bool exclusive = 3;
}

// Match port by value. Takes precedence over matching by the port ranges.
map<int32, xds.type.matcher.v3.Matcher.OnMatch> port_map = 1;

// Match port by port ranges.
repeated PortRangeMatcher range_matchers = 2;
}

// Matches a specific IP address against a set of possibly overlapping subnets.
// TODO(kuat) Move to cncf/xds.
message IPMatcher {
// Specifies an optional list of IP address ranges and a match action.
message IPRangeMatcher {
// Optional set of CIDR ranges. An empty set matches any IP address.
repeated core.v3.CidrRange ranges = 1;

// Match action to apply when the IP address is within one of the CIDR ranges.
xds.type.matcher.v3.Matcher.OnMatch on_match = 2;

// Indicates whether this match option should be considered if there is a
// more specific matcher. Exclusive matchers are not selected whenever a
// more specific matcher exists (e.g. matcher with a longer prefix) even
// when the more specific matcher fails its nested match condition.
// Non-exclusive matchers are considered if the more specific matcher
// exists but its nested match condition does not entirely match.
// Non-exclusive matchers are selected in the order of their specificity
// first (longest prefix first), then the order of declaration next.
bool exclusive = 3;
}

// Match IP address by CIDR ranges.
repeated IPRangeMatcher range_matchers = 1;
}

// Matches a specific server name against of a set of possibly overlapping wildcard domains.
// TODO(kuat) Move to cncf/xds.
message ServerNameMatcher {
// Specifies an optional list of wildcard domains and a match action.
// The server name will be matched against all wildcard domains, i.e. ``www.example.com``
// will be first matched against ``www.example.com``, then ``*.example.com``, then ``*.com``.
//
// Note that partial wildcards are not supported, and values like ``*w.example.com`` are invalid.
message DomainMatcher {
// Optional set of wildcard domains. An empty set matches any server name.
repeated string server_names = 1;

// Match action to apply when the server name matches.
xds.type.matcher.v3.Matcher.OnMatch on_match = 2;

// Indicates whether this match option should be considered if there is a
// more specific matcher. Exclusive matches are not selected whenever a
// more specific matcher exists even when the more specific matcher fails
// to match its nested match condition. For example, an exclusive matcher
// for ```*.com``` does not match ``www.example.com``` if there is a
// matcher for ```*.example.com```. Matchers are selected in the order of
// their specificity first (longest suffix first), then
// the order of declaration next.
bool exclusive = 3;
}

// Match server name by wildcard domains.
repeated DomainMatcher domain_matchers = 1;
}