Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions internal/gatewayapi/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,10 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource
// refers to the Listener TLS.
TLS: irTLSConfigsForTCPListener(&listener.tls),
}
// TLS listeners support hostname-based (SNI) matching; TCP does not.
if listener.Protocol == gwapiv1.TLSProtocolType && listener.Hostname != nil {
irListener.Hostnames = append(irListener.Hostnames, string(*listener.Hostname))
}
xdsIR[irKey].TCP = append(xdsIR[irKey].TCP, irListener)
case gwapiv1.UDPProtocolType:
irListener := &ir.UDPListener{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- foo.bar.com
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- foo.bar.com
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ xdsIR:
privateKey: '[redacted]'
- address: 0.0.0.0
externalPort: 90
hostnames:
- foo.bar.com
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- foo.com
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- '*.example.com'
metadata:
kind: Gateway
name: gateway-1
Expand Down Expand Up @@ -344,6 +346,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- '*.com'
metadata:
kind: Gateway
name: gateway-2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 443
hostnames:
- www.example.com
metadata:
kind: Gateway
name: gateway-tls-exact-hostname
Expand Down Expand Up @@ -603,6 +605,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 443
hostnames:
- '*.example.com'
metadata:
kind: Gateway
name: gateway-tls-wildcard-hostname
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 443
hostnames:
- '*.example.com'
metadata:
kind: Gateway
name: gateway-tlsroute-referencegrant
Expand Down
2 changes: 2 additions & 0 deletions internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- foo.com
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- foo.com
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- '*.example.com'
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- foo.example.com
metadata:
kind: Gateway
name: gateway-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ xdsIR:
tcp:
- address: 0.0.0.0
externalPort: 90
hostnames:
- '*.example.com'
metadata:
kind: Gateway
name: gateway-1
Expand Down
2 changes: 2 additions & 0 deletions internal/ir/xds.go
Original file line number Diff line number Diff line change
Expand Up @@ -2382,6 +2382,8 @@ func (s StringMatch) Validate() error {
// +k8s:deepcopy-gen=true
type TCPListener struct {
CoreListenerDetails `json:",inline" yaml:",inline"`
// Hostnames (SNI/server name) with which the service can be expected to be accessed by clients.
Hostnames []string `json:"hostnames,omitempty" yaml:"hostnames,omitempty"`
// TLS holds information for configuring TLS on a listener.
TLS *TLSConfig `json:"tls,omitempty" yaml:"tls,omitempty"`
// TCPKeepalive configuration for the listener
Expand Down
5 changes: 5 additions & 0 deletions internal/ir/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
http:
- name: "https-listener"
address: "0.0.0.0"
port: 10443
hostnames:
- "*"
path:
mergeSlashes: true
escapedSlashesAction: UnescapeAndRedirect
tls:
alpnProtocols:
- h2
- http/1.1
certificates:
- name: secret-1
certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97]
privateKey: [107, 101, 121, 45, 100, 97, 116, 97]
routes:
- name: "first-route"
hostname: "*"
destination:
name: "first-route-dest"
settings:
- endpoints:
- host: "1.2.3.4"
port: 50000
name: "first-route-dest/backend/0"
tcp:
- name: "tls-terminate-no-routes"
address: "0.0.0.0"
port: 10443
hostnames:
- "repro.example.com"
tls:
certificates:
- name: secret-1
certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97]
privateKey: [107, 101, 121, 45, 100, 97, 116, 97]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
- circuitBreakers:
thresholds:
- maxRetries: 1024
commonLbConfig: {}
connectTimeout: 10s
dnsLookupFamily: V4_PREFERRED
edsClusterConfig:
edsConfig:
ads: {}
resourceApiVersion: V3
serviceName: first-route-dest
ignoreHealthOnHostRemoval: true
loadBalancingPolicy:
policies:
- typedExtensionConfig:
name: envoy.load_balancing_policies.least_request
typedConfig:
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
localityLbConfig:
localityWeightedLbConfig: {}
name: first-route-dest
perConnectionBufferLimitBytes: 32768
type: EDS
- name: EmptyCluster
type: STATIC
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
- clusterName: first-route-dest
endpoints:
- lbEndpoints:
- endpoint:
address:
socketAddress:
address: 1.2.3.4
portValue: 50000
loadBalancingWeight: 1
loadBalancingWeight: 1
locality:
region: first-route-dest/backend/0
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
- address:
socketAddress:
address: 0.0.0.0
portValue: 10443
filterChains:
- filters:
- name: envoy.filters.network.http_connection_manager
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
commonHttpProtocolOptions:
headersWithUnderscoresAction: REJECT_REQUEST
http2ProtocolOptions:
initialConnectionWindowSize: 1048576
initialStreamWindowSize: 65536
maxConcurrentStreams: 100
httpFilters:
- name: envoy.filters.http.router
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
suppressEnvoyHeaders: true
mergeSlashes: true
normalizePath: true
pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT
rds:
configSource:
ads: {}
resourceApiVersion: V3
routeConfigName: https-listener
serverHeaderTransformation: PASS_THROUGH
statPrefix: https-10443
useRemoteAddress: true
name: https-listener
transportSocket:
name: envoy.transport_sockets.tls
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
commonTlsContext:
alpnProtocols:
- h2
- http/1.1
tlsCertificateSdsSecretConfigs:
- name: secret-1
sdsConfig:
ads: {}
resourceApiVersion: V3
disableStatefulSessionResumption: true
disableStatelessSessionResumption: true
- filterChainMatch:
serverNames:
- repro.example.com
filters:
- name: envoy.filters.network.tcp_proxy
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: EmptyCluster
statPrefix: tls-passthrough-10443
name: EmptyCluster/tls-terminate-no-routes
listenerFilters:
- name: envoy.filters.listener.tls_inspector
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
maxConnectionsToAcceptPerSocketEvent: 1
name: https-listener
perConnectionBufferLimitBytes: 32768
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- ignorePortInHostMatching: true
name: https-listener
virtualHosts:
- domains:
- '*'
name: https-listener/*
routes:
- match:
prefix: /
name: first-route
route:
cluster: first-route-dest
upgradeConfigs:
- upgradeType: websocket
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- name: secret-1
tlsCertificate:
certificateChain:
inlineBytes: Y2VydC1kYXRh
privateKey:
inlineBytes: a2V5LWRhdGE=
32 changes: 29 additions & 3 deletions internal/xds/translator/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,9 +869,35 @@ func (t *Translator) processTCPListenerXdsTranslation(
}
}

// Only add the filter chain once per xDS listener; multiple IR listeners may share
// the same address/port and map to the same xDS listener.
if !emptyFilterChainAdded[xdsListener.Name] {
if len(tcpListener.Hostnames) > 0 {
// TLS listener with a specific hostname: give the empty filter chain a unique SNI
// match so it does not collide with other wildcard filter chains on the same xDS
// listener (e.g. an HTTPS listener with hostname "*").
emptyTCPRoute := &ir.TCPRoute{
Name: emptyClusterName + "/" + tcpListener.Name,
Destination: &ir.RouteDestination{
Name: emptyClusterName,
},
TLS: &ir.TLS{
TLSInspectorConfig: &ir.TLSInspectorConfig{
SNIs: tcpListener.Hostnames,
},
Comment on lines +881 to +884

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve fingerprint options when adding SNI placeholder

When a hostname-only, no-route TLS listener is processed before another TLS listener on the same address/port that enables JA3/JA4 fingerprints, this new synthetic SNI route causes addXdsTCPFilterChain to install tls_inspector for SNI only. addXdsTLSInspectorFilter returns immediately once an inspector exists, so the later listener's fingerprint flags are never enabled and configured %TLS_JA*_FINGERPRINT% values stay empty. Before this branch, a no-route listener without fingerprints did not install the inspector, so the later listener could enable it; please merge/update existing inspector options when adding this placeholder chain.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Is that the desired behavior? As tls_inspector is a listener filter we can't have per filter chain scope? Maybe it's correct as it is to just install the first. @zirain

},
}
if err := t.addXdsTCPFilterChain(
xdsListener,
emptyTCPRoute,
emptyClusterName,
accesslog,
tcpListener.Timeout,
tcpListener.Connection,
tcpListener.TLS,
); err != nil {
errs = errors.Join(errs, err)
}
} else if !emptyFilterChainAdded[xdsListener.Name] {
// No hostname: add one shared wildcard empty filter chain per xDS listener.
// Multiple IR listeners may share the same address/port and map to the same xDS listener.
if err := t.addXdsTCPFilterChain(
xdsListener,
sharedEmptyTCPRoute,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a duplicate filter chain matcher error when a TLS listener with a specific hostname and no routes shares a port with an HTTPS wildcard listener, which caused Envoy to reject the xDS config update.