diff --git a/controllers/nginx/pkg/cmd/controller/nginx.go b/controllers/nginx/pkg/cmd/controller/nginx.go index 389c90cbff..8dcefd872e 100644 --- a/controllers/nginx/pkg/cmd/controller/nginx.go +++ b/controllers/nginx/pkg/cmd/controller/nginx.go @@ -70,8 +70,9 @@ func newNGINXController() ingress.Controller { ngx = binary } n := &NGINXController{ - binary: ngx, - configmap: &api_v1.ConfigMap{}, + binary: ngx, + configmap: &api_v1.ConfigMap{}, + isIPV6Enabled: isIPv6Enabled(), } var onChange func() @@ -121,6 +122,9 @@ type NGINXController struct { stats *statsCollector statusModule statusModule + + // returns true if IPV6 is enabled in the pod + isIPV6Enabled bool } // Start start a new NGINX master process running in foreground. @@ -425,6 +429,7 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) ([]byte, er HealthzURI: ngxHealthPath, CustomErrors: len(cfg.CustomHTTPErrors) > 0, Cfg: cfg, + IsIPV6Enabled: n.isIPV6Enabled && !cfg.DisableIpv6, }) if err != nil { return nil, err @@ -468,3 +473,8 @@ func nextPowerOf2(v int) int { return v } + +func isIPv6Enabled() bool { + cmd := exec.Command("test", "-f", "/proc/net/if_inet6") + return cmd.Run() == nil +} diff --git a/controllers/nginx/pkg/config/config.go b/controllers/nginx/pkg/config/config.go index 3127294da8..41605caa9c 100644 --- a/controllers/nginx/pkg/config/config.go +++ b/controllers/nginx/pkg/config/config.go @@ -347,4 +347,5 @@ type TemplateConfig struct { HealthzURI string CustomErrors bool Cfg Configuration + IsIPV6Enabled bool } diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index b8098880a5..4b43abe127 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -1,4 +1,5 @@ -{{ $cfg := .Cfg }} +{{ $cfg := .Cfg }} +{{ $IsIPV6Enabled := .IsIPV6Enabled }} {{ $healthzURI := .HealthzURI }} {{ $backends := .Backends }} {{ $proxyHeaders := .ProxySetHeaders }} @@ -218,10 +219,13 @@ http { {{ range $index, $server := .Servers }} server { server_name {{ $server.Hostname }}; - listen {{ if not $cfg.DisableIpv6 }}[::]:{{ end }}80{{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if not $cfg.DisableIpv6 }}ipv6only=off{{end}} reuseport backlog={{ $backlogSize }}{{end}}; + listen 80{{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{end}}; + {{ if $IsIPV6Enabled }}listen [::]:80{{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{ end }};{{ end }} + {{/* Listen on 442 because port 443 is used in the stream section */}} {{/* This listen on port 442 cannot contains proxy_protocol directive because port 443 is in charge of decoding the protocol */}} - {{ if not (empty $server.SSLCertificate) }}listen {{ if gt (len $passthroughBackends) 0 }}442{{ else }}{{ if not $cfg.DisableIpv6 }}[::]:{{ end }}443 {{ if $cfg.UseProxyProtocol }} proxy_protocol {{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server {{ if not $cfg.DisableIpv6 }}ipv6only=off{{end}} reuseport backlog={{ $backlogSize }}{{end}} ssl {{ if $cfg.UseHTTP2 }}http2{{ end }}; + {{ if not (empty $server.SSLCertificate) }}listen {{ if gt (len $passthroughBackends) 0 }}442{{ else }}443 {{ if $cfg.UseProxyProtocol }} proxy_protocol {{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{end}} ssl {{ if $cfg.UseHTTP2 }}http2{{ end }}; + {{ if $IsIPV6Enabled }}{{ if not (empty $server.SSLCertificate) }}listen {{ if gt (len $passthroughBackends) 0 }}[::]:442{{ else }}[::]:443 {{ end }}{{ if $cfg.UseProxyProtocol }} proxy_protocol {{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $backlogSize }}{{end}} ssl {{ if $cfg.UseHTTP2 }}http2{{ end }};{{ end }} {{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}} # PEM sha: {{ $server.SSLPemChecksum }} ssl_certificate {{ $server.SSLCertificate }}; @@ -396,7 +400,7 @@ http { # with an external software (like sysdig) location /nginx_status { allow 127.0.0.1; - {{ if not $cfg.DisableIpv6 }}allow ::1;{{ end }} + {{ if $IsIPV6Enabled }}allow ::1;{{ end }} deny all; access_log off; @@ -414,7 +418,8 @@ http { # Use the port 18080 (random value just to avoid known ports) as default port for nginx. # Changing this value requires a change in: # https://github.com/kubernetes/contrib/blob/master/ingress/controllers/nginx/nginx/command.go#L104 - listen {{ if not $cfg.DisableIpv6 }}[::]:{{ end }}18080 {{ if not $cfg.DisableIpv6 }}ipv6only=off{{end}} default_server reuseport backlog={{ .BacklogSize }}; + listen 18080 default_server reuseport backlog={{ .BacklogSize }}; + {{ if $IsIPV6Enabled }}listen [::]:18080 default_server reuseport backlog={{ .BacklogSize }};{{ end }} location {{ $healthzURI }} { access_log off; @@ -500,7 +505,8 @@ stream { {{ buildSSLPassthroughUpstreams $backends .PassthroughBackends }} server { - listen {{ if not $cfg.DisableIpv6 }}[::]:{{ end }}443 {{ if not $cfg.DisableIpv6 }}ipv6only=off{{ end }}{{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }}; + listen 443 {{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }}; + {{ if $IsIPV6Enabled }}listen [::]:443 {{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }};{{ end }} proxy_pass $stream_upstream; ssl_preread on; }