From 496cf5ae730a9939d42ffe96f64ba26e7fdd9a67 Mon Sep 17 00:00:00 2001 From: Evan Gilman Date: Tue, 22 Dec 2015 03:31:40 -0800 Subject: [PATCH] Implement `translate_wan_addrs` config option This knob tells consul whether it should prefer the WAN address (if set) when making service lookups in remote datacenters. This enables reachability for remote services which are behind a NAT. --- command/agent/config.go | 7 +++++++ command/agent/dns.go | 26 +++++++++++++++++++++----- command/agent/local.go | 4 ++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/command/agent/config.go b/command/agent/config.go index 5154439547..2b625eb1f2 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -189,6 +189,10 @@ type Config struct { // Serf WAN IP. If not specified, the general advertise address is used. AdvertiseAddrWan string `mapstructure:"advertise_addr_wan"` + // TranslateWanAddrs controls whether or not Consul should prefer + // the AdvertiseAddrWan address when doing lookups in remote datacenters. + TranslateWanAddrs bool `mapstructure:"translate_wan_addrs"` + // Port configurations Ports PortConfig @@ -968,6 +972,9 @@ func MergeConfig(a, b *Config) *Config { if b.AdvertiseAddrWan != "" { result.AdvertiseAddrWan = b.AdvertiseAddrWan } + if b.TranslateWanAddrs == true { + result.TranslateWanAddrs = true + } if b.AdvertiseAddrs.SerfLan != nil { result.AdvertiseAddrs.SerfLan = b.AdvertiseAddrs.SerfLan result.AdvertiseAddrs.SerfLanRaw = b.AdvertiseAddrs.SerfLanRaw diff --git a/command/agent/dns.go b/command/agent/dns.go index 6cbb89f590..71343afe8c 100644 --- a/command/agent/dns.go +++ b/command/agent/dns.go @@ -524,9 +524,15 @@ RPC: // Perform a random shuffle out.Nodes.Shuffle() + // Determine whether we should use the WAN address or not + var useWan bool + if d.agent.config.TranslateWanAddrs && datacenter != d.agent.config.Datacenter { + useWan = true + } + // Add various responses depending on the request qType := req.Question[0].Qtype - d.serviceNodeRecords(out.Nodes, req, resp, ttl) + d.serviceNodeRecords(out.Nodes, req, resp, ttl, useWan) if qType == dns.TypeSRV { d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl) @@ -620,9 +626,15 @@ RPC: return } + // Determine whether we should use the WAN address or not + var useWan bool + if d.agent.config.TranslateWanAddrs && datacenter != d.agent.config.Datacenter { + useWan = true + } + // Add various responses depending on the request. qType := req.Question[0].Qtype - d.serviceNodeRecords(out.Nodes, req, resp, ttl) + d.serviceNodeRecords(out.Nodes, req, resp, ttl, useWan) if qType == dns.TypeSRV { d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl) } @@ -646,18 +658,22 @@ RPC: } // serviceNodeRecords is used to add the node records for a service lookup -func (d *DNSServer) serviceNodeRecords(nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration) { +func (d *DNSServer) serviceNodeRecords(nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, useWan bool) { qName := req.Question[0].Name qType := req.Question[0].Qtype handled := make(map[string]struct{}) for _, node := range nodes { - // Avoid duplicate entries, possible if a node has - // the same service on multiple ports, etc. + // Prefer the Service Address or WAN Address over the + // Node Address when configured addr := node.Node.Address if node.Service.Address != "" { addr = node.Service.Address + } else if useWan == true && node.Node.WanAddress != "" { + addr = node.Node.WanAddress } + // Avoid duplicate entries, possible if a node has + // the same service on multiple ports, etc. if _, ok := handled[addr]; ok { continue } diff --git a/command/agent/local.go b/command/agent/local.go index cb8db27758..7320db8dc0 100644 --- a/command/agent/local.go +++ b/command/agent/local.go @@ -526,7 +526,7 @@ func (l *localState) syncService(id string) error { Datacenter: l.config.Datacenter, Node: l.config.NodeName, Address: l.config.AdvertiseAddr, - WanAddress: l.config.ConsulConfig.SerfWANConfig.MemberlistConfig.AdvertiseAddr, + WanAddress: l.config.AdvertiseAddrWan, Service: l.services[id], WriteRequest: structs.WriteRequest{Token: l.serviceToken(id)}, } @@ -584,7 +584,7 @@ func (l *localState) syncCheck(id string) error { Datacenter: l.config.Datacenter, Node: l.config.NodeName, Address: l.config.AdvertiseAddr, - WanAddress: l.config.ConsulConfig.SerfWANConfig.MemberlistConfig.AdvertiseAddr, + WanAddress: l.config.AdvertiseAddrWan, Service: service, Check: l.checks[id], WriteRequest: structs.WriteRequest{Token: l.checkToken(id)},