feat: refactor resolver in separate package
parent
0e195fd9a7
commit
508a8dd7c4
32
Makefile
32
Makefile
|
@ -1,25 +1,35 @@
|
|||
BIN := ./bin/doggo
|
||||
CLI_BIN := ./bin/doggo-cli.bin
|
||||
API_BIN := ./bin/doggo-api.bin
|
||||
|
||||
HASH := $(shell git rev-parse --short HEAD)
|
||||
BUILD_DATE := $(shell date '+%Y-%m-%d %H:%M:%S')
|
||||
VERSION := ${HASH}
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go build -o ${BIN} -ldflags="-X 'main.buildVersion=${VERSION}' -X 'main.buildDate=${BUILD_DATE}'" ./cmd/doggo/
|
||||
.PHONY: build-cli
|
||||
build-cli:
|
||||
go build -o ${CLI_BIN} -ldflags="-X 'main.buildVersion=${VERSION}' -X 'main.buildDate=${BUILD_DATE}'" ./cmd/doggo/cli/
|
||||
|
||||
.PHONY: run
|
||||
run: build ## Build and Execute the binary after the build step
|
||||
${BIN}
|
||||
.PHONY: build-api
|
||||
build-api:
|
||||
go build -o ${API_BIN} -ldflags="-X 'main.buildVersion=${VERSION}' -X 'main.buildDate=${BUILD_DATE}'" ./cmd/doggo/api/
|
||||
|
||||
|
||||
.PHONY: build
|
||||
build: build-api build-cli
|
||||
|
||||
.PHONY: run-cli
|
||||
run-cli: build-cli ## Build and Execute the CLI binary after the build step.
|
||||
${CLI_BIN}
|
||||
|
||||
.PHONY: run-api
|
||||
run-api: build-api ## Build and Execute the API binary after the build step.
|
||||
${API_BIN}
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
go clean
|
||||
- rm -f ${BIN}
|
||||
- rm -rf ./bin/
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
golangci-lint run
|
||||
|
||||
.PHONY: fresh
|
||||
fresh: clean build
|
||||
|
|
2
TODO.md
2
TODO.md
|
@ -61,7 +61,7 @@
|
|||
- [ ] zsh
|
||||
- [ ] fish
|
||||
- [ ] Add tests for Resolvers.
|
||||
- [ ] Add tests for CLI Output.
|
||||
- [ ] Add tests for CLI Output.
|
||||
- [ ] Homebrew - Goreleaser
|
||||
- [x] Separate Authority/Answer in JSON output.
|
||||
- [x] Error on NXDomain (Related upstream [bug](https://github.com/miekg/dns/issues/1198))
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/knadh/koanf"
|
||||
"github.com/mr-karan/doggo/pkg/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
logger = utils.InitLogger()
|
||||
k = koanf.New(".")
|
||||
)
|
||||
|
||||
type resp struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
r := chi.NewRouter()
|
||||
|
||||
// Setup middlewares.
|
||||
r.Use(middleware.RequestID)
|
||||
r.Use(middleware.RealIP)
|
||||
r.Use(middleware.Logger)
|
||||
r.Use(middleware.Recoverer)
|
||||
|
||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
sendSuccessResponse("Welcome to Doggo DNS!", w)
|
||||
return
|
||||
})
|
||||
|
||||
r.Get("/ping/", func(w http.ResponseWriter, r *http.Request) {
|
||||
sendSuccessResponse("PONG", w)
|
||||
return
|
||||
})
|
||||
|
||||
r.Post("/lookup/", func(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
})
|
||||
|
||||
http.ListenAndServe(":3000", r)
|
||||
}
|
||||
|
||||
// sendResponse sends an HTTP success response.
|
||||
func sendResponse(data interface{}, statusText string, status int, w http.ResponseWriter) {
|
||||
w.WriteHeader(status)
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
out, err := json.Marshal(resp{Status: statusText, Data: data})
|
||||
if err != nil {
|
||||
sendErrorResponse("Internal Server Error", http.StatusInternalServerError, nil, w)
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = w.Write(out)
|
||||
}
|
||||
|
||||
// sendSuccessResponse sends an HTTP success (200 OK) response.
|
||||
func sendSuccessResponse(data interface{}, w http.ResponseWriter) {
|
||||
sendResponse(data, "success", http.StatusOK, w)
|
||||
}
|
||||
|
||||
// sendErrorResponse sends an HTTP error response.
|
||||
func sendErrorResponse(message string, status int, data interface{}, w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(status)
|
||||
|
||||
resp := resp{Status: "error",
|
||||
Message: message,
|
||||
Data: data}
|
||||
|
||||
out, _ := json.Marshal(resp)
|
||||
|
||||
_, _ = w.Write(out)
|
||||
}
|
|
@ -3,11 +3,13 @@ package main
|
|||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/knadh/koanf"
|
||||
"github.com/knadh/koanf/providers/posflag"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/mr-karan/doggo/pkg/resolvers"
|
||||
"github.com/mr-karan/doggo/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
@ -20,7 +22,7 @@ var (
|
|||
|
||||
func main() {
|
||||
var (
|
||||
logger = initLogger()
|
||||
logger = utils.InitLogger()
|
||||
k = koanf.New(".")
|
||||
)
|
||||
|
||||
|
@ -110,15 +112,21 @@ func main() {
|
|||
hub.Logger.Exit(2)
|
||||
}
|
||||
|
||||
// Load Resolver Options.
|
||||
hub.loadResolverOptions()
|
||||
|
||||
// Load Resolvers.
|
||||
err = hub.loadResolvers()
|
||||
rslvrs, err := resolvers.LoadResolvers(resolvers.Options{
|
||||
Nameservers: hub.Nameservers,
|
||||
UseIPv4: hub.QueryFlags.UseIPv4,
|
||||
UseIPv6: hub.QueryFlags.UseIPv6,
|
||||
SearchList: hub.ResolverOpts.SearchList,
|
||||
Ndots: hub.ResolverOpts.Ndots,
|
||||
Timeout: hub.QueryFlags.Timeout * time.Second,
|
||||
Logger: hub.Logger,
|
||||
})
|
||||
if err != nil {
|
||||
hub.Logger.WithError(err).Error("error loading resolver")
|
||||
hub.Logger.Exit(2)
|
||||
}
|
||||
hub.Resolvers = rslvrs
|
||||
|
||||
// Run the app.
|
||||
hub.Logger.Debug("Starting doggo 🐶")
|
||||
|
@ -130,7 +138,7 @@ func main() {
|
|||
// Resolve Queries.
|
||||
var responses []resolvers.Response
|
||||
for _, q := range hub.Questions {
|
||||
for _, rslv := range hub.Resolver {
|
||||
for _, rslv := range hub.Resolvers {
|
||||
resp, err := rslv.Lookup(q)
|
||||
if err != nil {
|
||||
hub.Logger.WithError(err).Error("error looking up DNS records")
|
|
@ -0,0 +1,36 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/miekg/dns"
|
||||
"github.com/mr-karan/doggo/pkg/models"
|
||||
"github.com/mr-karan/doggo/pkg/resolvers"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Hub represents the structure for all app wide configuration.
|
||||
type Hub struct {
|
||||
Logger *logrus.Logger
|
||||
Version string
|
||||
QueryFlags models.QueryFlags
|
||||
UnparsedArgs []string
|
||||
Questions []dns.Question
|
||||
Resolvers []resolvers.Resolver
|
||||
ResolverOpts resolvers.Options
|
||||
Nameservers []models.Nameserver
|
||||
}
|
||||
|
||||
// NewHub initializes an instance of Hub which holds app wide configuration.
|
||||
func NewHub(logger *logrus.Logger, buildVersion string) *Hub {
|
||||
hub := &Hub{
|
||||
Logger: logger,
|
||||
Version: buildVersion,
|
||||
QueryFlags: models.QueryFlags{
|
||||
QNames: []string{},
|
||||
QTypes: []string{},
|
||||
QClasses: []string{},
|
||||
Nameservers: []string{},
|
||||
},
|
||||
Nameservers: []models.Nameserver{},
|
||||
}
|
||||
return hub
|
||||
}
|
|
@ -6,19 +6,7 @@ import (
|
|||
"net/url"
|
||||
|
||||
"github.com/mr-karan/doggo/pkg/config"
|
||||
)
|
||||
|
||||
const (
|
||||
// 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"
|
||||
// DefaultTCPPort specifies the default port for a DNS server connecting over TCP
|
||||
DefaultTCPPort = "53"
|
||||
UDPResolver = "udp"
|
||||
DOHResolver = "doh"
|
||||
TCPResolver = "tcp"
|
||||
DOTResolver = "dot"
|
||||
"github.com/mr-karan/doggo/pkg/models"
|
||||
)
|
||||
|
||||
// loadNameservers reads all the user given
|
||||
|
@ -62,56 +50,56 @@ func (hub *Hub) loadNameservers() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getDefaultServers() ([]Nameserver, int, []string, error) {
|
||||
func getDefaultServers() ([]models.Nameserver, int, []string, error) {
|
||||
dnsServers, ndots, search, err := config.GetDefaultServers()
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
servers := make([]Nameserver, 0, len(dnsServers))
|
||||
servers := make([]models.Nameserver, 0, len(dnsServers))
|
||||
for _, s := range dnsServers {
|
||||
ns := Nameserver{
|
||||
Type: UDPResolver,
|
||||
Address: net.JoinHostPort(s, DefaultUDPPort),
|
||||
ns := models.Nameserver{
|
||||
Type: models.UDPResolver,
|
||||
Address: net.JoinHostPort(s, models.DefaultUDPPort),
|
||||
}
|
||||
servers = append(servers, ns)
|
||||
}
|
||||
return servers, ndots, search, nil
|
||||
}
|
||||
|
||||
func initNameserver(n string) (Nameserver, error) {
|
||||
func initNameserver(n string) (models.Nameserver, error) {
|
||||
// Instantiate a UDP resolver with default port as a fallback.
|
||||
ns := Nameserver{
|
||||
Type: UDPResolver,
|
||||
Address: net.JoinHostPort(n, DefaultUDPPort),
|
||||
ns := models.Nameserver{
|
||||
Type: models.UDPResolver,
|
||||
Address: net.JoinHostPort(n, models.DefaultUDPPort),
|
||||
}
|
||||
u, err := url.Parse(n)
|
||||
if err != nil {
|
||||
return ns, err
|
||||
}
|
||||
if u.Scheme == "https" {
|
||||
ns.Type = DOHResolver
|
||||
ns.Type = models.DOHResolver
|
||||
ns.Address = u.String()
|
||||
}
|
||||
if u.Scheme == "tls" {
|
||||
ns.Type = DOTResolver
|
||||
ns.Type = models.DOTResolver
|
||||
if u.Port() == "" {
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), DefaultTLSPort)
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), models.DefaultTLSPort)
|
||||
} else {
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
|
||||
}
|
||||
}
|
||||
if u.Scheme == "tcp" {
|
||||
ns.Type = TCPResolver
|
||||
ns.Type = models.TCPResolver
|
||||
if u.Port() == "" {
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), DefaultTCPPort)
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), models.DefaultTCPPort)
|
||||
} else {
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
|
||||
}
|
||||
}
|
||||
if u.Scheme == "udp" {
|
||||
ns.Type = UDPResolver
|
||||
ns.Type = models.UDPResolver
|
||||
if u.Port() == "" {
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), DefaultUDPPort)
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), models.DefaultUDPPort)
|
||||
} else {
|
||||
ns.Address = net.JoinHostPort(u.Hostname(), u.Port())
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package main
|
|
@ -1,71 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/mr-karan/doggo/pkg/resolvers"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Hub represents the structure for all app wide configuration.
|
||||
type Hub struct {
|
||||
Logger *logrus.Logger
|
||||
Version string
|
||||
QueryFlags QueryFlags
|
||||
UnparsedArgs []string
|
||||
Questions []dns.Question
|
||||
Resolver []resolvers.Resolver
|
||||
ResolverOpts resolvers.Options
|
||||
Nameservers []Nameserver
|
||||
}
|
||||
|
||||
// QueryFlags is used store the query params
|
||||
// supplied by the user.
|
||||
type QueryFlags struct {
|
||||
QNames []string `koanf:"query"`
|
||||
QTypes []string `koanf:"type"`
|
||||
QClasses []string `koanf:"class"`
|
||||
Nameservers []string `koanf:"nameserver"`
|
||||
UseIPv4 bool `koanf:"ipv4"`
|
||||
UseIPv6 bool `koanf:"ipv6"`
|
||||
DisplayTimeTaken bool `koanf:"time"`
|
||||
ShowJSON bool `koanf:"json"`
|
||||
UseSearchList bool `koanf:"search"`
|
||||
Ndots int `koanf:"ndots"`
|
||||
Color bool `koanf:"color"`
|
||||
Timeout time.Duration `koanf:"timeout"`
|
||||
}
|
||||
|
||||
// Nameserver represents the type of Nameserver
|
||||
// along with the server address.
|
||||
type Nameserver struct {
|
||||
Address string
|
||||
Type string
|
||||
}
|
||||
|
||||
// NewHub initializes an instance of Hub which holds app wide configuration.
|
||||
func NewHub(logger *logrus.Logger, buildVersion string) *Hub {
|
||||
hub := &Hub{
|
||||
Logger: logger,
|
||||
Version: buildVersion,
|
||||
QueryFlags: QueryFlags{
|
||||
QNames: []string{},
|
||||
QTypes: []string{},
|
||||
QClasses: []string{},
|
||||
Nameservers: []string{},
|
||||
},
|
||||
Nameservers: []Nameserver{},
|
||||
}
|
||||
return hub
|
||||
}
|
||||
|
||||
// initLogger initializes logger
|
||||
func initLogger() *logrus.Logger {
|
||||
logger := logrus.New()
|
||||
logger.SetFormatter(&logrus.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
DisableLevelTruncation: true,
|
||||
})
|
||||
return logger
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/mr-karan/doggo/pkg/resolvers"
|
||||
)
|
||||
|
||||
// loadResolverOptions loads the common options
|
||||
// to configure a resolver from the query args.
|
||||
func (hub *Hub) loadResolverOptions() {
|
||||
hub.ResolverOpts.Timeout = hub.QueryFlags.Timeout
|
||||
}
|
||||
|
||||
// loadResolvers loads differently configured
|
||||
// resolvers based on a list of nameserver.
|
||||
func (hub *Hub) loadResolvers() error {
|
||||
var resolverOpts = resolvers.Options{
|
||||
Timeout: hub.QueryFlags.Timeout * time.Second,
|
||||
Ndots: hub.ResolverOpts.Ndots,
|
||||
SearchList: hub.ResolverOpts.SearchList,
|
||||
Logger: hub.Logger,
|
||||
}
|
||||
// for each nameserver, initialise the correct resolver
|
||||
for _, ns := range hub.Nameservers {
|
||||
if ns.Type == DOHResolver {
|
||||
hub.Logger.Debug("initiating DOH resolver")
|
||||
rslvr, err := resolvers.NewDOHResolver(ns.Address, resolverOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hub.Resolver = append(hub.Resolver, rslvr)
|
||||
}
|
||||
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,
|
||||
UseTLS: true,
|
||||
UseTCP: true,
|
||||
}, resolverOpts)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hub.Resolver = append(hub.Resolver, rslvr)
|
||||
}
|
||||
if ns.Type == TCPResolver {
|
||||
hub.Logger.Debug("initiating TCP resolver")
|
||||
rslvr, err := resolvers.NewClassicResolver(ns.Address,
|
||||
resolvers.ClassicResolverOpts{
|
||||
IPv4Only: hub.QueryFlags.UseIPv4,
|
||||
IPv6Only: hub.QueryFlags.UseIPv6,
|
||||
UseTLS: false,
|
||||
UseTCP: true,
|
||||
}, resolverOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hub.Resolver = append(hub.Resolver, rslvr)
|
||||
}
|
||||
if ns.Type == UDPResolver {
|
||||
hub.Logger.Debug("initiating UDP resolver")
|
||||
rslvr, err := resolvers.NewClassicResolver(ns.Address,
|
||||
resolvers.ClassicResolverOpts{
|
||||
IPv4Only: hub.QueryFlags.UseIPv4,
|
||||
IPv6Only: hub.QueryFlags.UseIPv6,
|
||||
UseTLS: false,
|
||||
UseTCP: false,
|
||||
}, resolverOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hub.Resolver = append(hub.Resolver, rslvr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
2
go.mod
2
go.mod
|
@ -4,6 +4,8 @@ go 1.16
|
|||
|
||||
require (
|
||||
github.com/fatih/color v1.10.0
|
||||
github.com/go-chi/chi v1.5.3
|
||||
github.com/go-chi/render v1.0.1
|
||||
github.com/knadh/koanf v0.14.0
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/miekg/dns v1.1.35
|
||||
|
|
10
go.sum
10
go.sum
|
@ -1,4 +1,3 @@
|
|||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -8,6 +7,10 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE
|
|||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-chi/chi v1.5.3 h1:+DVDS9/D3MTbEu3WrrH3oz9oP6PlSPSNj8LLw3X17yU=
|
||||
github.com/go-chi/chi v1.5.3/go.mod h1:Q8xfe6s3fjZyMr8ZTv5jL+vxhVaFyCq2s+RvSfzTD0E=
|
||||
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
|
||||
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
|
@ -37,7 +40,6 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
|
|||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
|
@ -54,20 +56,16 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha
|
|||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
// 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"
|
||||
// DefaultTCPPort specifies the default port for a DNS server connecting over TCP
|
||||
DefaultTCPPort = "53"
|
||||
UDPResolver = "udp"
|
||||
DOHResolver = "doh"
|
||||
TCPResolver = "tcp"
|
||||
DOTResolver = "dot"
|
||||
)
|
||||
|
||||
// QueryFlags is used store the query params
|
||||
// supplied by the user.
|
||||
type QueryFlags struct {
|
||||
QNames []string `koanf:"query"`
|
||||
QTypes []string `koanf:"type"`
|
||||
QClasses []string `koanf:"class"`
|
||||
Nameservers []string `koanf:"nameserver"`
|
||||
UseIPv4 bool `koanf:"ipv4"`
|
||||
UseIPv6 bool `koanf:"ipv6"`
|
||||
DisplayTimeTaken bool `koanf:"time"`
|
||||
ShowJSON bool `koanf:"json"`
|
||||
UseSearchList bool `koanf:"search"`
|
||||
Ndots int `koanf:"ndots"`
|
||||
Color bool `koanf:"color"`
|
||||
Timeout time.Duration `koanf:"timeout"`
|
||||
}
|
||||
|
||||
// Nameserver represents the type of Nameserver
|
||||
// along with the server address.
|
||||
type Nameserver struct {
|
||||
Address string
|
||||
Type string
|
||||
}
|
|
@ -4,16 +4,20 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/mr-karan/doggo/pkg/models"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Options represent a set of common options
|
||||
// to configure a Resolver.
|
||||
type Options struct {
|
||||
SearchList []string
|
||||
Ndots int
|
||||
Timeout time.Duration
|
||||
Logger *logrus.Logger
|
||||
Nameservers []models.Nameserver
|
||||
UseIPv4 bool
|
||||
UseIPv6 bool
|
||||
SearchList []string
|
||||
Ndots int
|
||||
Timeout time.Duration
|
||||
Logger *logrus.Logger
|
||||
}
|
||||
|
||||
// Resolver implements the configuration for a DNS
|
||||
|
@ -59,3 +63,70 @@ type Authority struct {
|
|||
RTT string `json:"rtt"`
|
||||
Nameserver string `json:"nameserver"`
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package utils
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
// InitLogger initializes logger.
|
||||
func InitLogger() *logrus.Logger {
|
||||
logger := logrus.New()
|
||||
logger.SetFormatter(&logrus.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
DisableLevelTruncation: true,
|
||||
})
|
||||
return logger
|
||||
}
|
Loading…
Reference in New Issue