doggo/pkg/resolvers/resolver.go

133 lines
3.3 KiB
Go
Raw Normal View History

2020-12-11 12:18:54 +01:00
package resolvers
2020-12-12 11:57:13 +01:00
import (
"time"
"github.com/miekg/dns"
"github.com/mr-karan/doggo/pkg/models"
2020-12-24 17:25:20 +01:00
"github.com/sirupsen/logrus"
2020-12-12 11:57:13 +01:00
)
2020-12-11 12:18:54 +01:00
2020-12-24 17:25:20 +01:00
// Options represent a set of common options
// to configure a Resolver.
type Options struct {
Nameservers []models.Nameserver
UseIPv4 bool
UseIPv6 bool
SearchList []string
Ndots int
Timeout time.Duration
Logger *logrus.Logger
2020-12-24 17:25:20 +01:00
}
2020-12-12 07:16:13 +01:00
// Resolver implements the configuration for a DNS
// Client. Different types of providers can load
// a DNS Resolver satisfying this interface.
2020-12-11 12:18:54 +01:00
type Resolver interface {
2020-12-24 17:25:20 +01:00
Lookup(dns.Question) (Response, error)
2020-12-12 11:57:13 +01:00
}
// Response represents a custom output format
// for DNS queries. It wraps metadata about the DNS query
2020-12-12 11:57:13 +01:00
// and the DNS Answer as well.
type Response struct {
2020-12-24 17:25:20 +01:00
Answers []Answer `json:"answers"`
Authorities []Authority `json:"authorities"`
Questions []Question `json:"questions"`
}
type Question struct {
Name string `json:"name"`
Type string `json:"type"`
Class string `json:"class"`
}
type Answer struct {
Name string `json:"name"`
Type string `json:"type"`
Class string `json:"class"`
TTL string `json:"ttl"`
Address string `json:"address"`
Status string `json:"status"`
RTT string `json:"rtt"`
Nameserver string `json:"nameserver"`
}
type Authority struct {
Name string `json:"name"`
Type string `json:"type"`
Class string `json:"class"`
TTL string `json:"ttl"`
MName string `json:"mname"`
Status string `json:"status"`
RTT string `json:"rtt"`
Nameserver string `json:"nameserver"`
2020-12-11 12:18:54 +01:00
}
// LoadResolvers loads differently configured
// resolvers based on a list of nameserver.
func LoadResolvers(opts Options) ([]Resolver, error) {
var resolverOpts = Options{
Timeout: opts.Timeout,
Ndots: opts.Ndots,
SearchList: opts.SearchList,
Logger: opts.Logger,
}
// for each nameserver, initialise the correct resolver
rslvrs := make([]Resolver, 0, len(opts.Nameservers))
for _, ns := range opts.Nameservers {
if ns.Type == models.DOHResolver {
opts.Logger.Debug("initiating DOH resolver")
rslvr, err := NewDOHResolver(ns.Address, resolverOpts)
if err != nil {
return rslvrs, err
}
rslvrs = append(rslvrs, rslvr)
}
if ns.Type == models.DOTResolver {
opts.Logger.Debug("initiating DOT resolver")
rslvr, err := NewClassicResolver(ns.Address,
ClassicResolverOpts{
IPv4Only: opts.UseIPv4,
IPv6Only: opts.UseIPv6,
UseTLS: true,
UseTCP: true,
}, resolverOpts)
if err != nil {
return rslvrs, err
}
rslvrs = append(rslvrs, rslvr)
}
if ns.Type == models.TCPResolver {
opts.Logger.Debug("initiating TCP resolver")
rslvr, err := NewClassicResolver(ns.Address,
ClassicResolverOpts{
IPv4Only: opts.UseIPv4,
IPv6Only: opts.UseIPv6,
UseTLS: false,
UseTCP: true,
}, resolverOpts)
if err != nil {
return rslvrs, err
}
rslvrs = append(rslvrs, rslvr)
}
if ns.Type == models.UDPResolver {
opts.Logger.Debug("initiating UDP resolver")
rslvr, err := NewClassicResolver(ns.Address,
ClassicResolverOpts{
IPv4Only: opts.UseIPv4,
IPv6Only: opts.UseIPv6,
UseTLS: false,
UseTCP: false,
}, resolverOpts)
if err != nil {
return rslvrs, err
}
rslvrs = append(rslvrs, rslvr)
}
}
return rslvrs, nil
}