doggo/internal/app/nameservers.go

127 lines
3.4 KiB
Go
Raw Normal View History

package app
2020-12-17 12:27:44 +01:00
import (
"fmt"
"net"
"net/url"
"github.com/ameshkov/dnsstamps"
"github.com/mr-karan/doggo/pkg/config"
"github.com/mr-karan/doggo/pkg/models"
2020-12-17 17:38:23 +01:00
)
// LoadNameservers reads all the user given
// nameservers and loads to App.
func (app *App) LoadNameservers() error {
for _, srv := range app.QueryFlags.Nameservers {
2020-12-17 12:27:44 +01:00
ns, err := initNameserver(srv)
if err != nil {
return fmt.Errorf("error parsing nameserver: %s", srv)
}
// check if properly initialised.
if ns.Address != "" && ns.Type != "" {
app.Nameservers = append(app.Nameservers, ns)
2020-12-17 12:27:44 +01:00
}
}
// Set `ndots` to the user specified value.
app.ResolverOpts.Ndots = app.QueryFlags.Ndots
2020-12-17 12:27:44 +01:00
// fallback to system nameserver
// in case no nameserver is specified by user.
if len(app.Nameservers) == 0 {
2020-12-24 17:25:20 +01:00
ns, ndots, search, err := getDefaultServers()
2020-12-17 12:27:44 +01:00
if err != nil {
return fmt.Errorf("error fetching system default nameserver")
}
// `-1` indicates the flag is not set.
// use from config if user hasn't specified any value.
if app.ResolverOpts.Ndots == -1 {
app.ResolverOpts.Ndots = ndots
2020-12-24 17:25:20 +01:00
}
if len(search) > 0 && app.QueryFlags.UseSearchList {
app.ResolverOpts.SearchList = search
2020-12-17 12:27:44 +01:00
}
app.Nameservers = append(app.Nameservers, ns...)
2020-12-17 12:27:44 +01:00
}
// if the user hasn't given any override of `ndots` AND has
// given a custom nameserver. Set `ndots` to 1 as the fallback value
if app.ResolverOpts.Ndots == -1 {
app.ResolverOpts.Ndots = 0
}
2020-12-17 12:27:44 +01:00
return nil
}
func initNameserver(n string) (models.Nameserver, error) {
2020-12-17 17:38:23 +01:00
// Instantiate a UDP resolver with default port as a fallback.
ns := models.Nameserver{
Type: models.UDPResolver,
Address: net.JoinHostPort(n, models.DefaultUDPPort),
2020-12-17 12:27:44 +01:00
}
u, err := url.Parse(n)
if err != nil {
return ns, err
}
if u.Scheme == "sdns" {
stamp, err := dnsstamps.NewServerStampFromString(n)
if err != nil {
return ns, err
}
switch stamp.Proto {
case dnsstamps.StampProtoTypeDoH:
ns.Type = models.DOHResolver
address := url.URL{Scheme: "https", Host: stamp.ProviderName, Path: stamp.Path}
ns.Address = address.String()
case dnsstamps.StampProtoTypeDNSCrypt:
ns.Type = models.DNSCryptResolver
ns.Address = n
default:
return ns, fmt.Errorf("unsupported protocol: %v", stamp.Proto.String())
}
}
2020-12-17 12:27:44 +01:00
if u.Scheme == "https" {
ns.Type = models.DOHResolver
2020-12-17 12:27:44 +01:00
ns.Address = u.String()
}
if u.Scheme == "tls" {
ns.Type = models.DOTResolver
2020-12-17 12:27:44 +01:00
if u.Port() == "" {
ns.Address = net.JoinHostPort(u.Hostname(), models.DefaultTLSPort)
2020-12-17 12:27:44 +01:00
} else {
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
}
}
if u.Scheme == "tcp" {
ns.Type = models.TCPResolver
2020-12-17 12:27:44 +01:00
if u.Port() == "" {
ns.Address = net.JoinHostPort(u.Hostname(), models.DefaultTCPPort)
2020-12-17 12:27:44 +01:00
} else {
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
}
}
if u.Scheme == "udp" {
ns.Type = models.UDPResolver
2020-12-17 12:27:44 +01:00
if u.Port() == "" {
ns.Address = net.JoinHostPort(u.Hostname(), models.DefaultUDPPort)
2020-12-17 12:27:44 +01:00
} else {
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
}
}
return ns, nil
}
func getDefaultServers() ([]models.Nameserver, int, []string, error) {
dnsServers, ndots, search, err := config.GetDefaultServers()
if err != nil {
return nil, 0, nil, err
}
servers := make([]models.Nameserver, 0, len(dnsServers))
for _, s := range dnsServers {
ns := models.Nameserver{
Type: models.UDPResolver,
Address: net.JoinHostPort(s, models.DefaultUDPPort),
}
servers = append(servers, ns)
}
return servers, ndots, search, nil
}