From c56ec05ae731dcdf804916e36284bb0d42483c6f Mon Sep 17 00:00:00 2001 From: George <57254463+zhoreeq@users.noreply.github.com> Date: Mon, 5 Apr 2021 00:58:46 -0400 Subject: [PATCH] Add .meship protocol support (#7) (#8) * Add .meship protocol support (#7) * Add an option to disable .meship resolver Co-authored-by: George --- cmd/meshnamed/main.go | 5 +-- pkg/meshname/server.go | 73 +++++++++++++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/cmd/meshnamed/main.go b/cmd/meshnamed/main.go index 9ddb77d..2a1dec2 100644 --- a/cmd/meshnamed/main.go +++ b/cmd/meshnamed/main.go @@ -38,7 +38,7 @@ func loadConfig(s *meshname.MeshnameServer, confPath string) error { var ( genconf, subdomain, useconffile, listenAddr, networksconf string - debug, allowRemote bool + debug, noMeshIP, allowRemote bool ) func init() { @@ -47,6 +47,7 @@ func init() { flag.StringVar(&useconffile, "useconffile", "", "run daemon with a config file") flag.StringVar(&listenAddr, "listenaddr", "[::1]:53535", "address to listen on") flag.StringVar(&networksconf, "networks", "ygg=200::/7,cjd=fc00::/8,meshname=::/0", "TLD=subnet list separated by comma") + flag.BoolVar(&noMeshIP, "nomeship", false, "disable .meship resolver") flag.BoolVar(&allowRemote, "allowremote", false, "allow remote queries from any IP address") flag.BoolVar(&debug, "debug", false, "enable debug logging") } @@ -77,7 +78,7 @@ func main() { logger.Fatalln(err) } - s := meshname.New(logger, listenAddr, networks, allowRemote) + s := meshname.New(logger, listenAddr, networks, !noMeshIP, allowRemote) if useconffile != "" { if err := loadConfig(s, useconffile); err != nil { logger.Fatalln(err) diff --git a/pkg/meshname/server.go b/pkg/meshname/server.go index 71ea538..3c45608 100644 --- a/pkg/meshname/server.go +++ b/pkg/meshname/server.go @@ -11,12 +11,13 @@ import ( ) type MeshnameServer struct { - log *log.Logger - listenAddr string - dnsClient *dns.Client - dnsServer *dns.Server - networks map[string]*net.IPNet - allowRemote bool + log *log.Logger + listenAddr string + dnsClient *dns.Client + dnsServer *dns.Server + networks map[string]*net.IPNet + enableMeshIP bool + allowRemote bool dnsRecordsLock sync.RWMutex dnsRecords map[string][]dns.RR @@ -26,17 +27,18 @@ type MeshnameServer struct { } // New is a constructor for MeshnameServer -func New(log *log.Logger, listenAddr string, networks map[string]*net.IPNet, allowRemote bool) *MeshnameServer { +func New(log *log.Logger, listenAddr string, networks map[string]*net.IPNet, enableMeshIP bool, allowRemote bool) *MeshnameServer { dnsClient := new(dns.Client) dnsClient.Timeout = 5000000000 // increased 5 seconds timeout return &MeshnameServer{ - log: log, - listenAddr: listenAddr, - dnsRecords: make(map[string][]dns.RR), - networks: networks, - dnsClient: dnsClient, - allowRemote: allowRemote, + log: log, + listenAddr: listenAddr, + dnsRecords: make(map[string][]dns.RR), + networks: networks, + dnsClient: dnsClient, + enableMeshIP: enableMeshIP, + allowRemote: allowRemote, } } @@ -59,15 +61,20 @@ func (s *MeshnameServer) Start() error { if !s.started { waitStarted := make(chan struct{}) s.dnsServer = &dns.Server{ - Addr: s.listenAddr, - Net: "udp", - NotifyStartedFunc: func(){ close(waitStarted) }, + Addr: s.listenAddr, + Net: "udp", + NotifyStartedFunc: func() { close(waitStarted) }, } for tld, subnet := range s.networks { - dns.HandleFunc(tld, s.handleRequest) + dns.HandleFunc(tld, s.handleMeshnameRequest) s.log.Debugln("Handling:", tld, subnet) } - go func(){ + if s.enableMeshIP { + dns.HandleFunc("meship", s.handleMeshIPRequest) + s.log.Debugln("Handling: meship ::/0") + } + + go func() { if err := s.dnsServer.ListenAndServe(); err != nil { s.log.Fatalln("MeshnameServer failed to start:", err) } @@ -88,7 +95,7 @@ func (s *MeshnameServer) ConfigureDNSRecords(dnsRecords map[string][]dns.RR) { s.dnsRecordsLock.Unlock() } -func (s *MeshnameServer) handleRequest(w dns.ResponseWriter, r *dns.Msg) { +func (s *MeshnameServer) handleMeshnameRequest(w dns.ResponseWriter, r *dns.Msg) { var remoteLookups = make(map[string][]dns.Question) m := new(dns.Msg) m.SetReply(r) @@ -146,6 +153,34 @@ func (s *MeshnameServer) handleRequest(w dns.ResponseWriter, r *dns.Msg) { } } +func (s *MeshnameServer) handleMeshIPRequest(w dns.ResponseWriter, r *dns.Msg) { + m := new(dns.Msg) + m.SetReply(r) + + for _, q := range r.Question { + labels := dns.SplitDomainName(q.Name) + // resolve only 2nd level domains and AAAA type + if len(labels) != 2 || q.Qtype != dns.TypeAAAA || q.Qclass != dns.ClassINET { + s.log.Debugln("Error: invalid resource requested") + continue + } + + if resolvedAddr, err := IPFromDomain(&labels[0]); err == nil { + answer := new(dns.AAAA) + answer.Hdr = dns.RR_Header{Name: q.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 3600} + answer.AAAA = resolvedAddr + + m.Answer = append(m.Answer, answer) + } else { + s.log.Debugln(err) + } + } + + if err := w.WriteMsg(m); err != nil { + s.log.Debugln("Error writing response:", err) + } +} + func (s *MeshnameServer) isRemoteLookupAllowed(addr net.Addr) bool { // TODO prefix whitelists ? if s.allowRemote {