dnsseed: serve results

This commit is contained in:
George Tankersley 2020-05-21 18:41:08 -04:00
parent 289e839360
commit a01f5196b7
4 changed files with 36 additions and 24 deletions

View File

@ -2,4 +2,22 @@
This is a CoreDNS plugin that scrapes addresses of peers from a Zcash network. It's intended as a safer and more scalable replacement for the [zcash-seeder](https://github.com/zcash/zcash-seeder) project. This is a CoreDNS plugin that scrapes addresses of peers from a Zcash network. It's intended as a safer and more scalable replacement for the [zcash-seeder](https://github.com/zcash/zcash-seeder) project.
It uses [btcsuite](https://github.com/btcsuite) for networking and [crawshaw/sqlite](https://crawshaw.io/blog/go-and-sqlite) for storing peer data. It's written in Go and uses [btcsuite](https://github.com/btcsuite) for low-level networking.
### Build instructions
TODO
### CoreDNS configuration
A sample Corefile that configures `mainnet.seeder.yolo.money` and `testnet.seeder.yolo.money` using two local Zcash nodes:
```
mainnet.seeder.yolo.money {
dnsseed yolo.money mainnet 127.0.0.1:8233
}
testnet.seeder.yolo.money {
dnsseed yolo.money testnet 127.0.0.1:18233
}
```

View File

@ -39,32 +39,22 @@ func (zs ZcashSeeder) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns
a := new(dns.Msg) a := new(dns.Msg)
a.SetReply(r) a.SetReply(r)
a.Authoritative = true a.Authoritative = true
a.Answer = make([]dns.RR, 0, 25)
a.Extra = make([]dns.RR, 0, len(peerIPs))
for i := 0; i < len(peerIPs); i++ { for i := 0; i < len(peerIPs); i++ {
var rr dns.RR var rr dns.RR
ip := peerIPs[i] if peerIPs[i].To4() == nil {
rr = new(dns.AAAA)
switch state.QType() { rr.(*dns.AAAA).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Ttl: 3600, Class: state.QClass()}
case dns.TypeA: rr.(*dns.AAAA).AAAA = peerIPs[i]
} else {
rr = new(dns.A) rr = new(dns.A)
rr.(*dns.A).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Class: state.QClass()} rr.(*dns.A).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Ttl: 3600, Class: state.QClass()}
rr.(*dns.A).A = ip.To4() rr.(*dns.A).A = peerIPs[i]
case dns.TypeAAAA:
if ip.To4() != nil {
rr = new(dns.AAAA)
rr.(*dns.AAAA).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: state.QClass()}
rr.(*dns.AAAA).AAAA = ip
}
default:
return dns.RcodeNotImplemented, nil
} }
// TODO: why don't we offer SRV records? Zcash has a configurable port. a.Answer = append(a.Answer, rr)
a.Extra = append(a.Extra, rr)
} }
w.WriteMsg(a) w.WriteMsg(a)

View File

@ -1,6 +1,7 @@
package dnsseed package dnsseed
import ( import (
"fmt"
"net" "net"
"time" "time"
@ -23,11 +24,11 @@ func init() { plugin.Register("dnsseed", setup) }
// setup is the function that gets called when the config parser see the token "dnsseed". Setup is responsible // setup is the function that gets called when the config parser see the token "dnsseed". Setup is responsible
// for parsing any extra options the example plugin may have. The first token this function sees is "dnsseed". // for parsing any extra options the example plugin may have. The first token this function sees is "dnsseed".
func setup(c *caddy.Controller) error { func setup(c *caddy.Controller) error {
var zoneArg, networkArg, hostArg string var rootArg, networkArg, hostArg string
c.Next() // Ignore "dnsseed" and give us the next token. c.Next() // Ignore "dnsseed" and give us the next token.
if !c.Args(&zoneArg, &networkArg, &hostArg) { if !c.Args(&rootArg, &networkArg, &hostArg) {
return plugin.Error("dnsseed", c.ArgErr()) return plugin.Error("dnsseed", c.ArgErr())
} }
@ -41,6 +42,9 @@ func setup(c *caddy.Controller) error {
return plugin.Error("dnsseed", c.Errf("Config error: expected {mainnet, testnet}, got %s", networkArg)) return plugin.Error("dnsseed", c.Errf("Config error: expected {mainnet, testnet}, got %s", networkArg))
} }
// Automatically configure the responsive zone by network
zone := fmt.Sprintf("%s.seeder.%s.", networkArg, rootArg)
address, port, err := net.SplitHostPort(hostArg) address, port, err := net.SplitHostPort(hostArg)
if err != nil { if err != nil {
return plugin.Error("dnsseed", c.Errf("Config error: expected 'host:port', got %s", hostArg)) return plugin.Error("dnsseed", c.Errf("Config error: expected 'host:port', got %s", hostArg))
@ -81,7 +85,7 @@ func setup(c *caddy.Controller) error {
dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
return ZcashSeeder{ return ZcashSeeder{
Next: next, Next: next,
Zones: []string{zoneArg}, Zones: []string{zone},
seeder: seeder, seeder: seeder,
} }
}) })

View File

@ -9,7 +9,7 @@ import (
// TestSetup tests the various things that should be parsed by setup. // TestSetup tests the various things that should be parsed by setup.
func TestSetup(t *testing.T) { func TestSetup(t *testing.T) {
c := caddy.NewTestController("dns", "dnsseed mainnet.seeder.yolo.money mainnet 127.0.0.1:8233") c := caddy.NewTestController("dns", "dnsseed yolo.money mainnet 127.0.0.1:8233")
if err := setup(c); err != nil { if err := setup(c); err != nil {
if strings.Contains(err.Error(), "connection refused") { if strings.Contains(err.Error(), "connection refused") {
// No local peer running // No local peer running