Simplify config and refactoring

This commit is contained in:
George 2020-05-17 10:05:06 -04:00
parent 00bd9a5486
commit 5c5e938742
3 changed files with 98 additions and 91 deletions

View File

@ -39,18 +39,14 @@ Look for `meshnamed.service` in the source directory for a systemd unit file.
In this example, meshnamed is configured as authoritative for two domain zones:
{
"Domain":"aiag7sesed2aaxgcgbnevruwpy",
"Records": [
"aiag7sesed2aaxgcgbnevruwpy": [
"aiag7sesed2aaxgcgbnevruwpy.meshname. AAAA 200:6fc8:9220:f400:5cc2:305a:4ac6:967e",
"_xmpp-client._tcp.aiag7sesed2aaxgcgbnevruwpy.meshname. SRV 5 0 5222 xmpp.aiag7sesed2aaxgcgbnevruwpy.meshname",
"_xmpp-server._tcp.aiag7sesed2aaxgcgbnevruwpy.meshname. SRV 5 0 5269 xmpp.aiag7sesed2aaxgcgbnevruwpy.meshname",
"xmpp.aiag7sesed2aaxgcgbnevruwpy.meshname. AAAA 300:6fc8:9220:f400::1",
"forum.aiag7sesed2aaxgcgbnevruwpy.meshname. CNAME amag7sesed2aaaaaaaaaaaaaau.meshname."
]
}
{
"Domain":"amag7sesed2aaaaaaaaaaaaaau",
"Records":[
],
"amag7sesed2aaaaaaaaaaaaaau": [
"amag7sesed2aaaaaaaaaaaaaau.meshname. AAAA 300:6fc8:9220:f400::5"
]
}

View File

@ -3,9 +3,10 @@ package main
import (
"flag"
"fmt"
"net"
"os"
"strings"
"os/signal"
"strings"
"syscall"
"github.com/gologme/log"
@ -13,6 +14,20 @@ import (
"github.com/zhoreeq/meshname/src/meshname"
)
func parseNetworks(networksconf string) (map[string]*net.IPNet, error) {
networks := make(map[string]*net.IPNet)
for _, item := range strings.Split(networksconf, ",") {
if tokens := strings.SplitN(item, "=", 2); len(tokens) == 2 {
if _, validSubnet, err := net.ParseCIDR(tokens[1]); err == nil {
networks[tokens[0]] = validSubnet
} else {
return nil, err
}
}
}
return networks, nil
}
func main() {
genconf := flag.String("genconf", "", "generate a new config for IP address")
subdomain := flag.String("subdomain", "meshname.", "subdomain used to generate config")
@ -33,24 +48,28 @@ func main() {
}
if *genconf != "" {
confString, err := meshname.GenConf(*genconf, *subdomain)
if err != nil {
logger.Errorln(err)
if conf, err := meshname.GenConf(*genconf, *subdomain); err == nil {
fmt.Println(conf)
} else {
fmt.Println(confString)
logger.Errorln(err)
}
return
}
networks := make(map[string]string)
for _, item := range strings.Split(*networksconf, ",") {
if tokens := strings.SplitN(item, "=", 2); len(tokens) == 2 {
networks[tokens[0]] = tokens[1]
}
}
s := new(meshname.MeshnameServer)
s.Init(logger, *listenAddr, *useconffile, networks)
s.Init(logger, *listenAddr)
if networks, err := parseNetworks(*networksconf); err == nil {
s.SetNetworks(networks)
} else {
logger.Errorln(err)
}
if *useconffile != "" {
s.LoadConfig(*useconffile)
}
s.Start()
c := make(chan os.Signal, 1)
@ -63,7 +82,11 @@ func main() {
case _ = <-c:
return
case _ = <-r:
s.UpdateConfig()
if *useconffile != "" {
s.Stop()
s.LoadConfig(*useconffile)
s.Start()
}
}
}
}

View File

@ -5,9 +5,8 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"strings"
"github.com/gologme/log"
@ -43,79 +42,58 @@ func GenConf(target, zone string) (string, error) {
}
subDomain := DomainFromIP(&ip)
selfRecord := fmt.Sprintf("\t\t\"%s.%s AAAA %s\"\n", subDomain, zone, target)
confString := fmt.Sprintf("{\n\t\"Domain\":\"%s\",\n\t\"Records\":[\n%s\t]\n}", subDomain, selfRecord)
confString := fmt.Sprintf("{\n\t\"%s\":[\n%s\t]\n}", subDomain, selfRecord)
return confString, nil
}
// Load zoneConfig from a JSON file
func ParseConfigFile(configPath string) (map[string][]dns.RR, error) {
conf, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, err
}
var dat map[string][]string
if err := json.Unmarshal(conf, &dat); err == nil {
return ParseZoneConfigMap(dat)
} else {
return nil, err
}
}
func ParseZoneConfigMap(zoneConfigMap map[string][]string) (map[string][]dns.RR, error) {
var zoneConfig = make(map[string][]dns.RR)
for subDomain, records := range zoneConfigMap {
for _, r := range records {
if rr, err := dns.NewRR(r); err == nil {
zoneConfig[subDomain] = append(zoneConfig[subDomain], rr)
} else {
return nil, err
}
}
}
return zoneConfig, nil
}
type MeshnameServer struct {
log *log.Logger
listenAddr, zoneConfigPath string
listenAddr string
zoneConfig map[string][]dns.RR
dnsClient *dns.Client
dnsServer *dns.Server
networks map[string]*net.IPNet
}
func (s *MeshnameServer) Init(log *log.Logger, listenAddr string, zoneConfigPath string, networks map[string]string) {
func (s *MeshnameServer) Init(log *log.Logger, listenAddr string) {
s.log = log
s.listenAddr = listenAddr
s.networks = make(map[string]*net.IPNet)
for domain, subnet := range networks {
_, validSubnet, err := net.ParseCIDR(subnet)
if err != nil {
s.log.Errorln(err)
continue
}
s.networks[domain] = validSubnet
}
s.zoneConfigPath = zoneConfigPath
s.zoneConfig = make(map[string][]dns.RR)
s.networks = make(map[string]*net.IPNet)
if s.dnsClient == nil {
s.dnsClient = new(dns.Client)
s.dnsClient.Timeout = 5000000000 // increased 5 seconds timeout
}
s.LoadConfig()
}
func (s *MeshnameServer) LoadConfig() {
if s.zoneConfigPath == "" {
return
}
for k := range s.zoneConfig {
delete(s.zoneConfig, k)
}
reader, err := os.Open(s.zoneConfigPath)
if err != nil {
s.log.Errorln("Can't open config:", err)
return
}
type Zone struct {
Domain string
Records []string
}
dec := json.NewDecoder(reader)
for {
var m Zone
if err := dec.Decode(&m); err == io.EOF {
break
} else if err != nil {
s.log.Errorln("Syntax error in config:", err)
return
}
for _, v := range m.Records {
rr, err := dns.NewRR(v)
if err != nil {
s.log.Errorln("Invalid DNS record:", v)
continue
}
s.zoneConfig[m.Domain] = append(s.zoneConfig[m.Domain], rr)
}
}
s.log.Infoln("Meshname config loaded:", s.zoneConfigPath)
}
func (s *MeshnameServer) Stop() error {
@ -127,15 +105,31 @@ func (s *MeshnameServer) Stop() error {
func (s *MeshnameServer) Start() error {
s.dnsServer = &dns.Server{Addr: s.listenAddr, Net: "udp"}
for domain := range s.networks {
dns.HandleFunc(domain, s.handleRequest)
s.log.Debugln("Handling:", domain)
for tld, subnet := range s.networks {
dns.HandleFunc(tld, s.handleRequest)
s.log.Debugln("Handling:", tld, subnet)
}
go s.dnsServer.ListenAndServe()
s.log.Infoln("Started meshnamed on:", s.listenAddr)
return nil
}
func (s *MeshnameServer) LoadConfig(confPath string) {
if zoneConf, err := ParseConfigFile(confPath); err == nil {
s.zoneConfig = zoneConf
} else {
s.log.Errorln("Can't parse config file:", err)
}
}
func (s *MeshnameServer) SetZoneConfig(zoneConfig map[string][]dns.RR) {
s.zoneConfig = zoneConfig
}
func (s *MeshnameServer) SetNetworks(networks map[string]*net.IPNet) {
s.networks = networks
}
func (s *MeshnameServer) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
var remoteLookups = make(map[string][]dns.Question)
m := new(dns.Msg)
@ -192,9 +186,3 @@ func (s *MeshnameServer) isRemoteLookupAllowed(addr net.Addr) bool {
return strings.HasPrefix(ra, "[::1]:") || strings.HasPrefix(ra, "127.0.0.1:")
}
func (s *MeshnameServer) UpdateConfig() error {
s.Stop()
s.LoadConfig()
s.Start()
return nil
}