Created
February 16, 2017 13:48
-
-
Save ssut/350892bc48b3ab7677b5647d27fea2a7 to your computer and use it in GitHub Desktop.
dnsoverhttps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"errors" | |
"net/url" | |
fasthttp "github.com/valyala/fasthttp" | |
) | |
const ( | |
RCODE_NOERROR = iota | |
RCODE_FORMERR | |
RCODE_SERVFAIL | |
RCODE_NXDOMAIN | |
RCODE_NOTIME | |
RCODE_REFUSED | |
RCODE_YXDOMAIN | |
RCODE_XRRSET | |
RCODE_NOTAUTH | |
RCODE_NOTZONE | |
) | |
type DNSResponseJson struct { | |
Status int32 `json:"Status,omitempty"` | |
TC bool `json:"TC,omitempty"` | |
RD bool `json:"RD,omitempty"` | |
RA bool `json:"RA,omitempty"` | |
AD bool `json:"AD,omitempty"` | |
CD bool `json:"CD,omitempty"` | |
Question []DNSQuestion `json:"Question,omitempty"` | |
Answer []DNSRR `json:"Answer,omitempty"` | |
Authority []DNSRR `json:"Authority,omitempty"` | |
Additional []DNSRR `json:"Additional,omitempty"` | |
Edns_client_subnet string `json:"edns_client_subnet,omitempty"` | |
Comment string `json:"Comment,omitempty"` | |
} | |
type DNSQuestion struct { | |
Name string `json:"name,omitempty"` | |
Type int32 `json:"type,omitempty"` | |
} | |
type DNSRR struct { | |
Name string `json:"name,omitempty"` | |
Type int32 `json:"type,omitempty"` | |
TTL int32 `json:"TTL,omitempty"` | |
Data string `json:"data,omitempty"` | |
} | |
type DNSQueryClient struct { | |
client *fasthttp.HostClient | |
url url.URL | |
} | |
func NewDNSQueryClient() *DNSQueryClient { | |
client := &fasthttp.HostClient{ | |
Addr: "dns.google.com", | |
} | |
baseURL := url.URL{ | |
Scheme: "https", | |
Host: "dns.google.com", | |
Path: "/resolve", | |
} | |
queryClient := &DNSQueryClient{ | |
client: client, | |
url: baseURL, | |
} | |
return queryClient | |
} | |
func (c *DNSQueryClient) generateQueryURL(name string, querytype string) string { | |
u := c.url | |
q := u.Query() | |
q.Set("name", name) | |
q.Set("type", querytype) | |
q.Set("edns_client_subnet", "0.0.0.0/0") | |
u.RawQuery = q.Encode() | |
return u.String() | |
} | |
func (c *DNSQueryClient) Query(name string, querytype string) (*DNSResponseJson, error) { | |
url := c.generateQueryURL(name, querytype) | |
status, resp, httperr := c.client.Get(nil, url) | |
if status != 200 || httperr != nil { | |
return nil, httperr | |
} | |
var dnsresp *DNSResponseJson | |
json.Unmarshal(resp, &dnsresp) | |
var err error | |
switch dnsresp.Status { | |
case RCODE_NOERROR: | |
err = nil | |
case RCODE_FORMERR: | |
err = errors.New("DNS Query Format Error") | |
case RCODE_SERVFAIL: | |
err = errors.New("Server failed to complete the DNS request") | |
case RCODE_NXDOMAIN: | |
err = errors.New("Domain name does not exist") | |
case RCODE_NOTIME: | |
err = errors.New("Function not implemented") | |
case RCODE_REFUSED: | |
err = errors.New("The server refused to answer for the reply") | |
case RCODE_YXDOMAIN: | |
err = errors.New("Name that should not exist, does exist") | |
case RCODE_XRRSET: | |
err = errors.New("RRset should not exist, does exist") | |
case RCODE_NOTAUTH: | |
err = errors.New("Server not authoritative for the zone") | |
case RCODE_NOTZONE: | |
err = errors.New("Name not in zone") | |
} | |
return dnsresp, err | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"sync" | |
) | |
func main() { | |
client := NewDNSQueryClient() | |
domains := []string{ | |
"www.naver.com", | |
"www.google.com", | |
"www.google.co.kr", | |
"www.daum.net", | |
"daum.net", | |
"ssut.me", | |
"translate.google.com", | |
"qiita.com", | |
} | |
tasks := make(chan string, 2) | |
var wg sync.WaitGroup | |
for i := 0; i < 4; i++ { | |
wg.Add(1) | |
go func(wg *sync.WaitGroup) { | |
for domain := range tasks { | |
resp, err := client.Query(domain, "A") | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println(domain, "->", resp.Answer[len(resp.Answer)-1].Data) | |
} | |
wg.Done() | |
}(&wg) | |
} | |
for _, domain := range domains { | |
tasks <- domain | |
} | |
close(tasks) | |
wg.Wait() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment