Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOT+DOH: support for root-cas file #8

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*.so
*.dylib
dist/
.idea/

# Test binary, built with `go test -c`
*.test
Expand Down
23 changes: 23 additions & 0 deletions cmd/doggo/cli.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"crypto/x509"
"fmt"
"net/http"
"os"
Expand Down Expand Up @@ -67,6 +68,7 @@ func main() {
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")
f.Var(&headerFlags, "header", "Headers to supply to DoH resolvers")
f.String("root-cas", "", "Root CAs file to use for TLS verification")

// Output Options
f.BoolP("json", "J", false, "Set the output format as JSON")
Expand Down Expand Up @@ -118,6 +120,8 @@ func main() {
app.QueryFlags.QClasses = append(app.QueryFlags.QClasses, qc...)
app.QueryFlags.QNames = append(app.QueryFlags.QNames, qn...)

app.Logger.WithField("query_flags", fmt.Sprintf("%+v", app.QueryFlags)).Debug("Loaded config")

// Check if reverse flag is passed. If it is, then set
// query type as PTR and query class as IN.
// Modify query name like 94.2.0.192.in-addr.arpa if it's an IPv4 address.
Expand Down Expand Up @@ -151,6 +155,24 @@ func main() {
}
}

var certPool *x509.CertPool

if app.QueryFlags.RootCAs != "" {
certPool = x509.NewCertPool()

rootCAs, err := os.ReadFile(app.QueryFlags.RootCAs)
if err != nil {
app.Logger.WithError(err).Error("error reading root CAs")
app.Logger.Exit(2)
}

ok := certPool.AppendCertsFromPEM(rootCAs)
if !ok {
app.Logger.Error("error loading root CAs")
app.Logger.Exit(2)
}
}

// Load Resolvers.
rslvrs, err := resolvers.LoadResolvers(resolvers.Options{
Nameservers: app.Nameservers,
Expand All @@ -164,6 +186,7 @@ func main() {
InsecureSkipVerify: app.QueryFlags.InsecureSkipVerify,
TLSHostname: app.QueryFlags.TLSHostname,
Headers: resolverHeaders,
RootCAs: certPool,
})
if err != nil {
app.Logger.WithError(err).Error("error loading resolver")
Expand Down
1 change: 1 addition & 0 deletions cmd/doggo/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var appHelpTextTemplate = `{{ "NAME" | color "" "heading" }}:
{{"--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.
{{"--header" | color "yellow" ""}} HTTP headers to supply to the resolver. Can supply multiple times.
{{"--root-cas=FILE" | color "yellow" ""}} Root CAs file to use for TLS verification.

{{ "Output Options" | color "" "heading" }}:
{{"-J, --json " | color "yellow" ""}} Format the output as JSON.
Expand Down
1 change: 1 addition & 0 deletions pkg/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type QueryFlags struct {
Strategy string `koanf:"strategy" strategy:"-"`
InsecureSkipVerify bool `koanf:"skip-hostname-verification" skip-hostname-verification:"-"`
TLSHostname string `koanf:"tls-hostname" tls-hostname:"-"`
RootCAs string `koanf:"root-cas"`
}

// Nameserver represents the type of Nameserver
Expand Down
1 change: 1 addition & 0 deletions pkg/resolvers/classic.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func NewClassicResolver(server string, classicOpts ClassicResolverOpts, resolver
client.TLSConfig = &tls.Config{
ServerName: resolverOpts.TLSHostname,
InsecureSkipVerify: resolverOpts.InsecureSkipVerify,
RootCAs: resolverOpts.RootCAs,
}
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/resolvers/doh.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func NewDOHResolver(server string, resolverOpts Options, doh3 bool) (Resolver, e
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: resolverOpts.InsecureSkipVerify,
RootCAs: resolverOpts.RootCAs,
},
},
}
Expand All @@ -49,6 +50,7 @@ func NewDOHResolver(server string, resolverOpts Options, doh3 bool) (Resolver, e
httpClient.Transport = &http3.RoundTripper{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: resolverOpts.InsecureSkipVerify,
RootCAs: resolverOpts.RootCAs,
},
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/resolvers/doq.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func NewDOQResolver(server string, resolverOpts Options) (Resolver, error) {
return &DOQResolver{
tls: &tls.Config{
NextProtos: []string{"doq"},
RootCAs: resolverOpts.RootCAs,
},
server: server,
resolverOptions: resolverOpts,
Expand Down
2 changes: 2 additions & 0 deletions pkg/resolvers/resolver.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package resolvers

import (
"crypto/x509"
"net/http"
"time"

Expand All @@ -24,6 +25,7 @@ type Options struct {
InsecureSkipVerify bool
TLSHostname string
Headers http.Header
RootCAs *x509.CertPool
}

// Resolver implements the configuration for a DNS
Expand Down