Skip to content

Commit

Permalink
feat: add tls config for dot lookups
Browse files Browse the repository at this point in the history
Ref #29
  • Loading branch information
mr-karan committed May 18, 2022
1 parent 0ce04d0 commit 53f7b70
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 78 deletions.
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,14 @@ URL scheme of the server is used to identify which resolver to use for lookups.
### Resolver Options

```
--strategy=STRATEGY Specify strategy to query nameserver listed in etc/resolv.conf. Defaults to `all` (`random`, `first`, `all`).
--ndots=INT Specify ndots parameter. Takes value from /etc/resolv.conf if using the system nameserver or 1 otherwise.
--search Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list.
--timeout Specify timeout (in seconds) for the resolver to return a response.
-4 --ipv4 Use IPv4 only.
-6 --ipv6 Use IPv6 only.
--strategy=STRATEGY Specify strategy to query nameserver listed in etc/resolv.conf. Defaults to `all` (`random`, `first`, `all`).
--ndots=INT Specify ndots parameter. Takes value from /etc/resolv.conf if using the system nameserver or 1 otherwise.
--search Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list.
--timeout Specify timeout (in seconds) for the resolver to return a response.
-4 --ipv4 Use IPv4 only.
-6 --ipv6 Use IPv6 only.
--tls-hostname=HOSTNAME Provide a hostname for doing verification of the certificate if the provided DoT nameserver is an IP.
--skip-hostname-verification Skip TLS Hostname Verification in case of DOT Lookups.
```


Expand Down
20 changes: 12 additions & 8 deletions cmd/doggo/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ func main() {
f.BoolP("ipv4", "4", false, "Use IPv4 only")
f.BoolP("ipv6", "6", false, "Use IPv6 only")
f.String("strategy", "all", "Strategy to query nameservers in resolv.conf file (`all`, `random`, `first`)")
f.String("tls-hostname", "", "Provide a hostname for doing verification of the certificate if the provided DoT nameserver is an IP")
f.Bool("skip-hostname-verification", false, "Skip TLS Hostname Verification")

// Output Options
f.BoolP("json", "J", false, "Set the output format as JSON")
Expand Down Expand Up @@ -121,14 +123,16 @@ func main() {

// Load Resolvers.
rslvrs, err := resolvers.LoadResolvers(resolvers.Options{
Nameservers: app.Nameservers,
UseIPv4: app.QueryFlags.UseIPv4,
UseIPv6: app.QueryFlags.UseIPv6,
SearchList: app.ResolverOpts.SearchList,
Ndots: app.ResolverOpts.Ndots,
Timeout: app.QueryFlags.Timeout * time.Second,
Logger: app.Logger,
Strategy: app.QueryFlags.Strategy,
Nameservers: app.Nameservers,
UseIPv4: app.QueryFlags.UseIPv4,
UseIPv6: app.QueryFlags.UseIPv6,
SearchList: app.ResolverOpts.SearchList,
Ndots: app.ResolverOpts.Ndots,
Timeout: app.QueryFlags.Timeout * time.Second,
Logger: app.Logger,
Strategy: app.QueryFlags.Strategy,
InsecureSkipVerify: app.QueryFlags.InsecureSkipVerify,
TLSHostname: app.QueryFlags.TLSHostname,
})
if err != nil {
app.Logger.WithError(err).Error("error loading resolver")
Expand Down
15 changes: 9 additions & 6 deletions cmd/doggo/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@ var appHelpTextTemplate = `{{ "NAME" | color "" "heading" }}:
{{"-x, --reverse" | color "yellow" ""}} Performs a DNS Lookup for an IPv4 or IPv6 address. Sets the query type and class to PTR and IN respectively.
{{ "Resolver Options" | color "" "heading" }}:
{{"--strategy=STRATEGY" | color "yellow" ""}} Specify strategy to query nameserver listed in etc/resolv.conf. ({{"all, random, first" | color "cyan" ""}}).
{{"--ndots=INT" | color "yellow" ""}} Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
{{"--search" | color "yellow" ""}} Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list.
{{"--timeout" | color "yellow" ""}} Specify timeout (in seconds) for the resolver to return a response.
{{"-4 --ipv4" | color "yellow" ""}} Use IPv4 only.
{{"-6 --ipv6" | color "yellow" ""}} Use IPv6 only.
{{"--strategy=STRATEGY" | color "yellow" ""}} Specify strategy to query nameserver listed in etc/resolv.conf. ({{"all, random, first" | color "cyan" ""}}).
{{"--ndots=INT" | color "yellow" ""}} Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
{{"--search" | color "yellow" ""}} Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list.
{{"--timeout" | color "yellow" ""}} Specify timeout (in seconds) for the resolver to return a response.
{{"-4 --ipv4" | color "yellow" ""}} Use IPv4 only.
{{"-6 --ipv6" | color "yellow" ""}} Use IPv6 only.
{{"--ndots=INT" | color "yellow" ""}} Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
{{"--tls-hostname=HOSTNAME" | color "yellow" ""}} Provide a hostname for doing verification of the certificate if the provided DoT nameserver is an IP.
{{"--skip-hostname-verification" | color "yellow" ""}} Skip TLS Hostname Verification in case of DOT Lookups.
{{ "Output Options" | color "" "heading" }}:
{{"-J, --json " | color "yellow" ""}} Format the output as JSON.
Expand Down
32 changes: 17 additions & 15 deletions pkg/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,23 @@ const (
// QueryFlags is used store the query params
// supplied by the user.
type QueryFlags struct {
QNames []string `koanf:"query" json:"query"`
QTypes []string `koanf:"type" json:"type"`
QClasses []string `koanf:"class" json:"class"`
Nameservers []string `koanf:"nameservers" json:"nameservers"`
UseIPv4 bool `koanf:"ipv4" json:"ipv4"`
UseIPv6 bool `koanf:"ipv6" json:"ipv6"`
Ndots int `koanf:"ndots" json:"ndots"`
Timeout time.Duration `koanf:"timeout" json:"timeout"`
Color bool `koanf:"color" json:"-"`
DisplayTimeTaken bool `koanf:"time" json:"-"`
ShowJSON bool `koanf:"json" json:"-"`
ShortOutput bool `koanf:"short" short:"-"`
UseSearchList bool `koanf:"search" json:"-"`
ReverseLookup bool `koanf:"reverse" reverse:"-"`
Strategy string `koanf:"strategy" strategy:"-"`
QNames []string `koanf:"query" json:"query"`
QTypes []string `koanf:"type" json:"type"`
QClasses []string `koanf:"class" json:"class"`
Nameservers []string `koanf:"nameservers" json:"nameservers"`
UseIPv4 bool `koanf:"ipv4" json:"ipv4"`
UseIPv6 bool `koanf:"ipv6" json:"ipv6"`
Ndots int `koanf:"ndots" json:"ndots"`
Timeout time.Duration `koanf:"timeout" json:"timeout"`
Color bool `koanf:"color" json:"-"`
DisplayTimeTaken bool `koanf:"time" json:"-"`
ShowJSON bool `koanf:"json" json:"-"`
ShortOutput bool `koanf:"short" short:"-"`
UseSearchList bool `koanf:"search" json:"-"`
ReverseLookup bool `koanf:"reverse" reverse:"-"`
Strategy string `koanf:"strategy" strategy:"-"`
InsecureSkipVerify bool `koanf:"skip-hostname-verification" skip-hostname-verification:"-"`
TLSHostname string `koanf:"tls-hostname" tls-hostname:"-"`
}

// Nameserver represents the type of Nameserver
Expand Down
16 changes: 10 additions & 6 deletions pkg/resolvers/classic.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package resolvers

import (
"crypto/tls"
"time"

"github.com/miekg/dns"
Expand All @@ -16,10 +17,8 @@ type ClassicResolver struct {

// ClassicResolverOpts holds options for setting up a Classic resolver.
type ClassicResolverOpts struct {
IPv4Only bool
IPv6Only bool
UseTLS bool
UseTCP bool
UseTLS bool
UseTCP bool
}

// NewClassicResolver accepts a list of nameservers and configures a DNS resolver.
Expand All @@ -34,15 +33,20 @@ func NewClassicResolver(server string, classicOpts ClassicResolverOpts, resolver
net = "tcp"
}

if classicOpts.IPv4Only {
if resolverOpts.UseIPv4 {
net = net + "4"
}
if classicOpts.IPv6Only {
if resolverOpts.UseIPv6 {
net = net + "6"
}

if classicOpts.UseTLS {
net = net + "-tls"
// Provide extra TLS config for doing/skipping hostname verification.
client.TLSConfig = &tls.Config{
ServerName: resolverOpts.TLSHostname,
InsecureSkipVerify: resolverOpts.InsecureSkipVerify,
}
}

client.Net = net
Expand Down
6 changes: 2 additions & 4 deletions pkg/resolvers/dnscrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ type DNSCryptResolver struct {

// DNSCryptResolverOpts holds options for setting up a DNSCrypt resolver.
type DNSCryptResolverOpts struct {
IPv4Only bool
IPv6Only bool
UseTLS bool
UseTCP bool
UseTCP bool
}

// NewDNSCryptResolver accepts a list of nameservers and configures a DNS resolver.
Expand All @@ -30,6 +27,7 @@ func NewDNSCryptResolver(server string, dnscryptOpts DNSCryptResolverOpts, resol
if dnscryptOpts.UseTCP {
net = "tcp"
}

client := &dnscrypt.Client{Net: net, Timeout: resolverOpts.Timeout, UDPSize: 4096}
resolverInfo, err := client.Dial(server)
if err != nil {
Expand Down
58 changes: 25 additions & 33 deletions pkg/resolvers/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ import (
// 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
Strategy string
Logger *logrus.Logger

Nameservers []models.Nameserver
UseIPv4 bool
UseIPv6 bool
SearchList []string
Ndots int
Timeout time.Duration
Strategy string
InsecureSkipVerify bool
TLSHostname string
}

// Resolver implements the configuration for a DNS
Expand Down Expand Up @@ -68,18 +71,13 @@ type Authority struct {
// 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
// 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)
rslvr, err := NewDOHResolver(ns.Address, opts)
if err != nil {
return rslvrs, err
}
Expand All @@ -89,11 +87,9 @@ func LoadResolvers(opts Options) ([]Resolver, error) {
opts.Logger.Debug("initiating DOT resolver")
rslvr, err := NewClassicResolver(ns.Address,
ClassicResolverOpts{
IPv4Only: opts.UseIPv4,
IPv6Only: opts.UseIPv6,
UseTLS: true,
UseTCP: true,
}, resolverOpts)
UseTLS: true,
UseTCP: true,
}, opts)

if err != nil {
return rslvrs, err
Expand All @@ -104,11 +100,9 @@ func LoadResolvers(opts Options) ([]Resolver, error) {
opts.Logger.Debug("initiating TCP resolver")
rslvr, err := NewClassicResolver(ns.Address,
ClassicResolverOpts{
IPv4Only: opts.UseIPv4,
IPv6Only: opts.UseIPv6,
UseTLS: false,
UseTCP: true,
}, resolverOpts)
UseTLS: false,
UseTCP: true,
}, opts)
if err != nil {
return rslvrs, err
}
Expand All @@ -118,11 +112,9 @@ func LoadResolvers(opts Options) ([]Resolver, error) {
opts.Logger.Debug("initiating UDP resolver")
rslvr, err := NewClassicResolver(ns.Address,
ClassicResolverOpts{
IPv4Only: opts.UseIPv4,
IPv6Only: opts.UseIPv6,
UseTLS: false,
UseTCP: false,
}, resolverOpts)
UseTLS: false,
UseTCP: false,
}, opts)
if err != nil {
return rslvrs, err
}
Expand All @@ -133,15 +125,15 @@ func LoadResolvers(opts Options) ([]Resolver, error) {
rslvr, err := NewDNSCryptResolver(ns.Address,
DNSCryptResolverOpts{
UseTCP: false,
}, resolverOpts)
}, opts)
if err != nil {
return rslvrs, err
}
rslvrs = append(rslvrs, rslvr)
}
if ns.Type == models.DOQResolver {
opts.Logger.Debug("initiating DOQ resolver")
rslvr, err := NewDOQResolver(ns.Address, resolverOpts)
rslvr, err := NewDOQResolver(ns.Address, opts)
if err != nil {
return rslvrs, err
}
Expand Down

0 comments on commit 53f7b70

Please sign in to comment.