Skip to content

Commit 2685e00

Browse files
committed
Add disable SNI host validation field
1 parent 9308f2c commit 2685e00

File tree

13 files changed

+105
-15
lines changed

13 files changed

+105
-15
lines changed

apis/v1alpha2/nginxproxy_types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ type NginxProxySpec struct {
7373
//
7474
// +optional
7575
DisableHTTP2 *bool `json:"disableHTTP2,omitempty"`
76+
// DisableSNIHostValidation disables the validation that ensures the SNI hostname
77+
// matches the Host header in HTTPS requests. When disabled, HTTPS connections can
78+
// be reused for requests to different hostnames covered by the same certificate.
79+
// This resolves HTTP/2 connection coalescing issues with wildcard certificates but
80+
// introduces security risks as described in Gateway API GEP-3567.
81+
// If not specified, defaults to false (validation enabled).
82+
//
83+
// +optional
84+
DisableSNIHostValidation *bool `json:"disableSNIHostValidation,omitempty"`
7685
// Kubernetes contains the configuration for the NGINX Deployment and Service Kubernetes objects.
7786
//
7887
// +optional

apis/v1alpha2/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/nginx-gateway-fabric/values.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@
106106
"required": [],
107107
"type": "boolean"
108108
},
109+
"disableSNIHostValidation": {
110+
"description": "DisableSNIHostValidation disables the validation that ensures the SNI hostname matches the Host header in HTTPS requests. This resolves HTTP/2 connection coalescing issues with wildcard certificates but introduces security risks as described in Gateway API GEP-3567.",
111+
"required": [],
112+
"type": "boolean"
113+
},
109114
"ipFamily": {
110115
"description": "IPFamily specifies the IP family to be used by the NGINX.",
111116
"enum": [

charts/nginx-gateway-fabric/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ nginx:
251251
# disableHTTP2:
252252
# description: DisableHTTP2 defines if http2 should be disabled for all servers.
253253
# type: boolean
254+
# disableSNIHostValidation:
255+
# description: DisableSNIHostValidation disables the validation that ensures the SNI hostname matches the Host header in HTTPS requests. This resolves HTTP/2 connection coalescing issues with wildcard certificates but introduces security risks as described in Gateway API GEP-3567.
256+
# type: boolean
254257
# ipFamily:
255258
# description: IPFamily specifies the IP family to be used by the NGINX.
256259
# type: string

config/crd/bases/gateway.nginx.org_nginxproxies.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ spec:
5656
DisableHTTP2 defines if http2 should be disabled for all servers.
5757
If not specified, or set to false, http2 will be enabled for all servers.
5858
type: boolean
59+
disableSNIHostValidation:
60+
description: |-
61+
DisableSNIHostValidation disables the validation that ensures the SNI hostname
62+
matches the Host header in HTTPS requests. When disabled, HTTPS connections can
63+
be reused for requests to different hostnames covered by the same certificate.
64+
This resolves HTTP/2 connection coalescing issues with wildcard certificates but
65+
introduces security risks as described in Gateway API GEP-3567.
66+
If not specified, defaults to false (validation enabled).
67+
type: boolean
5968
ipFamily:
6069
default: dual
6170
description: |-

deploy/crds.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,15 @@ spec:
641641
DisableHTTP2 defines if http2 should be disabled for all servers.
642642
If not specified, or set to false, http2 will be enabled for all servers.
643643
type: boolean
644+
disableSNIHostValidation:
645+
description: |-
646+
DisableSNIHostValidation disables the validation that ensures the SNI hostname
647+
matches the Host header in HTTPS requests. When disabled, HTTPS connections can
648+
be reused for requests to different hostnames covered by the same certificate.
649+
This resolves HTTP/2 connection coalescing issues with wildcard certificates but
650+
introduces security risks as described in Gateway API GEP-3567.
651+
If not specified, defaults to false (validation enabled).
652+
type: boolean
644653
ipFamily:
645654
default: dual
646655
description: |-

internal/controller/nginx/config/http/config.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ type ProxySSLVerify struct {
127127

128128
// ServerConfig holds configuration for an HTTP server and IP family to be used by NGINX.
129129
type ServerConfig struct {
130-
Servers []Server
131-
RewriteClientIP shared.RewriteClientIPSettings
132-
IPFamily shared.IPFamily
133-
Plus bool
130+
Servers []Server
131+
RewriteClientIP shared.RewriteClientIPSettings
132+
IPFamily shared.IPFamily
133+
Plus bool
134+
DisableSNIHostValidation bool
134135
}

internal/controller/nginx/config/servers.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,11 @@ func (g GeneratorImpl) executeServers(
6161
servers, httpMatchPairs := createServers(conf, generator, keepAliveCheck)
6262

6363
serverConfig := http.ServerConfig{
64-
Servers: servers,
65-
IPFamily: getIPFamily(conf.BaseHTTPConfig),
66-
Plus: g.plus,
67-
RewriteClientIP: getRewriteClientIPSettings(conf.BaseHTTPConfig.RewriteClientIPSettings),
64+
Servers: servers,
65+
IPFamily: getIPFamily(conf.BaseHTTPConfig),
66+
Plus: g.plus,
67+
RewriteClientIP: getRewriteClientIPSettings(conf.BaseHTTPConfig.RewriteClientIPSettings),
68+
DisableSNIHostValidation: conf.BaseHTTPConfig.DisableSNIHostValidation,
6869
}
6970

7071
serverResult := executeResult{

internal/controller/nginx/config/servers_template.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ server {
5555
ssl_certificate {{ $s.SSL.Certificate }};
5656
ssl_certificate_key {{ $s.SSL.CertificateKey }};
5757
58+
{{- if not $.DisableSNIHostValidation }}
5859
if ($ssl_server_name != $host) {
5960
return 421;
6061
}
62+
{{- end }}
6163
{{- else }}
6264
{{- if $.IPFamily.IPv4 }}
6365
listen {{ $s.Listen }}{{ $.RewriteClientIP.ProxyProtocol }};

internal/controller/nginx/config/servers_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4024,3 +4024,41 @@ func TestGetIPFamily(t *testing.T) {
40244024
})
40254025
}
40264026
}
4027+
4028+
func TestExecuteServers_DisableSNIHostValidation(t *testing.T) {
4029+
t.Parallel()
4030+
g := NewWithT(t)
4031+
4032+
sslServer := dataplane.VirtualServer{
4033+
Hostname: "example.com",
4034+
SSL: &dataplane.SSL{
4035+
KeyPairID: "test-keypair",
4036+
},
4037+
Port: 8443,
4038+
}
4039+
gen := GeneratorImpl{}
4040+
4041+
// Case 1: DisableSNIHostValidation = false (default)
4042+
confWithValidation := dataplane.Configuration{
4043+
SSLServers: []dataplane.VirtualServer{sslServer},
4044+
BaseHTTPConfig: dataplane.BaseHTTPConfig{
4045+
DisableSNIHostValidation: false,
4046+
},
4047+
}
4048+
results := gen.executeServers(confWithValidation, &policiesfakes.FakeGenerator{}, alwaysFalseKeepAliveChecker)
4049+
serverConf := string(results[0].data)
4050+
g.Expect(serverConf).To(ContainSubstring("if ($ssl_server_name != $host)"),
4051+
"Expected SNI host validation block to be present when DisableSNIHostValidation is false")
4052+
4053+
// Case 2: DisableSNIHostValidation = true
4054+
confWithoutValidation := dataplane.Configuration{
4055+
SSLServers: []dataplane.VirtualServer{sslServer},
4056+
BaseHTTPConfig: dataplane.BaseHTTPConfig{
4057+
DisableSNIHostValidation: true,
4058+
},
4059+
}
4060+
results = gen.executeServers(confWithoutValidation, &policiesfakes.FakeGenerator{}, alwaysFalseKeepAliveChecker)
4061+
serverConf = string(results[0].data)
4062+
g.Expect(serverConf).NotTo(ContainSubstring("if ($ssl_server_name != $host)"),
4063+
"Expected SNI host validation block to be absent when DisableSNIHostValidation is true")
4064+
}

0 commit comments

Comments
 (0)