Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SRV backend IPv6 support #222

Merged
merged 3 commits into from
Jan 22, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 44 additions & 24 deletions src/discovery/srv.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,52 +57,50 @@ func srvFetch(cfg config.DiscoveryConfig) (*[]core.Backend, error) {
return &[]core.Backend{}, nil
}

/* ----- try to get A data from additional section ------ */
/* ----- try to get IPs from additional section ------ */

hosts := make(map[string]string) // name -> host
for _, ans := range r.Extra {
record, ok := ans.(*dns.A)
if !ok {
continue
switch record := ans.(type) {
case *dns.A:
hosts[record.Header().Name] = record.A.String()
case *dns.AAAA:
hosts[record.Header().Name] = fmt.Sprintf("[%s]", record.AAAA.String())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is slightly annoying - Gobetween uses net.Dial("tcp", addr) which requires bracketed IPv6s. If storing IPs here, it would be better to store them as net.IPs.

}

hosts[record.Header().Name] = record.A.String()
}

/* ----- create backends list looking up for A if needed ----- */
/* ----- create backend list looking up IP if needed ----- */

backends := []core.Backend{}
for _, ans := range r.Answer {

record, ok := ans.(*dns.SRV)
if !ok {
return nil, errors.New("Non-SRV record in SRV answer")
}

// If there were no A record in additional SRV response,
// Fetch it explicitelly
// If there were no A/AAAA record in additional SRV response,
// fetch it
if _, ok := hosts[record.Target]; !ok {
log.Debug("Fetching ", cfg.SrvLookupServer, " A/AAAA ", record.Target)

log.Debug("Fetching ", cfg.SrvLookupServer, " A ", record.Target)

resp, err := srvDnsLookup(cfg, record.Target, dns.TypeA)
ip, err := srvIPLookup(cfg, record.Target, dns.TypeA)
if err != nil {
log.Warn("Error fetching A record for ", record.Target, " skipping...")
continue
log.Warn("Error fetching A record for ", record.Target, ": ", err)
}

if len(resp.Answer) == 0 {
log.Warn("Empty answer for A records ", record.Target, " skipping...")
continue
if ip == "" {
ip, err = srvIPLookup(cfg, record.Target, dns.TypeAAAA)
if err != nil {
log.Warn("Error fetching AAAA record for ", record.Target, ": ", err)
}
}

a, ok := resp.Answer[0].(*dns.A)
if !ok {
log.Warn("Non-A record in A answer ", record.Target, " skipping...")
if ip != "" {
hosts[record.Target] = ip
} else {
log.Warn("No IP found for ", record.Target, ", skipping...")
continue
}

hosts[record.Target] = a.A.String()
}

// Append new backends
Expand All @@ -127,7 +125,6 @@ func srvFetch(cfg config.DiscoveryConfig) (*[]core.Backend, error) {
* Perform DNS Lookup with needed pattern and type
*/
func srvDnsLookup(cfg config.DiscoveryConfig, pattern string, typ uint16) (*dns.Msg, error) {

timeout := utils.ParseDurationOrDefault(cfg.Timeout, srvDefaultWaitTimeout)
c := dns.Client{Net: cfg.SrvDnsProtocol, Timeout: timeout}
m := dns.Msg{}
Expand All @@ -138,3 +135,26 @@ func srvDnsLookup(cfg config.DiscoveryConfig, pattern string, typ uint16) (*dns.

return r, err
}

/**
* Perform DNS lookup and extract IP address
*/
func srvIPLookup(cfg config.DiscoveryConfig, pattern string, typ uint16) (string, error) {
resp, err := srvDnsLookup(cfg, pattern, typ)
if err != nil {
return "", err
}

if len(resp.Answer) == 0 {
return "", nil
}

switch ans := resp.Answer[0].(type) {
case *dns.A:
return ans.A.String(), nil
case *dns.AAAA:
return fmt.Sprintf("[%s]", ans.AAAA.String()), nil
default:
return "", nil
}
}