Skip to content

Commit

Permalink
add support for ipv6
Browse files Browse the repository at this point in the history
  • Loading branch information
salonichf5 committed Jul 8, 2024
1 parent 7bc0b6e commit 0d2462a
Show file tree
Hide file tree
Showing 18 changed files with 574 additions and 133 deletions.
21 changes: 20 additions & 1 deletion apis/v1alpha1/nginxproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

// NginxProxy is a configuration object that is attached to a GatewayClass parametersRef. It provides a way
// to configure global settings for all Gateways defined from the GatewayClass.
type NginxProxy struct { //nolint:govet // standard field alignment, don't change it
type NginxProxy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Expand All @@ -27,12 +27,31 @@ type NginxProxyList struct {
Items []NginxProxy `json:"items"`
}

// IPFamilyType specifies the IP family to be used by the server.
//
// +kubebuilder:validation:Enum=dual;ipv4;ipv6
type IPFamilyType string

const (
// Dual specifies that the server will use both IPv4 and IPv6.
Dual IPFamilyType = "dual"
// IPv4 specifies that the server will use only IPv4.
IPv4 IPFamilyType = "ipv4"
// IPv6 specifies that the server will use only IPv6.
IPv6 IPFamilyType = "ipv6"
)

// NginxProxySpec defines the desired state of the NginxProxy.
type NginxProxySpec struct {
// Telemetry specifies the OpenTelemetry configuration.
//
// +optional
Telemetry *Telemetry `json:"telemetry,omitempty"`
// IPFamily specifies the IP family to be used by the server.
// Default is "dual", meaning the server will use both IPv4 and IPv6.
//
// +optional
IPFamily IPFamilyType `json:"ipFamily,omitempty"`
// DisableHTTP2 defines if http2 should be disabled for all servers.
// Default is false, meaning http2 will be enabled for all servers.
//
Expand Down
1 change: 1 addition & 0 deletions charts/nginx-gateway-fabric/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ nginx:
config:
{}
# disableHTTP2: false
# ipFamily: dual
# telemetry:
# exporter:
# endpoint: otel-collector.default.svc:4317
Expand Down
9 changes: 9 additions & 0 deletions config/crd/bases/gateway.nginx.org_nginxproxies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ spec:
DisableHTTP2 defines if http2 should be disabled for all servers.
Default is false, meaning http2 will be enabled for all servers.
type: boolean
ipFamily:
description: |-
IPFamily specifies the IP family to be used by the server.
Default is "dual", meaning the server will use both IPv4 and IPv6.
enum:
- dual
- ipv4
- ipv6
type: string
telemetry:
description: Telemetry specifies the OpenTelemetry configuration.
properties:
Expand Down
9 changes: 9 additions & 0 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,15 @@ spec:
DisableHTTP2 defines if http2 should be disabled for all servers.
Default is false, meaning http2 will be enabled for all servers.
type: boolean
ipFamily:
description: |-
IPFamily specifies the IP family to be used by the server.
Default is "dual", meaning the server will use both IPv4 and IPv6.
enum:
- dual
- ipv4
- ipv6
type: string
telemetry:
description: Telemetry specifies the OpenTelemetry configuration.
properties:
Expand Down
19 changes: 19 additions & 0 deletions docs/developer/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,29 @@ This will build the docker images `nginx-gateway-fabric:<your-user>` and `nginx-
1. Create a `kind` cluster:
To create a `kind` cluster with IPv4 enabled:
```makefile
make create-kind-cluster
```
To create a `kind` cluster with IPv6 or Dual IPFamily enabled, use this `config.yaml`:
```yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
networking:
ipFamily: dual
# ipFamily: ipv6
apiServerAddress: 127.0.0.1
```
```shell
kind create cluster --config ~/cluster.yaml
```
2. Load the previously built images onto your `kind` cluster:
```shell
Expand Down
7 changes: 7 additions & 0 deletions internal/mode/static/nginx/config/http/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ type Server struct {
IsDefaultHTTP bool
IsDefaultSSL bool
GRPC bool
IPFamily IPFamily
}

// IPFamily holds the IP family configuration for all servers.
type IPFamily struct {
IPv4 bool
IPv6 bool
}

// Location holds all configuration for an HTTP location.
Expand Down
42 changes: 36 additions & 6 deletions internal/mode/static/nginx/config/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
gotemplate "text/template"

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

func executeServers(conf dataplane.Configuration) []executeResult {
servers, httpMatchPairs := createServers(conf.HTTPServers, conf.SSLServers)
ipFamily := getIPFamily(conf.BaseHTTPConfig)
servers, httpMatchPairs := createServers(conf.HTTPServers, conf.SSLServers, ipFamily)

serverResult := executeResult{
dest: httpConfigFile,
Expand Down Expand Up @@ -86,6 +88,18 @@ func executeServers(conf dataplane.Configuration) []executeResult {
return allResults
}

// getIPFamily returns whether the server should be configured for IPv4, IPv6, or both.
func getIPFamily(baseHTTPConfig dataplane.BaseHTTPConfig) http.IPFamily {
switch ip := baseHTTPConfig.IPFamily; ip {
case ngfAPI.IPv4:
return http.IPFamily{IPv4: true}
case ngfAPI.IPv6:
return http.IPFamily{IPv6: true}

Check warning on line 97 in internal/mode/static/nginx/config/servers.go

View check run for this annotation

Codecov / codecov/patch

internal/mode/static/nginx/config/servers.go#L96-L97

Added lines #L96 - L97 were not covered by tests
}

return http.IPFamily{IPv4: true, IPv6: true}
}

func createAdditionFileResults(conf dataplane.Configuration) []executeResult {
uniqueAdditions := make(map[string][]byte)

Expand Down Expand Up @@ -141,30 +155,39 @@ func createIncludes(additions []dataplane.Addition) []string {
return includes
}

func createServers(httpServers, sslServers []dataplane.VirtualServer) ([]http.Server, httpMatchPairs) {
func createServers(
httpServers,
sslServers []dataplane.VirtualServer,
ipFamily http.IPFamily,
) ([]http.Server, httpMatchPairs) {
servers := make([]http.Server, 0, len(httpServers)+len(sslServers))
finalMatchPairs := make(httpMatchPairs)

for serverID, s := range httpServers {
httpServer, matchPairs := createServer(s, serverID)
httpServer, matchPairs := createServer(s, serverID, ipFamily)
servers = append(servers, httpServer)
maps.Copy(finalMatchPairs, matchPairs)
}

for serverID, s := range sslServers {
sslServer, matchPair := createSSLServer(s, serverID)
sslServer, matchPair := createSSLServer(s, serverID, ipFamily)
servers = append(servers, sslServer)
maps.Copy(finalMatchPairs, matchPair)
}

return servers, finalMatchPairs
}

func createSSLServer(virtualServer dataplane.VirtualServer, serverID int) (http.Server, httpMatchPairs) {
func createSSLServer(
virtualServer dataplane.VirtualServer,
serverID int,
ipFamily http.IPFamily,
) (http.Server, httpMatchPairs) {
if virtualServer.IsDefault {
return http.Server{
IsDefaultSSL: true,
Port: virtualServer.Port,
IPFamily: ipFamily,
}, nil
}

Expand All @@ -180,14 +203,20 @@ func createSSLServer(virtualServer dataplane.VirtualServer, serverID int) (http.
Port: virtualServer.Port,
GRPC: grpc,
Includes: createIncludes(virtualServer.Additions),
IPFamily: ipFamily,
}, matchPairs
}

func createServer(virtualServer dataplane.VirtualServer, serverID int) (http.Server, httpMatchPairs) {
func createServer(
virtualServer dataplane.VirtualServer,
serverID int,
ipFamily http.IPFamily,
) (http.Server, httpMatchPairs) {
if virtualServer.IsDefault {
return http.Server{
IsDefaultHTTP: true,
Port: virtualServer.Port,
IPFamily: ipFamily,
}, nil
}

Expand All @@ -199,6 +228,7 @@ func createServer(virtualServer dataplane.VirtualServer, serverID int) (http.Ser
Port: virtualServer.Port,
GRPC: grpc,
Includes: createIncludes(virtualServer.Additions),
IPFamily: ipFamily,
}, matchPairs
}

Expand Down
20 changes: 20 additions & 0 deletions internal/mode/static/nginx/config/servers_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,50 @@ js_preload_object matches from /etc/nginx/conf.d/matches.json;
{{- range $s := . -}}
{{ if $s.IsDefaultSSL -}}
server {
{{- if $s.IPFamily.IPv4 }}
listen {{ $s.Port }} ssl default_server;
{{- end }}
{{- if $s.IPFamily.IPv6 }}
listen [::]:{{ $s.Port }} ssl default_server;
{{- end }}
ssl_reject_handshake on;
}
{{- else if $s.IsDefaultHTTP }}
server {
{{- if $s.IPFamily.IPv4 }}
listen {{ $s.Port }} default_server;
{{- end }}
{{- if $s.IPFamily.IPv6 }}
listen [::]:{{ $s.Port }} default_server;
{{- end }}
default_type text/html;
return 404;
}
{{- else }}
server {
{{- if $s.SSL }}
{{- if $s.IPFamily.IPv4 }}
listen {{ $s.Port }} ssl;
{{- end }}
{{- if $s.IPFamily.IPv6 }}
listen [::]:{{ $s.Port }} ssl;
{{- end }}
ssl_certificate {{ $s.SSL.Certificate }};
ssl_certificate_key {{ $s.SSL.CertificateKey }};
if ($ssl_server_name != $host) {
return 421;
}
{{- else }}
{{- if $s.IPFamily.IPv4 }}
listen {{ $s.Port }};
{{- end }}
{{- if $s.IPFamily.IPv6 }}
listen [::]:{{ $s.Port }};
{{- end }}
{{- end }}
server_name {{ $s.ServerName }};
Expand Down
Loading

0 comments on commit 0d2462a

Please sign in to comment.