Skip to content

Commit 7fd76fb

Browse files
committed
add support for ipv6
1 parent 97fb223 commit 7fd76fb

File tree

12 files changed

+313
-52
lines changed

12 files changed

+313
-52
lines changed

apis/v1alpha1/nginxproxy_types.go

+19
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,31 @@ type NginxProxyList struct {
2727
Items []NginxProxy `json:"items"`
2828
}
2929

30+
// IPFamilyType specifies the IP family to be used by the server.
31+
//
32+
// +kubebuilder:validation:Enum=both;ipv4;ipv6
33+
type IPFamilyType string
34+
35+
const (
36+
// Dual specifies that the server will use both IPv4 and IPv6.
37+
Dual IPFamilyType = "dual"
38+
// IPv4 specifies that the server will use only IPv4.
39+
IPv4 IPFamilyType = "ipv4"
40+
// IPv6 specifies that the server will use only IPv6.
41+
IPv6 IPFamilyType = "ipv6"
42+
)
43+
3044
// NginxProxySpec defines the desired state of the NginxProxy.
3145
type NginxProxySpec struct {
3246
// Telemetry specifies the OpenTelemetry configuration.
3347
//
3448
// +optional
3549
Telemetry *Telemetry `json:"telemetry,omitempty"`
50+
// IPFamily specifies the IP family to be used by the server.
51+
// Default is "both", meaning the server will use both IPv4 and IPv6.
52+
//
53+
// +optional
54+
IPFamily IPFamilyType `json:"ipFamily,omitempty"`
3655
// DisableHTTP2 defines if http2 should be disabled for all servers.
3756
// Default is false, meaning http2 will be enabled for all servers.
3857
//

charts/nginx-gateway-fabric/values.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ nginx:
8484

8585
# -- The configuration for the data plane that is contained in the NginxProxy resource.
8686
config:
87-
{}
8887
# disableHTTP2: false
88+
ipFamily: dual
8989
# telemetry:
9090
# exporter:
9191
# endpoint: otel-collector.default.svc:4317

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

+9
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ spec:
5252
DisableHTTP2 defines if http2 should be disabled for all servers.
5353
Default is false, meaning http2 will be enabled for all servers.
5454
type: boolean
55+
ipFamily:
56+
description: |-
57+
IPFamily specifies the IP family to be used by the server.
58+
Default is "both", meaning the server will use both IPv4 and IPv6.
59+
enum:
60+
- both
61+
- ipv4
62+
- ipv6
63+
type: string
5564
telemetry:
5665
description: Telemetry specifies the OpenTelemetry configuration.
5766
properties:

deploy/crds.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,15 @@ spec:
697697
DisableHTTP2 defines if http2 should be disabled for all servers.
698698
Default is false, meaning http2 will be enabled for all servers.
699699
type: boolean
700+
ipFamily:
701+
description: |-
702+
IPFamily specifies the IP family to be used by the server.
703+
Default is "both", meaning the server will use both IPv4 and IPv6.
704+
enum:
705+
- both
706+
- ipv4
707+
- ipv6
708+
type: string
700709
telemetry:
701710
description: Telemetry specifies the OpenTelemetry configuration.
702711
properties:

internal/mode/static/nginx/config/http/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type Server struct {
1010
IsDefaultHTTP bool
1111
IsDefaultSSL bool
1212
GRPC bool
13+
IPv6Enabled bool
1314
}
1415

1516
// Location holds all configuration for an HTTP location.

internal/mode/static/nginx/config/servers.go

+31-11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
gotemplate "text/template"
1010

11+
ngfAPI "github.com./nginxinc/nginx-gateway-fabric/apis/v1alpha1"
1112
"github.com./nginxinc/nginx-gateway-fabric/internal/framework/helpers"
1213
"github.com./nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/http"
1314
"github.com./nginxinc/nginx-gateway-fabric/internal/mode/static/state/dataplane"
@@ -58,7 +59,8 @@ var grpcBaseHeaders = []http.Header{
5859
}
5960

6061
func executeServers(conf dataplane.Configuration) []executeResult {
61-
servers, httpMatchPairs := createServers(conf.HTTPServers, conf.SSLServers)
62+
ipv6Enabled := isIPv6Enabled(conf.BaseHTTPConfig)
63+
servers, httpMatchPairs := createServers(conf.HTTPServers, conf.SSLServers, ipv6Enabled)
6264

6365
serverResult := executeResult{
6466
dest: httpConfigFile,
@@ -86,6 +88,14 @@ func executeServers(conf dataplane.Configuration) []executeResult {
8688
return allResults
8789
}
8890

91+
// getIPFamily returns whether or not the configuration is set to use IPv6.
92+
func isIPv6Enabled(baseHTTPConfig dataplane.BaseHTTPConfig) bool {
93+
if baseHTTPConfig.IPFamily == ngfAPI.IPv6 || baseHTTPConfig.IPFamily == ngfAPI.Dual {
94+
return true
95+
}
96+
return false
97+
}
98+
8999
func createAdditionFileResults(conf dataplane.Configuration) []executeResult {
90100
uniqueAdditions := make(map[string][]byte)
91101

@@ -141,17 +151,23 @@ func createIncludes(additions []dataplane.Addition) []string {
141151
return includes
142152
}
143153

144-
func createServers(httpServers, sslServers []dataplane.VirtualServer) ([]http.Server, httpMatchPairs) {
154+
func createServers(
155+
httpServers,
156+
sslServers []dataplane.VirtualServer,
157+
ipv6Enabled bool,
158+
) ([]http.Server, httpMatchPairs) {
145159
servers := make([]http.Server, 0, len(httpServers)+len(sslServers))
146160
finalMatchPairs := make(httpMatchPairs)
147161

148162
for serverID, s := range httpServers {
163+
s.IPv6Enabled = ipv6Enabled
149164
httpServer, matchPairs := createServer(s, serverID)
150165
servers = append(servers, httpServer)
151166
maps.Copy(finalMatchPairs, matchPairs)
152167
}
153168

154169
for serverID, s := range sslServers {
170+
s.IPv6Enabled = ipv6Enabled
155171
sslServer, matchPair := createSSLServer(s, serverID)
156172
servers = append(servers, sslServer)
157173
maps.Copy(finalMatchPairs, matchPair)
@@ -165,6 +181,7 @@ func createSSLServer(virtualServer dataplane.VirtualServer, serverID int) (http.
165181
return http.Server{
166182
IsDefaultSSL: true,
167183
Port: virtualServer.Port,
184+
IPv6Enabled: virtualServer.IPv6Enabled,
168185
}, nil
169186
}
170187

@@ -176,10 +193,11 @@ func createSSLServer(virtualServer dataplane.VirtualServer, serverID int) (http.
176193
Certificate: generatePEMFileName(virtualServer.SSL.KeyPairID),
177194
CertificateKey: generatePEMFileName(virtualServer.SSL.KeyPairID),
178195
},
179-
Locations: locs,
180-
Port: virtualServer.Port,
181-
GRPC: grpc,
182-
Includes: createIncludes(virtualServer.Additions),
196+
Locations: locs,
197+
Port: virtualServer.Port,
198+
GRPC: grpc,
199+
Includes: createIncludes(virtualServer.Additions),
200+
IPv6Enabled: virtualServer.IPv6Enabled,
183201
}, matchPairs
184202
}
185203

@@ -188,17 +206,19 @@ func createServer(virtualServer dataplane.VirtualServer, serverID int) (http.Ser
188206
return http.Server{
189207
IsDefaultHTTP: true,
190208
Port: virtualServer.Port,
209+
IPv6Enabled: virtualServer.IPv6Enabled,
191210
}, nil
192211
}
193212

194213
locs, matchPairs, grpc := createLocations(&virtualServer, serverID)
195214

196215
return http.Server{
197-
ServerName: virtualServer.Hostname,
198-
Locations: locs,
199-
Port: virtualServer.Port,
200-
GRPC: grpc,
201-
Includes: createIncludes(virtualServer.Additions),
216+
ServerName: virtualServer.Hostname,
217+
Locations: locs,
218+
Port: virtualServer.Port,
219+
GRPC: grpc,
220+
Includes: createIncludes(virtualServer.Additions),
221+
IPv6Enabled: virtualServer.IPv6Enabled,
202222
}, matchPairs
203223
}
204224

internal/mode/static/nginx/config/servers_template.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ js_preload_object matches from /etc/nginx/conf.d/matches.json;
66
{{ if $s.IsDefaultSSL -}}
77
server {
88
listen {{ $s.Port }} ssl default_server;
9+
{{- if $s.IPv6Enabled }}
10+
listen [::]:{{ $s.Port }} ssl default_server;
11+
{{- end }}
912
1013
ssl_reject_handshake on;
1114
}
1215
{{- else if $s.IsDefaultHTTP }}
1316
server {
1417
listen {{ $s.Port }} default_server;
18+
{{- if $s.IPv6Enabled }}
19+
listen [::]:{{ $s.Port }} default_server;
20+
{{- end }}
1521
1622
default_type text/html;
1723
return 404;
@@ -20,6 +26,9 @@ server {
2026
server {
2127
{{- if $s.SSL }}
2228
listen {{ $s.Port }} ssl;
29+
{{- if $s.IPv6Enabled }}
30+
listen [::]:{{ $s.Port }} ssl;
31+
{{- end }}
2332
ssl_certificate {{ $s.SSL.Certificate }};
2433
ssl_certificate_key {{ $s.SSL.CertificateKey }};
2534
@@ -28,6 +37,9 @@ server {
2837
}
2938
{{- else }}
3039
listen {{ $s.Port }};
40+
{{- if $s.IPv6Enabled }}
41+
listen [::]:{{ $s.Port }};
42+
{{- end }}
3143
{{- end }}
3244
3345
server_name {{ $s.ServerName }};
@@ -94,14 +106,14 @@ server {
94106
{{- end }}
95107
{{ end }}
96108
server {
97-
listen unix:/var/run/nginx/nginx-502-server.sock;
109+
listen unix:/var/lib/nginx/nginx-502-server.sock;
98110
access_log off;
99111
100112
return 502;
101113
}
102114
103115
server {
104-
listen unix:/var/run/nginx/nginx-500-server.sock;
116+
listen unix:/var/lib/nginx/nginx-500-server.sock;
105117
access_log off;
106118
107119
return 500;

internal/mode/static/nginx/config/servers_test.go

+34-14
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
. "github.com./onsi/gomega"
1010
"k8s.io/apimachinery/pkg/types"
1111

12+
ngfAPI "github.com./nginxinc/nginx-gateway-fabric/apis/v1alpha1"
1213
"github.com./nginxinc/nginx-gateway-fabric/internal/framework/helpers"
1314
"github.com./nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/http"
1415
"github.com./nginxinc/nginx-gateway-fabric/internal/mode/static/state/dataplane"
@@ -92,13 +93,20 @@ func TestExecuteServers(t *testing.T) {
9293
},
9394
},
9495
},
96+
BaseHTTPConfig: dataplane.BaseHTTPConfig{
97+
IPFamily: ngfAPI.Dual,
98+
},
9599
}
96100

97101
expSubStrings := map[string]int{
98102
"listen 8080 default_server;": 1,
103+
"listen [::]:8080 default_server;": 1,
99104
"listen 8080;": 2,
105+
"listen [::]:8080;": 2,
100106
"listen 8443 ssl;": 2,
107+
"listen [::]:8443 ssl;": 2,
101108
"listen 8443 ssl default_server;": 1,
109+
"listen [::]:8443 ssl default_server;": 1,
102110
"server_name example.com;": 2,
103111
"server_name cafe.example.com;": 2,
104112
"ssl_certificate /etc/nginx/secrets/test-keypair.pem;": 2,
@@ -621,8 +629,9 @@ func TestCreateServers(t *testing.T) {
621629

622630
httpServers := []dataplane.VirtualServer{
623631
{
624-
IsDefault: true,
625-
Port: 8080,
632+
IsDefault: true,
633+
Port: 8080,
634+
IPv6Enabled: true,
626635
},
627636
{
628637
Hostname: "cafe.example.com",
@@ -638,13 +647,15 @@ func TestCreateServers(t *testing.T) {
638647
Identifier: "server-addition-2",
639648
},
640649
},
650+
IPv6Enabled: true,
641651
},
642652
}
643653

644654
sslServers := []dataplane.VirtualServer{
645655
{
646-
IsDefault: true,
647-
Port: 8443,
656+
IsDefault: true,
657+
Port: 8443,
658+
IPv6Enabled: true,
648659
},
649660
{
650661
Hostname: "cafe.example.com",
@@ -661,6 +672,7 @@ func TestCreateServers(t *testing.T) {
661672
Identifier: "server-addition-3",
662673
},
663674
},
675+
IPv6Enabled: true,
664676
},
665677
}
666678

@@ -1025,6 +1037,7 @@ func TestCreateServers(t *testing.T) {
10251037
{
10261038
IsDefaultHTTP: true,
10271039
Port: 8080,
1040+
IPv6Enabled: true,
10281041
},
10291042
{
10301043
ServerName: "cafe.example.com",
@@ -1035,10 +1048,12 @@ func TestCreateServers(t *testing.T) {
10351048
includesFolder + "/server-addition-1.conf",
10361049
includesFolder + "/server-addition-2.conf",
10371050
},
1051+
IPv6Enabled: true,
10381052
},
10391053
{
10401054
IsDefaultSSL: true,
10411055
Port: 8443,
1056+
IPv6Enabled: true,
10421057
},
10431058
{
10441059
ServerName: "cafe.example.com",
@@ -1053,12 +1068,13 @@ func TestCreateServers(t *testing.T) {
10531068
includesFolder + "/server-addition-1.conf",
10541069
includesFolder + "/server-addition-3.conf",
10551070
},
1071+
IPv6Enabled: true,
10561072
},
10571073
}
10581074

10591075
g := NewWithT(t)
10601076

1061-
result, httpMatchPair := createServers(httpServers, sslServers)
1077+
result, httpMatchPair := createServers(httpServers, sslServers, true)
10621078

10631079
g.Expect(httpMatchPair).To(Equal(allExpMatchPair))
10641080
g.Expect(helpers.Diff(expectedServers, result)).To(BeEmpty())
@@ -1244,30 +1260,34 @@ func TestCreateServersConflicts(t *testing.T) {
12441260
t.Run(test.name, func(t *testing.T) {
12451261
httpServers := []dataplane.VirtualServer{
12461262
{
1247-
IsDefault: true,
1248-
Port: 8080,
1263+
IsDefault: true,
1264+
Port: 8080,
1265+
IPv6Enabled: true,
12491266
},
12501267
{
1251-
Hostname: "cafe.example.com",
1252-
PathRules: test.rules,
1253-
Port: 8080,
1268+
Hostname: "cafe.example.com",
1269+
PathRules: test.rules,
1270+
Port: 8080,
1271+
IPv6Enabled: true,
12541272
},
12551273
}
12561274
expectedServers := []http.Server{
12571275
{
12581276
IsDefaultHTTP: true,
12591277
Port: 8080,
1278+
IPv6Enabled: true,
12601279
},
12611280
{
1262-
ServerName: "cafe.example.com",
1263-
Locations: test.expLocs,
1264-
Port: 8080,
1281+
ServerName: "cafe.example.com",
1282+
Locations: test.expLocs,
1283+
Port: 8080,
1284+
IPv6Enabled: true,
12651285
},
12661286
}
12671287

12681288
g := NewWithT(t)
12691289

1270-
result, _ := createServers(httpServers, []dataplane.VirtualServer{})
1290+
result, _ := createServers(httpServers, []dataplane.VirtualServer{}, true)
12711291
g.Expect(helpers.Diff(expectedServers, result)).To(BeEmpty())
12721292
})
12731293
}

0 commit comments

Comments
 (0)