|
package main |
|
|
|
import ( |
|
"context" |
|
"crypto/tls" |
|
"fmt" |
|
"io" |
|
"log" |
|
"net" |
|
"net/http" |
|
"strings" |
|
"time" |
|
|
|
"github.com/miekg/dns" |
|
) |
|
|
|
func main() { |
|
client := &http.Client{ |
|
Timeout: time.Second * 5, |
|
Transport: &http.Transport{ |
|
// Avoid: "x509: certificate signed by unknown authority" |
|
TLSClientConfig: &tls.Config{ |
|
InsecureSkipVerify: true, |
|
}, |
|
DialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) { |
|
ipv4, err := resolveIPv4(addr) |
|
if err != nil { |
|
return nil, err |
|
} |
|
timeout, err := time.ParseDuration("10s") |
|
if err != nil { |
|
return nil, err |
|
} |
|
return (&net.Dialer{ |
|
Timeout: timeout, |
|
}).DialContext(ctx, network, ipv4) |
|
}, |
|
}, |
|
} |
|
|
|
// Also try: https://v4.testmyipv6.com/ |
|
req, err := http.NewRequest("GET", "https://ipv4.lookup.test-ipv6.com/", nil) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
|
|
res, err := client.Do(req) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
|
|
b, err := io.ReadAll(res.Body) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
fmt.Printf("%+v\n", string(b)) |
|
} |
|
|
|
// resolveIPv4 resolves an address to IPv4 address. |
|
func resolveIPv4(addr string) (string, error) { |
|
url := strings.Split(addr, ":") |
|
|
|
m := new(dns.Msg) |
|
m.SetQuestion(dns.Fqdn(url[0]), dns.TypeA) |
|
m.RecursionDesired = true |
|
|
|
// NOTE: you shouldn't consult or rely on /etc/resolv.conf as it has proven historically to contain nameservers that don't respond. |
|
config, _ := dns.ClientConfigFromFile("/etc/resolv.conf") |
|
c := new(dns.Client) |
|
r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port)) |
|
if err != nil { |
|
return "", err |
|
} |
|
for _, ans := range r.Answer { |
|
if a, ok := ans.(*dns.A); ok { |
|
url[0] = a.A.String() |
|
} |
|
} |
|
|
|
return strings.Join(url, ":"), nil |
|
} |
Hey @Integralist, great gist! In some cases we can have more than one DNS server, I'd like to know if in that case the code below is right (multiples DNS servers forcing IPV4 resolution):