Skip to content

Commit 9f0e696

Browse files
authored
Merge pull request #10 from blinklabs-io/feat/indexer-dns-responses
feat: use indexer data for DNS responses
2 parents 5b8a684 + 4000299 commit 9f0e696

File tree

2 files changed

+100
-22
lines changed

2 files changed

+100
-22
lines changed

internal/dns/dns.go

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package dns
22

33
import (
44
"fmt"
5+
"net"
56

67
"github.com/blinklabs-io/chnsd/internal/config"
8+
"github.com/blinklabs-io/chnsd/internal/indexer"
79
"github.com/blinklabs-io/chnsd/internal/logging"
810

911
"github.com/miekg/dns"
@@ -13,7 +15,7 @@ func Start() error {
1315
cfg := config.GetConfig()
1416
listenAddr := fmt.Sprintf("%s:%d", cfg.Dns.ListenAddress, cfg.Dns.ListenPort)
1517
// Setup handler
16-
dns.HandleFunc(".", handleTest)
18+
dns.HandleFunc(".", handleQuery)
1719
// UDP listener
1820
serverUdp := &dns.Server{Addr: listenAddr, Net: "udp", TsigSecret: nil, ReusePort: true}
1921
go startListener(serverUdp)
@@ -29,25 +31,44 @@ func startListener(server *dns.Server) {
2931
}
3032
}
3133

32-
func handleTest(w dns.ResponseWriter, r *dns.Msg) {
34+
func handleQuery(w dns.ResponseWriter, r *dns.Msg) {
3335
logger := logging.GetLogger()
3436
m := new(dns.Msg)
35-
m.SetReply(r)
3637

37-
queryStr := fmt.Sprintf(
38-
"%s %s",
39-
dns.Type(r.Question[0].Qtype).String(),
40-
r.Question[0].Name,
41-
)
38+
switch r.Question[0].Qtype {
39+
default:
40+
// Return a SERVFAIL response for unsupported record types
41+
m.SetRcode(r, dns.RcodeServerFailure)
42+
case dns.TypeA, dns.TypeNS:
43+
records := indexer.GetIndexer().LookupRecords(r.Question[0].Name, dns.Type(r.Question[0].Qtype).String())
44+
if len(records) == 0 {
45+
// Send NXDOMAIN
46+
m.SetRcode(r, dns.RcodeNameError)
47+
} else {
48+
// Send response
49+
m.SetReply(r)
50+
for _, record := range records {
51+
switch r.Question[0].Qtype {
52+
case dns.TypeA:
53+
ipAddr := net.ParseIP(record.Value)
54+
a := &dns.A{
55+
Hdr: dns.RR_Header{Name: record.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 999},
56+
A: ipAddr,
57+
}
58+
m.Answer = append(m.Answer, a)
59+
case dns.TypeNS:
60+
ns := &dns.NS{
61+
Hdr: dns.RR_Header{Name: record.Name, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 999},
62+
Ns: record.Value,
63+
}
64+
m.Answer = append(m.Answer, ns)
65+
default:
4266

43-
logger.Infof("request: %s", queryStr)
44-
45-
t := &dns.TXT{
46-
Hdr: dns.RR_Header{Name: "test.zone.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0},
47-
Txt: []string{queryStr},
67+
}
68+
}
69+
}
4870
}
4971

50-
m.Answer = append(m.Answer, t)
5172
if err := w.WriteMsg(m); err != nil {
5273
logger.Errorf("failed to write response: %s", err)
5374
}

internal/indexer/indexer.go

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,28 @@ import (
1414
input_chainsync "github.com/blinklabs-io/snek/input/chainsync"
1515
output_embedded "github.com/blinklabs-io/snek/output/embedded"
1616
"github.com/blinklabs-io/snek/pipeline"
17+
"github.com/miekg/dns"
1718
)
1819

20+
type Domain struct {
21+
name string
22+
records map[string]map[string][]DomainRecord
23+
}
24+
25+
type DomainRecord struct {
26+
Name string
27+
Value string
28+
}
29+
1930
type Indexer struct {
2031
pipeline *pipeline.Pipeline
32+
domains map[string]Domain
2133
}
2234

2335
// Singleton indexer instance
24-
var globalIndexer = &Indexer{}
36+
var globalIndexer = &Indexer{
37+
domains: make(map[string]Domain),
38+
}
2539

2640
func (i *Indexer) Start() error {
2741
cfg := config.GetConfig()
@@ -105,20 +119,63 @@ func (i *Indexer) handleEvent(evt event.Event) error {
105119
return err
106120
}
107121
datumFields := datum.Value().(cbor.Constructor).Fields()
108-
domainName := string(datumFields[0].(cbor.ByteString).Bytes())
109-
nsRecords := []string{}
122+
domainName := string(datumFields[0].(cbor.ByteString).Bytes()) + `.`
110123
for _, record := range datumFields[1].([]any) {
111-
nsRecords = append(
112-
nsRecords,
113-
string(record.(cbor.ByteString).Bytes()),
114-
)
124+
nameServer := string(record.(cbor.ByteString).Bytes()) + `.`
125+
// Create NS record for domain
126+
i.addRecord(domainName, domainName, "NS", nameServer)
127+
// Create A record for name server
128+
// We use a dummy IP address for now, since the on-chain data doesn't contain the IP yet
129+
i.addRecord(domainName, nameServer, "A", "1.2.3.4")
130+
}
131+
logger.Infof("found updated registration for domain: %s", domainName)
132+
}
133+
}
134+
return nil
135+
}
136+
137+
func (i *Indexer) LookupRecords(name string, recordType string) []DomainRecord {
138+
for domainName, domain := range i.domains {
139+
if dns.IsSubDomain(domainName, name) {
140+
if records, ok := domain.records[name]; ok {
141+
if record, ok := records[recordType]; ok {
142+
return record
143+
} else {
144+
return nil
145+
}
146+
} else {
147+
return nil
115148
}
116-
logger.Infof("found domain %s with NS records: %v", domainName, nsRecords)
117149
}
118150
}
119151
return nil
120152
}
121153

154+
func (i *Indexer) addRecord(domainName string, recordName string, recordType string, value string) {
155+
// Create initial domain record
156+
if _, ok := i.domains[domainName]; !ok {
157+
i.domains[domainName] = Domain{
158+
name: domainName,
159+
records: make(map[string]map[string][]DomainRecord),
160+
}
161+
}
162+
// Create initial list for record type
163+
if _, ok := i.domains[domainName].records[recordName]; !ok {
164+
i.domains[domainName].records[recordName] = make(map[string][]DomainRecord)
165+
if _, ok := i.domains[domainName].records[recordName][recordType]; !ok {
166+
i.domains[domainName].records[recordName][recordType] = make([]DomainRecord, 0)
167+
}
168+
}
169+
// Create record
170+
i.domains[domainName].records[recordName][recordType] = append(
171+
i.domains[domainName].records[recordName][recordType],
172+
DomainRecord{
173+
Name: recordName,
174+
Value: value,
175+
},
176+
)
177+
}
178+
122179
// GetIndexer returns the global indexer instance
123180
func GetIndexer() *Indexer {
124181
return globalIndexer

0 commit comments

Comments
 (0)