diff --git a/internal/controller/nginx/config/base_http_config.go b/internal/controller/nginx/config/base_http_config.go index fcceaed0f2..7af0712bde 100644 --- a/internal/controller/nginx/config/base_http_config.go +++ b/internal/controller/nginx/config/base_http_config.go @@ -1,6 +1,8 @@ package config import ( + "fmt" + "net" gotemplate "text/template" "github.com/nginx/nginx-gateway-fabric/v2/internal/controller/nginx/config/shared" @@ -34,7 +36,7 @@ func executeBaseHTTPConfig(conf dataplane.Configuration) []executeResult { Includes: includes, NginxReadinessProbePort: conf.BaseHTTPConfig.NginxReadinessProbePort, IPFamily: getIPFamily(conf.BaseHTTPConfig), - DNSResolver: conf.BaseHTTPConfig.DNSResolver, + DNSResolver: buildDNSResolver(conf.BaseHTTPConfig.DNSResolver), AccessLog: buildAccessLog(conf.Logging.AccessLog), GatewaySecretID: conf.BaseHTTPConfig.GatewaySecretID, } @@ -49,6 +51,34 @@ func executeBaseHTTPConfig(conf dataplane.Configuration) []executeResult { return results } +func buildDNSResolver(dnsResolver *dataplane.DNSResolverConfig) *dataplane.DNSResolverConfig { + if dnsResolver == nil { + return nil + } + + fixed := &dataplane.DNSResolverConfig{ + Timeout: dnsResolver.Timeout, + Valid: dnsResolver.Valid, + DisableIPv6: dnsResolver.DisableIPv6, + } + + for _, address := range dnsResolver.Addresses { + ip := net.ParseIP(address) + if ip == nil { + continue + } + + if ip.To4() == nil { + // nginx expects IPv6 DNS resolvers to be passed with brackets + fixed.Addresses = append(fixed.Addresses, fmt.Sprintf("[%s]", address)) + } else { + fixed.Addresses = append(fixed.Addresses, address) + } + } + + return fixed +} + func buildAccessLog(accessLogConfig *dataplane.AccessLog) *AccessLog { if accessLogConfig != nil { accessLog := &AccessLog{ diff --git a/internal/controller/nginx/config/base_http_config_test.go b/internal/controller/nginx/config/base_http_config_test.go index 50ac43232f..b91b2c8909 100644 --- a/internal/controller/nginx/config/base_http_config_test.go +++ b/internal/controller/nginx/config/base_http_config_test.go @@ -317,6 +317,28 @@ func TestExecuteBaseHttp_DNSResolver(t *testing.T) { }, expectedConfig: "resolver 8.8.8.8;", }, + { + name: "DNS resolver with single IPv6 address", + conf: dataplane.Configuration{ + BaseHTTPConfig: dataplane.BaseHTTPConfig{ + DNSResolver: &dataplane.DNSResolverConfig{ + Addresses: []string{"2606:4700:4700::64"}, + }, + }, + }, + expectedConfig: "resolver [2606:4700:4700::64];", + }, + { + name: "DNS resolver with one IPv6 address and one IPv4 address", + conf: dataplane.Configuration{ + BaseHTTPConfig: dataplane.BaseHTTPConfig{ + DNSResolver: &dataplane.DNSResolverConfig{ + Addresses: []string{"2606:4700:4700::64", "8.8.8.8"}, + }, + }, + }, + expectedConfig: "resolver [2606:4700:4700::64] 8.8.8.8;", + }, { name: "no DNS resolver", conf: dataplane.Configuration{ diff --git a/internal/controller/nginx/config/stream_servers.go b/internal/controller/nginx/config/stream_servers.go index cbac92cc7a..7c4e1b3436 100644 --- a/internal/controller/nginx/config/stream_servers.go +++ b/internal/controller/nginx/config/stream_servers.go @@ -19,7 +19,7 @@ func (g GeneratorImpl) executeStreamServers(conf dataplane.Configuration) []exec Servers: streamServers, IPFamily: getIPFamily(conf.BaseHTTPConfig), Plus: g.plus, - DNSResolver: conf.BaseStreamConfig.DNSResolver, + DNSResolver: buildDNSResolver(conf.BaseStreamConfig.DNSResolver), } streamServerResult := executeResult{ diff --git a/internal/controller/nginx/config/stream_servers_test.go b/internal/controller/nginx/config/stream_servers_test.go index e603fe1fed..ba2bfeee86 100644 --- a/internal/controller/nginx/config/stream_servers_test.go +++ b/internal/controller/nginx/config/stream_servers_test.go @@ -471,7 +471,7 @@ server { }, expectedConfig: ` # DNS resolver configuration for ExternalName services -resolver 2001:4860:4860::8888 valid=30s; +resolver [2001:4860:4860::8888] valid=30s; resolver_timeout 5s; server {