Skip to content

Commit

Permalink
fix: multi-resolver querying and http client calls
Browse files Browse the repository at this point in the history
This change resolves two key bugs:

1. All HTTP requests to detect a lancache heartbeat were incorrectly utilising the system resolver, we now utilise an HTTP transport with the appropriate resolver.
2. Works around a current Go limitation with Windows where all requests would utilise the system resolver even if attempting to manually override, we now use a Pure Go dns client library to make and parse said requests.
  • Loading branch information
nightah committed Jul 28, 2022
1 parent 522b04d commit 344a34b
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 17 deletions.
3 changes: 3 additions & 0 deletions const.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const (

testPrefix = "lancachetest."
wildcardPrefix = "*."

portHTTP = ":80"
portDNS = ":53"
)

var (
Expand Down
4 changes: 1 addition & 3 deletions types.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package main

import "net"

type CDN struct {
Name string
File string
Expand All @@ -10,7 +8,7 @@ type CDN struct {
type Lookup struct {
Resolver string
Hostname string
Address []net.IP
Address []string
ContainerID string
Time string
}
92 changes: 78 additions & 14 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"reflect"
"strings"
"time"

"github.com/miekg/dns"
)

func getInterfaceAddresses(logger io.Writer) {
Expand Down Expand Up @@ -132,38 +134,57 @@ func lookupHostnames(host string, hostnames []string, iterations int, servers []

func processHostnames(hostname, resolver string, logger io.Writer) (success, failed []Lookup) {
var (
ips []net.IP
err error
dialer net.Dialer
transport http.Transport
ips []string
err error
)

if resolver != "system" {
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: 1 * time.Second,
}
return d.DialContext(ctx, network, resolver)
},
// Fixed in Go 1.19: https://github.com/golang/go/issues/33097
//r := &net.Resolver{
// PreferGo: true,
// Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
// dialer = net.Dialer{
// Timeout: 1 * time.Second,
// }
// return dialer.DialContext(ctx, network, resolver+portDNS)
// },
//}
//
//ips, err = r.LookupHost(context.Background(), hostname)

ips, err = resolveIP(hostname, resolver+portDNS)
if len(ips) == 0 {
failed = append(failed, Lookup{
Resolver: resolver,
Hostname: hostname,
Time: time.Now().Format(time.RFC822),
})
return success, failed
}

ips, err = r.LookupIP(context.Background(), "ip", hostname)
transport = http.Transport{DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
addr = ips[0] + portHTTP
return dialer.DialContext(ctx, network, addr)
}}
} else {
ips, err = net.LookupIP(hostname)
ips, err = net.LookupHost(hostname)
}

if err != nil {
_, _ = fmt.Fprintf(logger, "Could not get IPs: %v\n", err)
failed = append(failed, Lookup{
Resolver: resolver,
Hostname: hostname,
Time: time.Now().String(),
Time: time.Now().Format(time.RFC822),
})
return success, failed
}

client := &http.Client{
Timeout: 1 * time.Second,
Timeout: 1 * time.Second,
Transport: &transport,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
Expand Down Expand Up @@ -223,6 +244,49 @@ func parseCDN(name, file string, logger io.Writer) (hostnames []string) {
return hostnames
}

func resolveIP(name, resolver string) ([]string, error) {
var addresses []string
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

client := new(dns.Client)
parsed := net.ParseIP(name)
if parsed != nil {
addresses = append(addresses, name)
return addresses, nil
}

messageAAAA := new(dns.Msg)
messageAAAA.SetQuestion(dns.Fqdn(name), dns.TypeAAAA)
inAAAA, _, err := client.ExchangeContext(ctx, messageAAAA, resolver)

if err != nil {
return nil, err
}

for _, record := range inAAAA.Answer {
if t, ok := record.(*dns.AAAA); ok {
addresses = append(addresses, t.AAAA.String())
}
}

messageA := new(dns.Msg)
messageA.SetQuestion(dns.Fqdn(name), dns.TypeA)
inA, _, err := client.ExchangeContext(ctx, messageA, resolver)

if err != nil {
return nil, err
}

for _, record := range inA.Answer {
if t, ok := record.(*dns.A); ok {
addresses = append(addresses, t.A.String())
}
}

return addresses, nil
}

func isLookupInSliceEqual(a []Lookup) []Lookup {
var l []Lookup

Expand Down

0 comments on commit 344a34b

Please sign in to comment.