Skip to content

Commit ede4734

Browse files
authored
Merge pull request #20 from blinklabs-io/feat/dns-fallback
feat: DNS fallback server support
2 parents b35380a + 9edaf15 commit ede4734

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

internal/config/config.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ type LoggingConfig struct {
4141
}
4242

4343
type DnsConfig struct {
44-
ListenAddress string `yaml:"address" envconfig:"DNS_LISTEN_ADDRESS"`
45-
ListenPort uint `yaml:"port" envconfig:"DNS_LISTEN_PORT"`
44+
ListenAddress string `yaml:"address" envconfig:"DNS_LISTEN_ADDRESS"`
45+
ListenPort uint `yaml:"port" envconfig:"DNS_LISTEN_PORT"`
46+
FallbackServers []string `yaml:"fallbackServers" envconfig:"DNS_FALLBACK_SERVERS"`
4647
}
4748

4849
type DebugConfig struct {
@@ -78,6 +79,8 @@ var globalConfig = &Config{
7879
Dns: DnsConfig{
7980
ListenAddress: "",
8081
ListenPort: 8053,
82+
// hdns.io
83+
FallbackServers: []string{"103.196.38.38", "103.196.38.39", "103.196.38.40"},
8184
},
8285
Debug: DebugConfig{
8386
ListenAddress: "localhost",

internal/dns/dns.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dns
22

33
import (
44
"fmt"
5+
"math/rand"
56
"net"
67
"strings"
78

@@ -84,9 +85,53 @@ func handleQuery(w dns.ResponseWriter, r *dns.Msg) {
8485
return
8586
}
8687

88+
// Query fallback servers
89+
fallbackResp, err := queryFallbackServer(r)
90+
if err != nil {
91+
// Send failure response
92+
m.SetRcode(r, dns.RcodeServerFailure)
93+
if err := w.WriteMsg(m); err != nil {
94+
logger.Errorf("failed to write response: %s", err)
95+
}
96+
logger.Errorf("failed to query fallback server: %s", err)
97+
return
98+
} else {
99+
// Copy relevant data from fallback response into our response
100+
m.SetRcode(r, fallbackResp.MsgHdr.Rcode)
101+
m.RecursionDesired = r.RecursionDesired
102+
m.RecursionAvailable = fallbackResp.RecursionAvailable
103+
if fallbackResp.Ns != nil {
104+
m.Ns = append(m.Ns, fallbackResp.Ns...)
105+
}
106+
if fallbackResp.Answer != nil {
107+
m.Answer = append(m.Answer, fallbackResp.Answer...)
108+
}
109+
if fallbackResp.Extra != nil {
110+
m.Extra = append(m.Extra, fallbackResp.Extra...)
111+
}
112+
// Send response
113+
if err := w.WriteMsg(m); err != nil {
114+
logger.Errorf("failed to write response: %s", err)
115+
}
116+
return
117+
}
118+
87119
// Return NXDOMAIN if we have no information about the requested domain or any of its parents
88120
m.SetRcode(r, dns.RcodeNameError)
89121
if err := w.WriteMsg(m); err != nil {
90122
logger.Errorf("failed to write response: %s", err)
91123
}
92124
}
125+
126+
func queryFallbackServer(req *dns.Msg) (*dns.Msg, error) {
127+
// Pick random fallback server
128+
cfg := config.GetConfig()
129+
fallbackServer := cfg.Dns.FallbackServers[rand.Intn(len(cfg.Dns.FallbackServers))]
130+
// Query chosen server
131+
m := new(dns.Msg)
132+
m.Id = dns.Id()
133+
m.RecursionDesired = req.RecursionDesired
134+
m.Question = append(m.Question, req.Question...)
135+
in, err := dns.Exchange(m, fmt.Sprintf("%s:53", fallbackServer))
136+
return in, err
137+
}

0 commit comments

Comments
 (0)