GEP-735: TCP and UDP addresses matching

  • Issue: #735
  • Status: Declined

Notes about declined status

At one point before the release of v0.5.0 we did have an implementation of this GEP in main, but we decided to pull back on it for multiple reasons:

  • operated too much like WAF/firewall functionality, which is not in scope
  • no implementations championing the use case

It should also be noted that the maintainers have at least considered the idea of an IPRoute API which would help differentiate this from firewall functionality, however there haven’t been any strong champions for such a use case for this either.

As such this GEP is marked as Declined to make it clear to readers that presently we don’t have plans to include this in any future release. Keep in mind that this doesn’t mean that we wouldn’t consider it again as a future feature however: if you’re interested in this functionality please feel free to start a new github discussion and/or feel free to create a new PR updating this GEP with your use case(s) and context.

TLDR

Spec for matching source and destination addresses on L4 APIs.

Goals

  • add matching rules for address to TCPRoute
  • add matching rules for address to UDPRoute
  • intentionally avoid type definitions that would make it hard to expand later

Non-Goals

  • define rules for port matching

Introduction

While TCPRoute and UDPRoute currently support custom matching extensions, there is desire among the community to include some “fundamental” matching options in the spec that cover the most common requirements. In this GEP we request address matching for these APIs in order to support a standard for some of the commonplace setups of gateway implementations. Matching is intended to be covered for both source and destination to enable a finer level of tuning options for L4 traffic routing at a level below the Gateway.

API

The API changes include the following new types:

  • AddressMatch to indicate the IP for address matching
  • AddressRouteMatches to configure matching according to network address

These types enable the address matching required, with some active considerations about how to leave these open ended for later expansion.

AddressMatch Type

A new AddressMatch type provides the targeting mechanism for match inclusion of a given network address:

  1. type AddressMatch struct {
  2. // Type of the address, either IPAddress or NamedAddress.
  3. //
  4. // If NamedAddress is used this is a custom and specific value for each
  5. // implementation to handle (and add validation for) according to their
  6. // own needs.
  7. //
  8. // For IPAddress the implementor may expect either IPv4 or IPv6.
  9. //
  10. // Support: Core (IPAddress)
  11. // Support: Implementation-specific (NamedAddress)
  12. //
  13. // +optional
  14. // +kubebuilder:validation:Enum=IPAddress;NamedAddress
  15. // +kubebuilder:default=IPAddress
  16. Type *AddressType `json:"type,omitempty"`
  17. // Value of the address. The validity of the values will depend
  18. // on the type and support by the controller.
  19. //
  20. // If implementations support proxy-protocol (see:
  21. // https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) they
  22. // must respect the connection metadata from proxy-protocol
  23. // in the match logic implemented for these address values.
  24. //
  25. // Examples: `1.2.3.4`, `128::1`, `my-named-address`.
  26. //
  27. // Support: Core
  28. //
  29. // +kubebuilder:validation:MinLength=1
  30. // +kubebuilder:validation:MaxLength=253
  31. Value string `json:"value"`
  32. }

AddressRouteMatches Type

Using the new AddressMatch type matches can be expressed in topical lists on TCPRoute and UDPRoute using the new AddressRouteMatches type:

  1. type AddressRouteMatches struct {
  2. // SourceAddresses indicates the originating (source) network
  3. // addresses which are valid for routing traffic.
  4. //
  5. // Support: Core
  6. SourceAddresses []AddressMatch `json:"sourceAddresses"`
  7. // DestinationAddresses indicates the destination network addresses
  8. // which are valid for routing traffic.
  9. //
  10. // Support: Core
  11. DestinationAddresses []AddressMatch `json:"destinationAddresses"`
  12. }

This type becomes an optional field and shared by both TCPRouteRule and UDPRouteRule as a list:

  1. type TCPRouteRule struct {
  2. // Matches add rules for filtering traffic to backends based on addresses.
  3. //
  4. // +optional
  5. Matches []AddressRouteMatches `json:"matches,omitempty"`
  6. }

Each element in []AddressRouteMatches should be implemented as an OR style match (e.g. the inbound traffic matches as long as at least one of the separate AddressRouteMatches rules is matched).

The above would make the following YAML examples possible:

  1. apiVersion: gateway.networking.k8s.io/v1alpha2
  2. kind: TCPRoute
  3. metadata:
  4. name: matching
  5. spec:
  6. rules:
  7. - matches:
  8. - sourceAddresses:
  9. - value: "192.168.1.1"
  10. - value: "FE80::0202:B3FF:FE1E:8329"
  11. - type: NamedAddress
  12. value: "my-custom-name"
  13. destinationAddresses:
  14. - value: "10.96.0.1"
  15. backendRefs:
  16. - name: my-service
  17. port: 8080

Alternatives

Pure Gateway Mode

Technically the existing specification supported this kind of matching through Gateway object Listeners and it was considered to simply document that further and expand upon it, but in a desire to better support more complex setups that are becoming commonplace in the ecosystem (e.g. service mesh) there was sufficient cause to add this functionality at the route level.

Copying NetworkPolicy

After the first draft of this document we consulted the NetworkPolicy API to determine if there were enough similarities to copy some of the semantics there to here. Both the existing API and (at the time of writing) the upcoming API were reviewed. Ultimately some influence was taken from NetworkPolicyPort to define the PolicyMatch structure here, but some ideas such as binding ports and network addresses together in a single struct did not seem necessary as the RuleAction present in policy did not seem applicable for this work at the time. We may want to revisit this as the new policy work merges and matures.

Port Matching

While we were able to think of some cases for port matching, the constraints of listeners for the Gateway make it much harder to understand the value at this stage. We’re deferring port matching to focus on address matching for this iteration so that we can come back around to it separately once we’ve gathered more use case information.

CIDR AddressType

When using AddressType as a component to AddressMatch it was considered to add a new type CIDRAddress which would allow matching against an entire subnet. This sounds good, but given a lack of concrete feedback on an immediate need for this in the original issue #727 it was decided that this could wait for now and just as easily be added later in a backwards compatible manner.

References

A related conversation in #727 ultimately instigated these new requirements and may be helpful to review.