doggo/cmd/resolver.go

161 lines
4.2 KiB
Go
Raw Normal View History

2020-12-11 12:18:54 +01:00
package main
import (
2020-12-16 14:08:34 +01:00
"errors"
"fmt"
"net"
"net/url"
"runtime"
"time"
2020-12-11 12:18:54 +01:00
2020-12-16 14:08:34 +01:00
"github.com/miekg/dns"
2020-12-11 12:18:54 +01:00
"github.com/mr-karan/doggo/pkg/resolvers"
)
2020-12-16 14:08:34 +01:00
const (
//DefaultResolvConfPath specifies path to default resolv config file on UNIX.
DefaultResolvConfPath = "/etc/resolv.conf"
// DefaultTLSPort specifies the default port for a DNS server connecting over TCP over TLS
DefaultTLSPort = "853"
// DefaultUDPPort specifies the default port for a DNS server connecting over UDP
DefaultUDPPort = "53"
2020-12-16 15:10:01 +01:00
DefaultTCPPort = "53"
2020-12-16 14:25:07 +01:00
UDPResolver = "udp"
DOHResolver = "doh"
TCPResolver = "tcp"
DOTResolver = "dot"
2020-12-16 14:08:34 +01:00
)
2020-12-12 11:57:13 +01:00
// initResolver checks for various flags and initialises
2020-12-12 08:46:45 +01:00
// the correct resolver based on the config.
2020-12-13 13:19:10 +01:00
func (hub *Hub) initResolver() error {
2020-12-16 14:08:34 +01:00
// for each nameserver, initialise the correct resolver
for _, ns := range hub.Nameservers {
2020-12-16 14:25:07 +01:00
if ns.Type == DOHResolver {
2020-12-16 14:08:34 +01:00
hub.Logger.Debug("initiating DOH resolver")
rslvr, err := resolvers.NewDOHResolver(ns.Address, resolvers.DOHResolverOpts{
Timeout: hub.QueryFlags.Timeout * time.Second,
})
if err != nil {
return err
}
hub.Resolver = append(hub.Resolver, rslvr)
2020-12-12 07:16:13 +01:00
}
2020-12-16 15:10:01 +01:00
if ns.Type == DOTResolver {
hub.Logger.Debug("initiating DOT resolver")
rslvr, err := resolvers.NewClassicResolver(ns.Address, resolvers.ClassicResolverOpts{
IPv4Only: hub.QueryFlags.UseIPv4,
IPv6Only: hub.QueryFlags.UseIPv6,
Timeout: hub.QueryFlags.Timeout * time.Second,
UseTLS: true,
UseTCP: true,
})
if err != nil {
return err
}
hub.Resolver = append(hub.Resolver, rslvr)
}
2020-12-16 14:25:07 +01:00
if ns.Type == TCPResolver {
2020-12-16 14:08:34 +01:00
hub.Logger.Debug("initiating TCP resolver")
2020-12-16 15:10:01 +01:00
rslvr, err := resolvers.NewClassicResolver(ns.Address, resolvers.ClassicResolverOpts{
2020-12-16 14:08:34 +01:00
IPv4Only: hub.QueryFlags.UseIPv4,
IPv6Only: hub.QueryFlags.UseIPv6,
Timeout: hub.QueryFlags.Timeout * time.Second,
2020-12-16 15:10:01 +01:00
UseTLS: false,
UseTCP: true,
2020-12-16 14:08:34 +01:00
})
if err != nil {
return err
}
hub.Resolver = append(hub.Resolver, rslvr)
2020-12-11 12:18:54 +01:00
}
2020-12-16 14:25:07 +01:00
if ns.Type == UDPResolver {
2020-12-16 14:08:34 +01:00
hub.Logger.Debug("initiating UDP resolver")
2020-12-16 15:10:01 +01:00
rslvr, err := resolvers.NewClassicResolver(ns.Address, resolvers.ClassicResolverOpts{
2020-12-16 14:08:34 +01:00
IPv4Only: hub.QueryFlags.UseIPv4,
IPv6Only: hub.QueryFlags.UseIPv6,
Timeout: hub.QueryFlags.Timeout * time.Second,
2020-12-16 15:10:01 +01:00
UseTLS: false,
UseTCP: false,
2020-12-16 14:08:34 +01:00
})
if err != nil {
return err
}
hub.Resolver = append(hub.Resolver, rslvr)
2020-12-12 07:16:13 +01:00
}
2020-12-11 12:18:54 +01:00
}
return nil
}
2020-12-16 14:08:34 +01:00
func getDefaultServers() ([]Nameserver, error) {
if runtime.GOOS == "windows" {
// TODO: Add a method for reading system default nameserver in windows.
return nil, errors.New(`unable to read default nameservers in this machine`)
}
// if no nameserver is provided, take it from `resolv.conf`
cfg, err := dns.ClientConfigFromFile(DefaultResolvConfPath)
if err != nil {
return nil, err
}
servers := make([]Nameserver, 0, len(cfg.Servers))
for _, s := range cfg.Servers {
ip := net.ParseIP(s)
// handle IPv6
if ip != nil && ip.To4() != nil {
ns := Nameserver{
2020-12-16 14:25:07 +01:00
Type: UDPResolver,
2020-12-16 14:08:34 +01:00
Address: fmt.Sprintf("%s:%s", s, cfg.Port),
}
servers = append(servers, ns)
} else {
ns := Nameserver{
2020-12-16 14:25:07 +01:00
Type: UDPResolver,
2020-12-16 14:08:34 +01:00
Address: fmt.Sprintf("[%s]:%s", s, cfg.Port),
}
servers = append(servers, ns)
}
}
return servers, nil
}
func initNameserver(n string) (Nameserver, error) {
// Instantiate a dumb UDP resolver as a fallback.
ns := Nameserver{
2020-12-16 14:25:07 +01:00
Type: UDPResolver,
2020-12-16 14:08:34 +01:00
Address: n,
}
u, err := url.Parse(n)
if err != nil {
return ns, err
}
if u.Scheme == "https" {
2020-12-16 14:25:07 +01:00
ns.Type = DOHResolver
2020-12-16 14:08:34 +01:00
ns.Address = u.String()
}
2020-12-16 15:10:01 +01:00
if u.Scheme == "tls" {
ns.Type = DOTResolver
if u.Port() == "" {
ns.Address = net.JoinHostPort(u.Hostname(), DefaultTLSPort)
} else {
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
}
}
2020-12-16 14:08:34 +01:00
if u.Scheme == "tcp" {
2020-12-16 14:25:07 +01:00
ns.Type = TCPResolver
2020-12-16 15:10:01 +01:00
if u.Port() == "" {
ns.Address = net.JoinHostPort(u.Hostname(), DefaultTCPPort)
} else {
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
2020-12-16 14:08:34 +01:00
}
}
if u.Scheme == "udp" {
2020-12-16 14:25:07 +01:00
ns.Type = UDPResolver
2020-12-16 14:08:34 +01:00
if u.Port() == "" {
ns.Address = net.JoinHostPort(u.Hostname(), DefaultUDPPort)
} else {
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
}
}
return ns, nil
}