Skip to content

Instantly share code, notes, and snippets.

@marcinwyszynski
Created September 5, 2016 21:16
Show Gist options
  • Save marcinwyszynski/9df73af0ca52d999b9139fe272e2e0cf to your computer and use it in GitHub Desktop.
Save marcinwyszynski/9df73af0ca52d999b9139fe272e2e0cf to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"net"
"net/http"
"strconv"
"strings"
"time"
"github.com/miekg/dns"
)
type dnsDialer struct {
resolver net.Addr
client *dns.Client
}
func newDNSDialer(resolver net.Addr) *dnsDialer {
return &dnsDialer{resolver, new(dns.Client)}
}
func (dd *dnsDialer) Dial(network, address string) (net.Conn, error) {
tokens := strings.Split(address, ":")
hostname, portStr := tokens[0], tokens[1]
port, err := strconv.Atoi(portStr)
if err != nil {
return nil, err
}
answer, err := dd.getAnswer(hostname)
if len(answer) == 0 {
return nil, fmt.Errorf("DNS lookup failed for %s", hostname)
}
var conn net.Conn
for _, ans := range answer {
tcpAddr := &net.TCPAddr{IP: ans.(*dns.A).A, Port: port}
conn, err = net.Dial(network, tcpAddr.String())
if err == nil {
return conn, nil
}
}
return nil, err
}
func (dd *dnsDialer) getAnswer(hostname string) ([]dns.RR, error) {
query := new(dns.Msg).SetQuestion(hostname+".", dns.TypeA)
resp, _, err := dd.client.Exchange(query, dd.resolver.String())
if err != nil {
return nil, err
}
return resp.Answer, nil
}
func main() {
dDial := newDNSDialer(
&net.UDPAddr{
IP: net.ParseIP("8.8.8.8"),
Port: 53,
},
)
client := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: dDial.Dial,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
resp, err := client.Get("http://google.com/")
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", resp)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment