remove from here, own repo github/miekg/fks
This commit is contained in:
parent
784e99184e
commit
39d8d37d96
|
@ -1,75 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"dns"
|
||||
"fmt"
|
||||
"github.com/miekg/radix"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Cache elements, we using to key (toRadixKey) to distinguish between dns and dnssec
|
||||
type Packet struct {
|
||||
ttl time.Time // insertion time
|
||||
d []byte // raw packet, except the first two bytes
|
||||
}
|
||||
|
||||
func toRadixKey(d *dns.Msg) string {
|
||||
s := fmt.Sprintf("%s,%d,%d", strings.ToLower(d.Question[0].Name), d.Question[0].Qtype, d.Question[0].Qclass)
|
||||
for _, r := range d.Extra {
|
||||
if r.Header().Rrtype == dns.TypeOPT {
|
||||
if r.(*dns.RR_OPT).Do() {
|
||||
return s + "D"
|
||||
}
|
||||
}
|
||||
}
|
||||
return s + "P" // plain
|
||||
}
|
||||
|
||||
type Cache struct {
|
||||
*radix.Radix
|
||||
}
|
||||
|
||||
func NewCache() *Cache {
|
||||
return &Cache{Radix: radix.New()}
|
||||
}
|
||||
|
||||
func (c *Cache) Evict() {
|
||||
// A bit tedious, keys() -> find() -> remove()
|
||||
for _, key := range c.Radix.Keys() {
|
||||
node := c.Radix.Find(key)
|
||||
if node == nil || node.Value == nil {
|
||||
continue
|
||||
}
|
||||
if t := time.Since(node.Value.(*Packet).ttl).Seconds(); t > float64(*flagttl) {
|
||||
c.Radix.Remove(key)
|
||||
if *flaglog {
|
||||
log.Printf("fks-shield: evicting %s after %f\n", key, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) Find(d *dns.Msg) []byte {
|
||||
p := c.Radix.Find(toRadixKey(d))
|
||||
if p == nil {
|
||||
if *flaglog {
|
||||
log.Printf("fsk-shield: cache miss for " + toRadixKey(d))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return p.Value.(*Packet).d
|
||||
}
|
||||
|
||||
func (c *Cache) Insert(d *dns.Msg) {
|
||||
if *flaglog {
|
||||
log.Printf("fsk-shield: inserting " + toRadixKey(d))
|
||||
}
|
||||
buf, _ := d.Pack() // Should always work
|
||||
c.Radix.Insert(toRadixKey(d), &Packet{d: buf[2:], ttl: time.Now().UTC()})
|
||||
}
|
||||
|
||||
func (c *Cache) Remove(d *dns.Msg) {
|
||||
c.Radix.Remove(toRadixKey(d))
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
package main
|
||||
|
||||
// TODO: locking, tsig (need key list to rewrap the queries)
|
||||
|
||||
import (
|
||||
"dns"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
listen = flag.String("listen", ":8053", "set the listener address")
|
||||
server = flag.String("server", ":53", "remote server address")
|
||||
flagttl = flag.Int("ttl", 30, "ttl (in seconds) for cached packets")
|
||||
flaglog = flag.Bool("log", false, "be more verbose")
|
||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
|
||||
)
|
||||
|
||||
func serve(w dns.ResponseWriter, r *dns.Msg, c *Cache) {
|
||||
switch {
|
||||
case r.IsNotify():
|
||||
if *flaglog {
|
||||
log.Printf("fks-shield: notify/update")
|
||||
}
|
||||
fallthrough
|
||||
case r.IsUpdate():
|
||||
client := new(dns.Client)
|
||||
if p, e := client.Exchange(r, *server); e == nil {
|
||||
w.Write(p)
|
||||
}
|
||||
return
|
||||
}
|
||||
if p := c.Find(r); p != nil {
|
||||
b := []byte{0, 0}
|
||||
dns.RawSetId(b, r.MsgHdr.Id)
|
||||
p = append(b, p...)
|
||||
w.WriteBuf(p)
|
||||
return
|
||||
}
|
||||
// Cache miss
|
||||
client := new(dns.Client)
|
||||
if p, e := client.Exchange(r, *server); e == nil {
|
||||
// TODO(mg): If r has edns0 and p has not we create a mismatch here
|
||||
w.Write(p)
|
||||
c.Insert(p)
|
||||
return
|
||||
} else {
|
||||
log.Printf("fks-shield: failed to get answer " + e.Error())
|
||||
m := new(dns.Msg)
|
||||
m.SetRcode(r, dns.RcodeServerFailure)
|
||||
w.Write(m)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
flag.Parse()
|
||||
if *cpuprofile != "" {
|
||||
f, err := os.Create(*cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
cache := NewCache()
|
||||
dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) { serve(w, r, cache) })
|
||||
|
||||
// Only listen on UDP
|
||||
go func() {
|
||||
if err := dns.ListenAndServe(*listen, "udp", nil); err != nil {
|
||||
log.Fatalf("fks-shield: failed to setup %s %s", *listen, "udp")
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
// Every 10 sec run the cache cleaner
|
||||
time.Sleep(10 * 1e9)
|
||||
cache.Evict()
|
||||
}
|
||||
}()
|
||||
|
||||
sig := make(chan os.Signal)
|
||||
signal.Notify(sig, os.Interrupt)
|
||||
|
||||
forever:
|
||||
for {
|
||||
select {
|
||||
case <-sig:
|
||||
log.Printf("fks-shield: signal received, stopping")
|
||||
break forever
|
||||
}
|
||||
}
|
||||
}
|
11
ex/fksd/TODO
11
ex/fksd/TODO
|
@ -1,11 +0,0 @@
|
|||
* wildcard
|
||||
* locking r/w or copy-on-write in radix
|
||||
* check message length
|
||||
* ds handling in serve()
|
||||
* tsig
|
||||
* dynamic updates
|
||||
* zone transfers
|
||||
* incremental zone transfers
|
||||
* configuration
|
||||
* journal
|
||||
* ...
|
|
@ -1,5 +0,0 @@
|
|||
server 127.0.0.1 1053
|
||||
zone ZONE.
|
||||
update add USER. 60 IN TXT "ADD miekg bWlla2c="
|
||||
key root c3R1cGlk
|
||||
send
|
|
@ -1,5 +0,0 @@
|
|||
server 127.0.0.1 1053
|
||||
zone ZONE.
|
||||
update add ZONE. 60 IN TXT "READ miek.nl /home/miekg/g/src/dns/ex/fksd/z/miek.nl.db"
|
||||
key root c3R1cGlk
|
||||
send
|
|
@ -1,5 +0,0 @@
|
|||
server 127.0.0.1 1053
|
||||
zone ZONE.
|
||||
update add ZONE. 60 IN TXT "READXFR miek.nl 213.154.224.17:53"
|
||||
key root c3R1cGlk
|
||||
send
|
|
@ -1,42 +0,0 @@
|
|||
Zone configuration commands:
|
||||
|
||||
We have defined the following groups:
|
||||
|
||||
* `ZONE`: for zone configuration
|
||||
* `USER`: for user management
|
||||
* `ERROR`: for error reporting
|
||||
* `SYSTEM`: for system management?
|
||||
* `...`: ...
|
||||
|
||||
Better stuff then add and set
|
||||
|
||||
# ZONE
|
||||
|
||||
In zone we have:
|
||||
|
||||
(This will probably all change and use more consistent names)
|
||||
|
||||
ZONE. TXT "READ origin /path/to/zone"
|
||||
ZONE. TXT "READXFR origin ip(6)-of-master [tsig-secret]"
|
||||
ZONE. TXT "DROP origin"
|
||||
ZONE. TXT "list"
|
||||
|
||||
Zones are listed in the additional section of the reply packet
|
||||
|
||||
ZONE. TXT "zonename1"
|
||||
ZONE. TXT "zonename2"
|
||||
|
||||
# USER
|
||||
|
||||
USER. TXT "ADD miekg"
|
||||
USER. TXT "DROP miekg"
|
||||
USER. TXT "ADDTSIG miekg base64-tsig-secret"
|
||||
USER. TXT "ADDPOWER miekg list" // list/write/drop
|
||||
USER. TXT "DROPPOWER miekg list"
|
||||
|
||||
|
||||
The config is internally stored in some memory structure.
|
||||
|
||||
|
||||
.FKS
|
||||
ZONE.FKS. USER.FKS.
|
|
@ -1,5 +0,0 @@
|
|||
server 127.0.0.1 1053
|
||||
zone ZONE.
|
||||
update add ZONE. 60 IN TXT "DROP miek.nl"
|
||||
key root c3R1cGlk
|
||||
send
|
|
@ -1,5 +0,0 @@
|
|||
server 127.0.0.1 1053
|
||||
zone ZONE.
|
||||
update add USER. 60 IN TXT "LIST"
|
||||
key root c3R1cGlk
|
||||
send
|
|
@ -1,5 +0,0 @@
|
|||
server 127.0.0.1 1053
|
||||
zone ZONE.
|
||||
update add ZONE. 60 IN TXT "LIST"
|
||||
key root c3R1cGlk
|
||||
send
|
|
@ -1,5 +0,0 @@
|
|||
server 127.0.0.1 1053
|
||||
zone ZONE.
|
||||
update add ZONE. 60 IN TXT "LIST"
|
||||
key miekg bWlla2c=
|
||||
send
|
|
@ -1,203 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"dns"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
R_NONE = 0 // Right to do nada
|
||||
R_LIST = 1 // Right to list stuff
|
||||
R_WRITE = 2 // Right to write stuff
|
||||
R_DROP = 4 // Right to drop stuff
|
||||
R_USER = 8 // Right to add users
|
||||
)
|
||||
|
||||
// fks config
|
||||
type Config struct {
|
||||
Server *dns.Server // Server instance for this configuration
|
||||
Zones map[string]*dns.Zone // All zones we are authoritative for
|
||||
Rights map[string]int // Rights for all users
|
||||
}
|
||||
|
||||
func NewConfig() *Config {
|
||||
c := new(Config)
|
||||
c.Zones = make(map[string]*dns.Zone)
|
||||
c.Rights = make(map[string]int)
|
||||
return c
|
||||
}
|
||||
|
||||
func formerr(w dns.ResponseWriter, req *dns.Msg) {
|
||||
m := new(dns.Msg)
|
||||
m.MsgHdr.Opcode = dns.OpcodeUpdate
|
||||
if req.IsTsig() {
|
||||
m.SetTsig(userFromTsig(req), dns.HmacMD5, 300, time.Now().Unix())
|
||||
}
|
||||
w.Write(m.SetRcode(req, dns.RcodeFormatError))
|
||||
}
|
||||
|
||||
func noerr(w dns.ResponseWriter, req *dns.Msg) {
|
||||
m := new(dns.Msg)
|
||||
m.MsgHdr.Opcode = dns.OpcodeUpdate
|
||||
m.SetTsig(userFromTsig(req), dns.HmacMD5, 300, time.Now().Unix())
|
||||
w.Write(m.SetReply(req))
|
||||
}
|
||||
|
||||
func userFromTsig(req *dns.Msg) string {
|
||||
return req.Extra[len(req.Extra)-1].Header().Name
|
||||
}
|
||||
|
||||
// Check if the user has any rights
|
||||
func configRights(user string, c *Config) {
|
||||
|
||||
}
|
||||
|
||||
// config stuff in Auth section (just as dynamic updates (*hint* *hint*)
|
||||
// SUBSYSTEM. IN TXT "OPERATION<SPACE>OPTIONS..."
|
||||
// ZONE. IN TXT "READ origin /z/bloep" - absolute path in fs
|
||||
func config(w dns.ResponseWriter, req *dns.Msg, c *Config) {
|
||||
logPrintf("config command")
|
||||
|
||||
if !req.IsTsig() {
|
||||
logPrintf("non config command (no tsig)")
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
if !req.IsUpdate() {
|
||||
logPrintf("non config command (no update)")
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
if e := w.TsigStatus(); e != nil {
|
||||
logPrintf("non config command (tsig fail): %s", e.Error())
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
// No need to check the user, if the tsig checks out, the user exists
|
||||
logPrintf("config command ok")
|
||||
|
||||
for _, rr := range req.Ns {
|
||||
t, ok := rr.(*dns.RR_TXT)
|
||||
|
||||
if !ok {
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
switch strings.ToUpper(t.Header().Name) {
|
||||
case "ZONE.":
|
||||
if e := configZONE(w, req, t, c); e != nil {
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
case "USER.":
|
||||
if userFromTsig(req) != dns.Fqdn(*superuser) {
|
||||
logPrintf("user management is only for the superuser\n")
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
if e := configUSER(w, req, t, c); e != nil {
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
default:
|
||||
formerr(w, req)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with the zone options
|
||||
func configZONE(w dns.ResponseWriter, req *dns.Msg, t *dns.RR_TXT, c *Config) error {
|
||||
sx := strings.Split(t.Txt[0], " ")
|
||||
if len(sx) == 0 {
|
||||
return nil
|
||||
}
|
||||
switch strings.ToUpper(sx[0]) {
|
||||
case "READ":
|
||||
if len(sx) != 3 {
|
||||
return nil
|
||||
}
|
||||
logPrintf("config READ %s %s\n", dns.Fqdn(sx[1]), sx[2])
|
||||
if e := c.ReadZoneFile(dns.Fqdn(sx[1]), sx[2]); e != nil {
|
||||
logPrintf("failed to read %s: %s\n", sx[2], e.Error())
|
||||
return e
|
||||
}
|
||||
logPrintf("config added: READ %s %s\n", dns.Fqdn(sx[1]), sx[2])
|
||||
noerr(w, req)
|
||||
case "READXFR":
|
||||
if len(sx) != 3 {
|
||||
return nil
|
||||
}
|
||||
logPrintf("config READXFR %s %s\n", dns.Fqdn(sx[1]), sx[2])
|
||||
if e := c.ReadZoneXfr(dns.Fqdn(sx[1]), sx[2]); e != nil {
|
||||
logPrintf("failed to axfr %s: %s\n", sx[2], e.Error())
|
||||
return e
|
||||
}
|
||||
logPrintf("config added: READXFR %s %s\n", dns.Fqdn(sx[1]), sx[2])
|
||||
noerr(w, req)
|
||||
case "DROP":
|
||||
if len(sx) != 2 {
|
||||
return nil
|
||||
}
|
||||
logPrintf("config DROP %s\n", dns.Fqdn(sx[1]))
|
||||
if e := c.DropZone(dns.Fqdn(sx[1])); e != nil {
|
||||
logPrintf("Failed to drop %s: %s\n", dns.Fqdn(sx[1]), e.Error())
|
||||
return e
|
||||
}
|
||||
logPrintf("config dropped: DROP %s\n", dns.Fqdn(sx[1]))
|
||||
noerr(w, req)
|
||||
case "LIST":
|
||||
logPrintf("config LIST\n")
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(req)
|
||||
// Add the zones to the additional section
|
||||
for zone, _ := range c.Zones {
|
||||
a, _ := dns.NewRR("ZONE. TXT \"" + zone + "\"")
|
||||
m.Extra = append(m.Extra, a)
|
||||
}
|
||||
m.SetTsig(userFromTsig(req), dns.HmacMD5, 300, time.Now().Unix())
|
||||
w.Write(m)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deal with the user options
|
||||
func configUSER(w dns.ResponseWriter, req *dns.Msg, t *dns.RR_TXT, c *Config) error {
|
||||
sx := strings.Split(t.Txt[0], " ")
|
||||
if len(sx) == 0 {
|
||||
return nil
|
||||
}
|
||||
switch strings.ToUpper(sx[0]) {
|
||||
case "ADD":
|
||||
if len(sx) != 3 {
|
||||
return nil
|
||||
}
|
||||
logPrintf("config ADD %s with %s\n", dns.Fqdn(sx[1]), sx[2])
|
||||
c.Server.TsigSecret[dns.Fqdn(sx[1])] = sx[2]
|
||||
c.Rights[dns.Fqdn(sx[1])] = R_NONE
|
||||
noerr(w, req)
|
||||
case "DROP":
|
||||
if len(sx) != 2 {
|
||||
return nil
|
||||
}
|
||||
logPrintf("config DROP %s\n", dns.Fqdn(sx[1]))
|
||||
delete(c.Server.TsigSecret, dns.Fqdn(sx[1]))
|
||||
delete(c.Rights, dns.Fqdn(sx[1]))
|
||||
noerr(w, req)
|
||||
case "LIST":
|
||||
for u, p := range c.Server.TsigSecret {
|
||||
logPrintf("config USER %s: %s\n", u, p)
|
||||
}
|
||||
fallthrough
|
||||
case "ADDPOWER":
|
||||
fallthrough
|
||||
case "DROPPOWER":
|
||||
noerr(w, req)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package main
|
||||
|
||||
import "log"
|
||||
|
||||
const NAME = "fksd: "
|
||||
|
||||
func logPrintf(format string, a ...interface{}) {
|
||||
if *flaglog {
|
||||
log.Printf(NAME + format, a...)
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"dns"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
flaglog = flag.Bool("log", false, "log incoming queries")
|
||||
superuser = flag.String("user", "root", "username to use for the superuser")
|
||||
superkey = flag.String("key", "c3R1cGlk", "base64 tsig key for superuser authentication")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
*superuser = strings.ToLower(*superuser)
|
||||
conf := NewConfig()
|
||||
conf.Rights[*superuser] = R_LIST | R_WRITE | R_DROP | R_USER // *all* of them
|
||||
|
||||
go func() {
|
||||
err := dns.ListenAndServe(":1053", "udp", nil)
|
||||
if err != nil {
|
||||
log.Fatal("fksd: could not start server listener: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
conf.Server = &dns.Server{Addr: ":1053", Net: "tcp", TsigSecret: map[string]string{dns.Fqdn(*superuser): *superkey}}
|
||||
err := conf.Server.ListenAndServe()
|
||||
if err != nil {
|
||||
log.Fatal("fksd: could not start config listener: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
// Yes, we HIJACK zone. ... not sure on how to make this "private"
|
||||
dns.HandleFunc("ZONE.", func(w dns.ResponseWriter, req *dns.Msg) { config(w, req, conf) })
|
||||
// Gasp!! And USER.
|
||||
dns.HandleFunc("USER.", func(w dns.ResponseWriter, req *dns.Msg) { config(w, req, conf) })
|
||||
|
||||
sig := make(chan os.Signal)
|
||||
signal.Notify(sig, os.Interrupt)
|
||||
forever:
|
||||
for {
|
||||
select {
|
||||
case <-sig:
|
||||
logPrintf("signal received, stopping")
|
||||
break forever
|
||||
}
|
||||
}
|
||||
}
|
119
ex/fksd/serve.go
119
ex/fksd/serve.go
|
@ -1,119 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"dns"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Create skeleton edns opt RR from the query and
|
||||
// add it to the message m
|
||||
func ednsFromRequest(req, m *dns.Msg) {
|
||||
for _, r := range req.Extra {
|
||||
if r.Header().Rrtype == dns.TypeOPT {
|
||||
m.SetEdns0(4096, r.(*dns.RR_OPT).Do())
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func serve(w dns.ResponseWriter, req *dns.Msg, z *dns.Zone) {
|
||||
if z == nil {
|
||||
panic("fksd: no zone")
|
||||
}
|
||||
logPrintf("[zone %s] incoming %s %s %d from %s\n", z.Origin, req.Question[0].Name, dns.Rr_str[req.Question[0].Qtype], req.MsgHdr.Id, w.RemoteAddr())
|
||||
// if we find something with NonAuth = true, it means we need to return referral
|
||||
nss := z.Predecessor(req.Question[0].Name)
|
||||
m := new(dns.Msg)
|
||||
if nss != nil && nss.NonAuth {
|
||||
m.SetReply(req)
|
||||
m.Ns = nss.RR[dns.TypeNS]
|
||||
for _, n := range m.Ns {
|
||||
if dns.IsSubDomain(n.(*dns.RR_NS).Ns, n.Header().Name) {
|
||||
// Need glue
|
||||
glue := z.Find(n.(*dns.RR_NS).Ns)
|
||||
if glue != nil {
|
||||
if a4, ok := glue.RR[dns.TypeAAAA]; ok {
|
||||
m.Extra = append(m.Extra, a4...)
|
||||
}
|
||||
if a, ok := glue.RR[dns.TypeA]; ok {
|
||||
m.Extra = append(m.Extra, a...)
|
||||
}
|
||||
// length
|
||||
}
|
||||
}
|
||||
}
|
||||
ednsFromRequest(req, m)
|
||||
w.Write(m)
|
||||
return
|
||||
}
|
||||
|
||||
// If we don't have the name return NXDOMAIN
|
||||
node := z.Find(req.Question[0].Name)
|
||||
if node == nil {
|
||||
if z.Wildcard > 0 {
|
||||
lx := dns.SplitLabels(req.Question[0].Name)
|
||||
wc := "*." + strings.Join(lx[1:], ".")
|
||||
node = z.Find(wc)
|
||||
if node != nil {
|
||||
goto Wildcard
|
||||
}
|
||||
}
|
||||
m.SetRcode(req, dns.RcodeNameError)
|
||||
ednsFromRequest(req, m)
|
||||
w.Write(m)
|
||||
return
|
||||
}
|
||||
|
||||
Wildcard:
|
||||
|
||||
// We have the name it isn't a referral, but it may that
|
||||
// we still have NSs for this name. If we have nss and they
|
||||
// are NonAuth true return those.
|
||||
if nss, ok := node.RR[dns.TypeNS]; ok && node.NonAuth {
|
||||
m.SetReply(req)
|
||||
m.Ns = nss
|
||||
for _, n := range m.Ns {
|
||||
if dns.IsSubDomain(n.(*dns.RR_NS).Ns, n.Header().Name) {
|
||||
// Need glue
|
||||
glue := z.Find(n.(*dns.RR_NS).Ns)
|
||||
if glue != nil {
|
||||
if a4, ok := glue.RR[dns.TypeAAAA]; ok {
|
||||
m.Extra = append(m.Extra, a4...)
|
||||
}
|
||||
if a, ok := glue.RR[dns.TypeA]; ok {
|
||||
m.Extra = append(m.Extra, a...)
|
||||
}
|
||||
// length
|
||||
}
|
||||
}
|
||||
}
|
||||
ednsFromRequest(req, m)
|
||||
w.Write(m)
|
||||
return
|
||||
}
|
||||
|
||||
apex := z.Find(z.Origin)
|
||||
|
||||
if rrs, ok := node.RR[req.Question[0].Qtype]; ok {
|
||||
m.SetReply(req)
|
||||
m.MsgHdr.Authoritative = true
|
||||
m.Answer = rrs
|
||||
m.Ns = apex.RR[dns.TypeNS]
|
||||
ednsFromRequest(req, m)
|
||||
w.Write(m)
|
||||
return
|
||||
} else { // NoData reply or CNAME
|
||||
m.SetReply(req)
|
||||
if cname, ok := node.RR[dns.TypeCNAME]; ok {
|
||||
m.Answer = cname // tODO
|
||||
}
|
||||
m.Ns = apex.RR[dns.TypeSOA]
|
||||
ednsFromRequest(req, m)
|
||||
w.Write(m)
|
||||
return
|
||||
}
|
||||
m.SetRcode(req, dns.RcodeNameError)
|
||||
ednsFromRequest(req, m)
|
||||
w.Write(m)
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
; <<>> DiG 9.8.1-P1 <<>> axfr miek.nl @elektron.atoom.net
|
||||
;; global options: +cmd
|
||||
miek.nl. 345600 IN SOA elektron.atoom.net. ghostbuster.atoom.net. 1343873581 14400 3600 604800 86400
|
||||
miek.nl. 345600 IN RRSIG SOA 8 2 345600 20120901011301 20120802011301 12051 miek.nl. Sh1GoyMfseseRzqPdJwaNQojbIcn8nAfpGBUoq7J8Y6Jr9jKVEeivMo6 OYedeDhWDcchzLsfJxIM0j6h6dlhLqdNJu/5yLfaFeGgzJR9UcNaVLi5 CxGUwXZjDCfTlpTO8QHgo/sMiFA7Gbs7nLHg1b4V42rTOTVAqMoeZRaz AZE=
|
||||
miek.nl. 345600 IN NS ext.ns.whyscream.net.
|
||||
miek.nl. 345600 IN NS open.nlnetlabs.nl.
|
||||
miek.nl. 345600 IN NS omval.tednet.nl.
|
||||
miek.nl. 345600 IN NS elektron.atoom.net.
|
||||
miek.nl. 345600 IN RRSIG NS 8 2 345600 20120901011301 20120802011301 12051 miek.nl. KVLQGLCxIKtdAyUaz5UrukgvUOU4+V+nq0//hcbaWxs88v3Ir07tRg2S 6OYNxusLNRYuPDBu4IFm0R5uwcg26hxeCEr0U70cATG5wMjeu7o9B4Xt aQEZPTJuq8JiWOuRuyaLedBc+LjYiO9nR+vy49sJO0UawH03kzKNkaZV AjQ=
|
||||
miek.nl. 345600 IN A 85.223.71.124
|
||||
miek.nl. 345600 IN RRSIG A 8 2 345600 20120901011301 20120802011301 12051 miek.nl. k+814/HozR+qedDS8bbISBvtcMmC9iOncs9afu8YN4vTbUTWRmqJNtsm VvuR3RLlbOkDOCKemiHs3bIe203DPBDkpjc02t1VLQ2vt562cfd4Jcwn xbkMqWwISXflP2FRftPtX8vOQVQpwe1HwDGhLzeo5zEGrdGaZo5XdcsU Xxc=
|
||||
miek.nl. 345600 IN MX 20 mail.atoom.net.
|
||||
miek.nl. 345600 IN MX 40 mx-ext.tjeb.nl.
|
||||
miek.nl. 345600 IN RRSIG MX 8 2 345600 20120901011301 20120802011301 12051 miek.nl. mTKDp/VLkjVrNv0I5GYmy6N/NsX8wQEnE10euDoXp1qzVgprz2CqYI1F jVxhdpH4bnjOjXla2bDlis16uEOb/a4SipVYrA8IbOk4pFi4THKodOS6 9XR4/9mGGpZuvTxqurTNjzNfnz/dhny8ML7VeFX4wVILT1gFN7yS3JV1 Q2U=
|
||||
miek.nl. 345600 IN TXT "$pup: e66a339 2011-02-24 12:50:03 +0100 Miek Gieben$"
|
||||
miek.nl. 345600 IN RRSIG TXT 8 2 345600 20120901011301 20120802011301 12051 miek.nl. TnGt+voabTe1XZuV+llYwx+Y4roIueBzY9i0x1RL+84AvVd3mu8dYKKM VYOY0y2tjKCBeugD2Xu8g0FbmgKDUR3kEeWNfijTtsPuzpRDuZSV+20i S1Zy77NvQRRMp+aHRtrmMni8eIsDEGBwYMWS2U2Gk5o+fCuiDJ7GGssp +vA=
|
||||
miek.nl. 345600 IN AAAA 2001:7b8:32a::2
|
||||
miek.nl. 345600 IN RRSIG AAAA 8 2 345600 20120901011301 20120802011301 12051 miek.nl. ViYKNCIPvCcufFZhq5aMi4vlg0mMF5hPcHGLcpBZYziXk4525QczauGv cd3nBMw4Ge21uALNqYf6n7tEY6EdcFMRSz7x/RpBY/cm23XP1VQrfvn3 vFB326kwkXAJN5BOJzGtwLv44S1djMbPOBZQotrmL4u1FuP2FV+AyRmD ZiI=
|
||||
miek.nl. 86400 IN NSEC miek._pka.miek.nl. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY
|
||||
miek.nl. 86400 IN RRSIG NSEC 8 2 86400 20120901011301 20120802011301 12051 miek.nl. XK+KWyjSiCMiufeSit2QWDkEGd+xAz1rHDQSM4PP0iDZe6QWrmxdFCap CV16qdugR75+puZw5L0YZeT+aPiNN7kBRcEDJuivIED0GThEJtfdrKrF AB/377+gqBZNFm7gPBsKSx4WuX3y8xPZSznX8liR/raDE6e81TB25EjL NF8=
|
||||
miek.nl. 345600 IN DNSKEY 256 3 8 AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2 836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4b AmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0Pi wgoXVesz
|
||||
miek.nl. 345600 IN DNSKEY 257 3 8 AwEAAcWdjBl4W4wh/hPxMDcBytmNCvEngIgB9Ut3C2+QI0oVz78/WK9K PoQF7B74JQ/mjO4fvIncBmPp6mFNxs9/WQX0IXf7oKviEVOXLjctR4D1 KQLX0wprvtUIsQFIGdXaO6suTT5eDbSd6tTwu5xIkGkDmQhhH8OQydoE uCwV245ZwF/8AIsqBYDNQtQ6zhd6jDC+uZJXg/9LuPOxFHbiMTjp6j3C CW0kHbfM/YHZErWWtjPj3U3Z7knQSIm5PO5FRKBEYDdr5UxWJ/1/20Sr zI3iztvPwHDsA2rdHm/4YRzq7CvG4N0t9ac/T0a0Sxba/BUX2UVPWaIV BdTRBtgHi0s=
|
||||
miek.nl. 345600 IN RRSIG DNSKEY 8 2 345600 20120901011301 20120802011301 12051 miek.nl. LTZ6r10DeNgc23f+O37B15798grkYs5gmB1U1XPFiawZ21yy1i0OxMy/ E+zCbDMP3XJVKv9yFZPGkQlsm57ZhWvJgWxumPuWl3fZsP+2Z9CAKfJs 0ogybUa220RcTv/IkEqjzeOF04bSqp1fi6Fsk+L5G2UaHdz7AZoF1lgR LV0=
|
||||
miek.nl. 345600 IN RRSIG DNSKEY 8 2 345600 20120901011301 20120802011301 33694 miek.nl. Ic83rWz0R1T+UkIDMzX6XmSZHlwDQnyVc1Fzz7aevsNJA5o24WUGWTrC UPA+lek0cXJP/yYGHJAhBk9BVkEO9xos4Aaey+wWke54V/UwB3juhLSu 2JiLwfejojyCVSug9wjoQ+VgmLrAP1peRFOHuQcQ8NmAh+Tr6CAwYn3A 7UcXrR8oMl+8KCzMA2u+ly50RzcwlTWwXoxtl+0/Ep0g3TxM0RsJ08Ff kT7U2Nt9RRMCnTH+nuIZLhjh87SiJT+gLS8lGDND01o96z6KB7y1w8rN 1Q9IH3QRIK2dtBhkI7uefVu2valoU5z7QLsu8c9So4+/Z+rldEXhG4KT YpPyuw==
|
||||
miek._pka.miek.nl. 345600 IN TXT "v=pkal\;fpr=6A3CF4506D4E7C6BC23CF982258B85CF3880D0F6\;uri=http://www.miek.nl/miek.pub.asc"
|
||||
miek._pka.miek.nl. 345600 IN RRSIG TXT 8 4 345600 20120901011301 20120802011301 12051 miek.nl. Zj8wLmh0oiyPGqBvfGaDJN+VeFYo52SQ34Ie2VaaaYUrYlAPp4BZGLvd MAh5/5Jz2HVMd+7NIavBpNmbpXWNhvF+gMbK7+aKu9AD0JqdjSxmqNqY WnpCVsI22628qzxlbfs002YbJvf9tmeUyJB7jqy7zAMauuvXOPaL17pH b3k=
|
||||
miek._pka.miek.nl. 86400 IN NSEC a.miek.nl. TXT RRSIG NSEC
|
||||
miek._pka.miek.nl. 86400 IN RRSIG NSEC 8 4 86400 20120901011301 20120802011301 12051 miek.nl. KvNt7u5pSlvLMtdqW/PnbZhNNZkmkxSII5Ig/JvgpVufwl3Bq8PwYqHd 9xEmIsFlVq8nGQ1+xnAmbolI3jVGObdFwNZ9lq0jPckXttjWomSHz7o2 updjXEa1oqThGnFWXhYBc/3wbhTxx4mRY3Hgnwr3QitYKPuCcajzTe2j qFk=
|
||||
a.miek.nl. 345600 IN A 85.223.71.124
|
||||
a.miek.nl. 345600 IN RRSIG A 8 3 345600 20120901011301 20120802011301 12051 miek.nl. dLfhQJ8E5UzZrhruEFmAMzcqnVbANgmM8LJ4+Td9N8nSMkISdX6w5PEL P4z4XfIwiHnqLqck5N2AIPXNs9nQPtzwyftI3sqwnmNG+r6OA1QnykEA KRSzUdoNlkiOcLHO92hoh56BrBWZ44/eAKbZN/33KTmTPFoyftxpm1u1 FCs=
|
||||
a.miek.nl. 345600 IN AAAA 2001:7b8:32a::2
|
||||
a.miek.nl. 345600 IN RRSIG AAAA 8 3 345600 20120901011301 20120802011301 12051 miek.nl. BYSfIW0TtTt4NiCzKS2sbVU0S07chOYVyeRu1wqvEdjnwbkC5jHkRure 9z1b1sVObZ+/5A3j1jrQxDRFvvdEieQXB3u0br/15ksHadcx/0PJXO/I 7cMwIcNDXsDrZ8Ibmoma6UbGFG3IlcB+vFrc2s5P1Vs7B5tLk1KxyNBj AZ4=
|
||||
a.miek.nl. 86400 IN NSEC elektron.miek.nl. A AAAA RRSIG NSEC
|
||||
a.miek.nl. 86400 IN RRSIG NSEC 8 3 86400 20120901011301 20120802011301 12051 miek.nl. ms4ID23GdlABeaZiI7mPQoLLEsuBkJLwBbps5gmeLv7jBHjq0WH3inTS grXMJP/tjBXy67eej5EsgOeKJPUfQxsriA8KY2+Fisw0sASEy2D5jELG ydsCZ19XmmW1bwLxSK3u4dd7OLt9Q8MjbBW04mnO8lxWd1P1HK76HvBv 0bE=
|
||||
elektron.miek.nl. 345600 IN A 85.223.71.124
|
||||
elektron.miek.nl. 345600 IN RRSIG A 8 3 345600 20120901011301 20120802011301 12051 miek.nl. ZLaUqqwnM3b40T4PSyObXwH2BPG15TN/NlcspNUSDNOjPXPRecqcfpka 8zC+iABKomyVSIBSFMUXbXJZWvSArpQQp9j5XIIHrT6ePcYggQxqI1Kg ml+X0fIqxMW2CkmjIckZIHnRqctnrBGL7dlg6VFQnatoSOR82ldj20Sl MX4=
|
||||
elektron.miek.nl. 345600 IN AAAA 2001:7b8:32a::2
|
||||
elektron.miek.nl. 345600 IN RRSIG AAAA 8 3 345600 20120901011301 20120802011301 12051 miek.nl. NqXWEP9oH5SYarsNm1qAQRdQVh3/bcTjJj4vPpIqzn+U1yPWIBY0EMD/ N81FxwQ7kgwtMUDAULa3ml0IwRHXdv0V0qlQsMT5XPQnvYpi0MmfbLjk 8jV48vNgOavkIbC3uXXZ0NIuLUHSWs9+mneUEhyS9cUwu8O6AVQnNRi1 k+s=
|
||||
elektron.miek.nl. 345600 IN SSHFP 1 1 EFEA55929C653057D981BC0F1D2C9E11C60953C7
|
||||
elektron.miek.nl. 345600 IN SSHFP 2 1 1A117C327825918B23422021EB5618FADD8150EE
|
||||
elektron.miek.nl. 345600 IN RRSIG SSHFP 8 3 345600 20120901011301 20120802011301 12051 miek.nl. dHIqttT8uaGWCSTrzurNpfo9JZV+DV2aUJWJJsJlUijUe0ZyUOv2eD3V gxbi0Q1kTOWfFesCZi87Uweo+CRE5tsol3K5Tk4QZw3BI+bKi2Oo2m69 +Tb4TemzAM9zs2ySV5fTpmYFy03yknmbkD64v5St9De+W84WB6XjFTan jxc=
|
||||
elektron.miek.nl. 86400 IN NSEC localhost.miek.nl. A AAAA SSHFP RRSIG NSEC
|
||||
elektron.miek.nl. 86400 IN RRSIG NSEC 8 3 86400 20120901011301 20120802011301 12051 miek.nl. UzogCQ2By82P+QDL8liljGJQ2FNIbQ1kczfB1VEjRqMNE1c86DOXztHZ 0iTRXUYUa+VTjFyNeXmHuR09QApTcrs6QnZ1iTi23sECK76PXxBKj6/5 Nd4up9UiuLj1KLiKe1WqHgHfFfGn72xm3Rs8tEcWwbEPvph9CaL4FOhM bQM=
|
||||
localhost.miek.nl. 345600 IN A 127.0.0.1
|
||||
localhost.miek.nl. 345600 IN RRSIG A 8 3 345600 20120901011301 20120802011301 12051 miek.nl. fdzIyrQmEm4/oea3HHTDlIE9Yt89qdl/JrEZ+vhOQVQnUA7N1356cfHE J1defIMj+z8EiP7Lvg+kjsK+KXTYM880hE5QMQ3HrYX7n4Vqgeh2esiZ nbEx6zsJY4/7oYz7SC5wAfJxLXbT8vMJ7n6pZe1+oiZCzVCDazhIV+J1 h8g=
|
||||
localhost.miek.nl. 86400 IN NSEC www.miek.nl. A RRSIG NSEC
|
||||
localhost.miek.nl. 86400 IN RRSIG NSEC 8 3 86400 20120901011301 20120802011301 12051 miek.nl. JKZkBSeZfgAWpwtKGI/7uVxlMy4voS6942gzi4PDlcdvA95RmHTcwNnc oDX+dqA++tetOBsj93DzsqcCB4yKRGnd/KjwXvaKjD185kpNGP5G+zls lhM902aFwAHLdLcRNtcAmJypa8bPbjnfDdgznfmRh4waw84IRFUDAXrG e4c=
|
||||
www.miek.nl. 345600 IN CNAME a.miek.nl.
|
||||
www.miek.nl. 345600 IN RRSIG CNAME 8 3 345600 20120901011301 20120802011301 12051 miek.nl. D9u83dq8vO7jRZqgmv9kGMP/C3kLTdbLX0Yj6cfp5OtzPfKHi33NizJ/ 5jvr6f+w1gaMSI128d+znNbPpuIqr0BLYKTTBRok53ak2hSCLvL34ME3 5KLnSgq41xs3QxMtZvlak63s9kHuw+3fQpkr97sW7/v+PG6gGKRi4unn yKQ=
|
||||
www.miek.nl. 86400 IN NSEC miek.nl. CNAME RRSIG NSEC
|
||||
www.miek.nl. 86400 IN RRSIG NSEC 8 3 86400 20120901011301 20120802011301 12051 miek.nl. nvalmbQXtSBCKTnYgB+7AtnUKwpok7v42FptBZsbkHtXVupxfSq2uoaS Rnm8EBaBIRTD2cy5BtB6SSRaXzAn+nzm5jCvKYrmANXrm1KRw2M1OdLT Exk8MIr7NFpPNTKdGX2x0bpqq+sxbJn6m3F9QfnKYwtFeLlXZ2Tf1vfM 5A0=
|
||||
sub.miek.nl. IN NS a1.sub.miek.nl.
|
||||
sub.miek.nl. IN NS a2.sub.miek.nl.
|
||||
a1.sub IN A 127.0.0.1
|
||||
a2.sub IN A 127.0.0.1
|
||||
a1.sub IN AAAA ::1
|
||||
a2.sub IN AAAA ::1
|
||||
*.w.miek.nl. IN TXT "wildcard"
|
|
@ -1,12 +0,0 @@
|
|||
nl. 345600 IN SOA elektron.atoom.net. ghostbuster.atoom.net. 1343873581 14400 3600 604800 86400
|
||||
nl. 345600 IN RRSIG SOA 8 2 345600 20120901011301 20120802011301 12051 miek.nl. Sh1GoyMfseseRzqPdJwaNQojbIcn8nAfpGBUoq7J8Y6Jr9jKVEeivMo6 OYedeDhWDcchzLsfJxIM0j6h6dlhLqdNJu/5yLfaFeGgzJR9UcNaVLi5 CxGUwXZjDCfTlpTO8QHgo/sMiFA7Gbs7nLHg1b4V42rTOTVAqMoeZRaz AZE=
|
||||
nl. 345600 IN NS ext.ns.whyscream.net.
|
||||
nl. 345600 IN NS open.nlnetlabs.nl.
|
||||
nl. 345600 IN NS omval.tednet.nl.
|
||||
nl. 345600 IN NS elektron.atoom.net.
|
||||
|
||||
miek.nl. 345600 IN NS ext.ns.whyscream.net.
|
||||
miek.nl. 345600 IN NS open.nlnetlabs.nl.
|
||||
miek.nl. 345600 IN NS omval.tednet.nl.
|
||||
miek.nl. 345600 IN NS elektron.atoom.net.
|
||||
miek.nl. 3600 IN DS 5240 10 2 ddd87b83c6c3d7fdc528e94f5d79300f97f450d0961e787b9314690d69742539
|
|
@ -1,59 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"dns"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ReadZoneFile reads a zone and adds it.
|
||||
func (c *Config) ReadZoneFile(origin, file string) error {
|
||||
f, e := os.Open(file)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
z := dns.NewZone(origin)
|
||||
for rr := range dns.ParseZone(f, origin, file) {
|
||||
if rr.Error == nil {
|
||||
if e := z.Insert(rr.RR); e != nil {
|
||||
logPrintf("failed to insert record: %s\n", e.Error())
|
||||
}
|
||||
} else {
|
||||
logPrintf("failed to parse: %s\n", rr.Error.Error())
|
||||
}
|
||||
}
|
||||
c.Zones[origin] = z
|
||||
dns.HandleFunc(origin, func(w dns.ResponseWriter, req *dns.Msg) { serve(w, req, c.Zones[origin]) })
|
||||
return nil
|
||||
}
|
||||
|
||||
// DropZone discards a zone from the config.
|
||||
func (c *Config) DropZone(origin string) error {
|
||||
dns.HandleRemove(origin)
|
||||
delete(c.Zones, origin)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadZoneXfr reads a zone from an axfr.
|
||||
func (c *Config) ReadZoneXfr(origin, master string) error {
|
||||
client := new(dns.Client)
|
||||
client.Net = "tcp"
|
||||
m := new(dns.Msg)
|
||||
m.SetAxfr(origin)
|
||||
|
||||
z := dns.NewZone(origin)
|
||||
t, e := client.XfrReceive(m, master)
|
||||
if e == nil {
|
||||
for r := range t {
|
||||
if r.Error == nil {
|
||||
// Loop answer section
|
||||
for _, rr := range r.Reply.Answer {
|
||||
z.Insert(rr)
|
||||
}
|
||||
}
|
||||
}
|
||||
c.Zones[origin] = z
|
||||
dns.HandleFunc(origin, func(w dns.ResponseWriter, req *dns.Msg) { serve(w, req, c.Zones[origin]) })
|
||||
return nil
|
||||
}
|
||||
return e
|
||||
}
|
Loading…
Reference in New Issue