-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
199 additions
and
70 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package dns | ||
|
||
import ( | ||
"context" | ||
"net" | ||
"time" | ||
) | ||
|
||
var ( | ||
dnsCache = make(map[string]bool) | ||
dnsResolver = &net.Resolver{} | ||
) | ||
|
||
func init() { | ||
//dnsResolver.PreferGo = true | ||
dnsResolver.StrictErrors = false | ||
} | ||
|
||
func noSuchHostDNSError(err error) bool { | ||
dnsErr, ok := err.(*net.DNSError) | ||
if !ok { | ||
// not a DNSError | ||
return false | ||
} | ||
return dnsErr.Err == "no such host" | ||
} | ||
|
||
// HasRecords does NS, CNAME, A, and AAAA lookups with a timeout | ||
// returns error when no NS found, does not use TLDPlus1 | ||
func HasRecords(domain string, timeout time.Duration) (bool, error) { | ||
ctx, cancel := context.WithTimeout(context.Background(), timeout) | ||
defer cancel() | ||
|
||
// first check for NS | ||
ns, err := dnsResolver.LookupNS(ctx, domain) | ||
if err != nil && !noSuchHostDNSError(err) { | ||
//fmt.Println("NS error ", err) | ||
return false, err | ||
} | ||
if len(ns) > 0 { | ||
//fmt.Printf("Found %d NS for %s\n", len(ns), domain) | ||
return true, nil | ||
} | ||
|
||
// next check for CNAME | ||
cname, err := dnsResolver.LookupCNAME(ctx, domain) | ||
if err != nil && !noSuchHostDNSError(err) { | ||
//fmt.Println("cname error ", err) | ||
return false, err | ||
} | ||
if len(cname) > 2 { | ||
//fmt.Printf("found CNAME %s for %s\n", cname, domain) | ||
return true, nil | ||
} | ||
|
||
// next check for IP | ||
addrs, err := dnsResolver.LookupHost(ctx, domain) | ||
if err != nil && !noSuchHostDNSError(err) { | ||
//fmt.Println("ip error ", err) | ||
return false, err | ||
} | ||
if len(addrs) > 0 { | ||
//fmt.Printf("Found %d IPs for %s\n", len(addrs), domain) | ||
return true, nil | ||
} | ||
|
||
//fmt.Printf("Found no DNS records for %s\n", domain) | ||
return false, nil | ||
} | ||
|
||
// HasRecordsCache returns true if the domain has no DNS records (at the tldplus1 level) | ||
// uses a cache to store results to prevent lots of DNS lookups | ||
func HasRecordsCache(domain string, timeout time.Duration) (bool, error) { | ||
domain, err := TLDPlus1(domain) | ||
if err != nil { | ||
return false, err | ||
} | ||
hasDNS, found := dnsCache[domain] | ||
if found { | ||
return hasDNS, nil | ||
} | ||
hasRecords, err := HasRecords(domain, timeout) | ||
if err != nil { | ||
dnsCache[domain] = hasRecords | ||
} | ||
return hasRecords, err | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package dns | ||
|
||
import ( | ||
"net/http" | ||
"time" | ||
|
||
"github.com/weppos/publicsuffix-go/publicsuffix" | ||
) | ||
|
||
var ( | ||
suffixListFindOptions = &publicsuffix.FindOptions{ | ||
IgnorePrivate: true, | ||
DefaultRule: publicsuffix.DefaultRule, | ||
} | ||
suffixListURL = "https://publicsuffix.org/list/public_suffix_list.dat" | ||
suffixList = publicsuffix.DefaultList | ||
nsCache = make(map[string]bool) | ||
) | ||
|
||
// UpdatePublicSuffixList gets a new copy of the public suffix list from the internat and updates the built in copy with the new rules | ||
func UpdatePublicSuffixList(timeout time.Duration) error { | ||
suffixListParseOptions := &publicsuffix.ParserOption{ | ||
PrivateDomains: !suffixListFindOptions.IgnorePrivate, | ||
} | ||
client := http.Client{ | ||
Timeout: timeout, | ||
} | ||
resp, err := client.Get(suffixListURL) | ||
if err != nil { | ||
return err | ||
} | ||
defer resp.Body.Close() | ||
newSuffixList := publicsuffix.NewList() | ||
newSuffixList.Load(resp.Body, suffixListParseOptions) | ||
suffixList = newSuffixList | ||
return err | ||
} | ||
|
||
// TLDPlus1 returns TLD+1 of domain | ||
func TLDPlus1(domain string) (string, error) { | ||
return publicsuffix.DomainFromListWithOptions(suffixList, domain, suffixListFindOptions) | ||
} |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Oops, something went wrong.