diff --git a/attacker/resolver_test.go b/attacker/resolver_test.go new file mode 100644 index 0000000..34a1099 --- /dev/null +++ b/attacker/resolver_test.go @@ -0,0 +1,92 @@ +package attacker + +import ( + "fmt" + "io/ioutil" + "net" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + "time" + + "github.com/miekg/dns" +) + +const ( + testDomain = "test.notadomain" + DNSServerAddress = "127.0.0.1" + message = "Test Server" +) + +func TestNewResolver(t *testing.T) { + done := make(chan struct{}) // for ensuring ds.PacketConn is not nil + + // prepare custom DNS server + dns.HandleFunc(".", handleRequest) + ds := dns.Server{ + Addr: DNSServerAddress + ":0", + Net: "udp", + ReadTimeout: time.Millisecond * time.Duration(2000), + WriteTimeout: time.Millisecond * time.Duration(2000), + NotifyStartedFunc: func() { close(done) }, + } + + go func() { + if err := ds.ListenAndServe(); err != nil { + t.Logf("got error during dns ListenAndServe: %s", err) + } + }() + defer func() { + _ = ds.Shutdown() + }() + + <-done + + net.DefaultResolver = NewResolver([]string{ds.PacketConn.LocalAddr().String()}) + + // test server for name resolution + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, message) + })) + defer ts.Close() + + tsURL, _ := url.Parse(ts.URL) + _, port, _ := net.SplitHostPort(tsURL.Host) + tsURL.Host = net.JoinHostPort(testDomain, port) + + resp, err := http.Get(tsURL.String()) + if err != nil { + t.Fatalf("failed resolver round trip: %v", err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf("failed to read respose body: %v", err) + } + + if strings.TrimSpace(string(body)) != message { + t.Errorf("reponse body mismatch, expected: '%s', but got '%s'", message, body) + } +} + +func handleRequest(w dns.ResponseWriter, r *dns.Msg) { + m := new(dns.Msg) + m.SetReply(r) + + m.Answer = []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{ + Name: r.Question[0].Name, + Rrtype: dns.TypeA, + Class: dns.ClassINET, + Ttl: 1, + }, + A: net.ParseIP(DNSServerAddress), + }, + } + + w.WriteMsg(m) +} diff --git a/go.mod b/go.mod index df55a86..68c68bc 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect github.com/k0kubun/pp v3.0.1+incompatible github.com/mattn/go-colorable v0.1.7 // indirect + github.com/miekg/dns v1.1.17 github.com/mum4k/termdash v0.12.2 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.6.1 diff --git a/go.sum b/go.sum index 069f46c..d7e8e57 100644 --- a/go.sum +++ b/go.sum @@ -60,6 +60,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/miekg/dns v1.1.17 h1:BhJxdA7bH51vKFZSY8Sn9pR7++LREvg0eYFzHA452ew= github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= github.com/mum4k/termdash v0.12.2 h1:S2frz71OrXUKIVVZ3snYBEzyYlUNRTu0ElV6d5Pf6gI= github.com/mum4k/termdash v0.12.2/go.mod h1:haerPCSO0U8pehROAecmuOHDF+2UXw2KaCTxdWooDFE= @@ -84,6 +85,7 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=