Merge pull request #139 from projectdiscovery/feature-ipv6-dns

adding support for ipv6
This commit is contained in:
bauthard 2020-10-14 01:31:29 +05:30 committed by GitHub
commit c3962a518f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 17 deletions

View File

@ -554,7 +554,7 @@ retry:
)
dnsData, err := cache.GetDNSData(domain)
if dnsData != nil && err == nil {
ips = dnsData.IPs
ips = append(dnsData.IP4s, dnsData.IP6s...)
cnames = dnsData.CNAMEs
} else {
ips = append(ips, ip)

View File

@ -58,7 +58,12 @@ func New(options Options) (*Cache, error) {
// Lookup a hostname
func (c *Cache) Lookup(hostname string) (*dns.Result, error) {
if ip := net.ParseIP(hostname); ip != nil {
return &dns.Result{IPs: []string{hostname}}, nil
if ip.To4() != nil {
return &dns.Result{IP4s: []string{hostname}}, nil
}
if ip.To16() != nil {
return &dns.Result{IP6s: []string{hostname}}, nil
}
}
hostnameBytes := []byte(hostname)
value, err := c.cache.Get(hostnameBytes)

View File

@ -44,10 +44,12 @@ func NewDialer(options Options) (DialerFunc, error) {
// we need to filter out empty records
hostname := address[:separator]
dnsResult, err := cache.Lookup(hostname)
if err != nil || len(dnsResult.IPs) == 0 {
if err != nil || len(dnsResult.IP4s)+len(dnsResult.IP6s) == 0 {
return nil, &NoAddressFoundError{}
} // Dial to the IPs finally.
for _, ip := range dnsResult.IPs {
}
// Dial to the IPs finally.
for _, ip := range append(dnsResult.IP4s, dnsResult.IP6s...) {
conn, err = dialer.DialContext(ctx, network, ip+address[separator:])
if err == nil {
setErr := dialerHistory.Set([]byte(hostname), []byte(ip), 0)

View File

@ -21,7 +21,8 @@ type Client struct {
// Result containing ip and time to live
type Result struct {
IPs []string
IP4s []string
IP6s []string
CNAMEs []string
TTL int
}
@ -60,44 +61,61 @@ func New(baseResolvers []string, maxRetries int) (*Client, error) {
}
// Resolve ips for a record
func (c *Client) Resolve(host string) (Result, error) {
func (c *Client) Resolve(host string) (result Result, err error) {
// retrieve ipv4 addresses
err = c.query(host, dns.TypeA, &result)
if err != nil {
return
}
// retrieve ipv6 addresses
err = c.query(host, dns.TypeAAAA, &result)
return
}
func (c *Client) query(host string, queryType uint16, result *Result) error {
msg := new(dns.Msg)
msg.Id = dns.Id()
msg.RecursionDesired = true
msg.Question = make([]dns.Question, 1)
msg.Question[0] = dns.Question{
Name: dns.Fqdn(host),
Qtype: dns.TypeA,
Qtype: queryType,
Qclass: dns.ClassINET,
}
resolver := c.resolvers[rand.Intn(len(c.resolvers))]
var err error
var answer *dns.Msg
result := Result{}
for i := 0; i < c.maxRetries; i++ {
answer, err = dns.Exchange(msg, resolver)
answer, err := dns.Exchange(msg, resolver)
if err != nil {
continue
}
if answer != nil && answer.Rcode != dns.RcodeSuccess {
return result, errors.New(dns.RcodeToString[answer.Rcode])
return errors.New(dns.RcodeToString[answer.Rcode])
}
for _, record := range answer.Answer {
switch t := record.(type) {
case *dns.A:
ip := t.A.String()
if ip != "" {
result.IPs = append(result.IPs, t.A.String())
result.IP4s = append(result.IP4s, t.A.String())
result.TTL = int(t.Header().Ttl)
}
case *dns.AAAA:
ip := t.AAAA.String()
if ip != "" {
result.IP6s = append(result.IP6s, t.AAAA.String())
result.TTL = int(t.Header().Ttl)
}
case *dns.CNAME:
if t.Target != "" {
if queryType == dns.TypeA && t.Target != "" {
result.CNAMEs = append(result.CNAMEs, strings.TrimSuffix(t.Target, "."))
}
}
}
return result, nil
break
}
return result, err
return nil
}