Skip to content

Commit

Permalink
Merge pull request #20 from blinklabs-io/feat/dns-fallback
Browse files Browse the repository at this point in the history
feat: DNS fallback server support
  • Loading branch information
agaffney authored Aug 11, 2023
2 parents b35380a + 9edaf15 commit ede4734
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
7 changes: 5 additions & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ type LoggingConfig struct {
}

type DnsConfig struct {
ListenAddress string `yaml:"address" envconfig:"DNS_LISTEN_ADDRESS"`
ListenPort uint `yaml:"port" envconfig:"DNS_LISTEN_PORT"`
ListenAddress string `yaml:"address" envconfig:"DNS_LISTEN_ADDRESS"`
ListenPort uint `yaml:"port" envconfig:"DNS_LISTEN_PORT"`
FallbackServers []string `yaml:"fallbackServers" envconfig:"DNS_FALLBACK_SERVERS"`
}

type DebugConfig struct {
Expand Down Expand Up @@ -78,6 +79,8 @@ var globalConfig = &Config{
Dns: DnsConfig{
ListenAddress: "",
ListenPort: 8053,
// hdns.io
FallbackServers: []string{"103.196.38.38", "103.196.38.39", "103.196.38.40"},
},
Debug: DebugConfig{
ListenAddress: "localhost",
Expand Down
45 changes: 45 additions & 0 deletions internal/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dns

import (
"fmt"
"math/rand"
"net"
"strings"

Expand Down Expand Up @@ -84,9 +85,53 @@ func handleQuery(w dns.ResponseWriter, r *dns.Msg) {
return
}

// Query fallback servers
fallbackResp, err := queryFallbackServer(r)
if err != nil {
// Send failure response
m.SetRcode(r, dns.RcodeServerFailure)
if err := w.WriteMsg(m); err != nil {
logger.Errorf("failed to write response: %s", err)
}
logger.Errorf("failed to query fallback server: %s", err)
return
} else {
// Copy relevant data from fallback response into our response
m.SetRcode(r, fallbackResp.MsgHdr.Rcode)
m.RecursionDesired = r.RecursionDesired
m.RecursionAvailable = fallbackResp.RecursionAvailable
if fallbackResp.Ns != nil {
m.Ns = append(m.Ns, fallbackResp.Ns...)
}
if fallbackResp.Answer != nil {
m.Answer = append(m.Answer, fallbackResp.Answer...)
}
if fallbackResp.Extra != nil {
m.Extra = append(m.Extra, fallbackResp.Extra...)
}
// Send response
if err := w.WriteMsg(m); err != nil {
logger.Errorf("failed to write response: %s", err)
}
return
}

// Return NXDOMAIN if we have no information about the requested domain or any of its parents
m.SetRcode(r, dns.RcodeNameError)

Check failure on line 120 in internal/dns/dns.go

View workflow job for this annotation

GitHub Actions / lint (1.19.x, ubuntu-latest)

unreachable: unreachable code (govet)

Check failure on line 120 in internal/dns/dns.go

View workflow job for this annotation

GitHub Actions / lint (1.19.x, ubuntu-latest)

unreachable: unreachable code (govet)
if err := w.WriteMsg(m); err != nil {
logger.Errorf("failed to write response: %s", err)
}
}

func queryFallbackServer(req *dns.Msg) (*dns.Msg, error) {
// Pick random fallback server
cfg := config.GetConfig()
fallbackServer := cfg.Dns.FallbackServers[rand.Intn(len(cfg.Dns.FallbackServers))]
// Query chosen server
m := new(dns.Msg)
m.Id = dns.Id()
m.RecursionDesired = req.RecursionDesired
m.Question = append(m.Question, req.Question...)
in, err := dns.Exchange(m, fmt.Sprintf("%s:53", fallbackServer))
return in, err
}

0 comments on commit ede4734

Please sign in to comment.