package server import "github.com/hlandau/madns" import "github.com/hlandau/degoutils/log" import "github.com/hlandau/ncdns/backend" import "github.com/miekg/dns" import "os" import "fmt" import "os/signal" import "syscall" type Server struct { cfg ServerConfig engine madns.Engine mux *dns.ServeMux udpListener *dns.Server tcpListener *dns.Server } type ServerConfig struct { Bind string `default:":53" usage:"Address to bind to (e.g. 0.0.0.0:53)"` PublicKey string `default:"ncdns.key" usage:"Path to the DNSKEY KSK public key file"` PrivateKey string `default:"ncdns.private" usage:"Path to the KSK's corresponding private key file"` ZonePublicKey string `default:"" usage:"Path to the DNSKEY ZSK public key file; if one is not specified, a temporary one is generated on startup and used only for the duration of that process"` ZonePrivateKey string `default:"" usage:"Path to the ZSK's corresponding private key file"` NamecoinRPCUsername string `default:"" usage:"Namecoin RPC username"` NamecoinRPCPassword string `default:"" usage:"Namecoin RPC password"` NamecoinRPCAddress string `default:"localhost:8336" usage:"Namecoin RPC server address"` CacheMaxEntries int `default:"1000" usage:"Maximum name cache entries"` SelfName string `default:"" usage:"Canonical name for this nameserver (default: autogenerated psuedo-hostname resolving to SelfIP; SelfIP is not used if this is set)"` SelfIP string `default:"127.127.127.127" usage:"The canonical IP address for this service"` Daemonize bool `default:"false" usage:"Daemonize (doesn't fork)"` UID int `default:"0" usage:"UID to drop privileges to if run as root"` GID int `default:"0" usage:"GID to drop privileges to if run as root"` } func NewServer(cfg *ServerConfig) (s *Server, err error) { s = &Server{} s.cfg = *cfg bcfg := &backend.Config { RPCUsername: cfg.NamecoinRPCUsername, RPCPassword: cfg.NamecoinRPCPassword, RPCAddress: cfg.NamecoinRPCAddress, CacheMaxEntries: cfg.CacheMaxEntries, SelfName: cfg.SelfName, SelfIP: cfg.SelfIP, } b, err := backend.New(bcfg) if err != nil { return } // key setup ksk, kskPrivate, err := s.loadKey(cfg.PublicKey, cfg.PrivateKey) log.Fatale(err, "error reading KSK key") var zsk *dns.DNSKEY var zskPrivate dns.PrivateKey if cfg.ZonePublicKey != "" { zsk, zskPrivate, err = s.loadKey(cfg.ZonePublicKey, cfg.ZonePrivateKey) log.Fatale(err, "error reading ZSK key") } else { zsk = &dns.DNSKEY{} zsk.Hdr.Rrtype = dns.TypeDNSKEY zsk.Hdr.Class = dns.ClassINET zsk.Hdr.Ttl = 3600 zsk.Algorithm = dns.RSASHA256 zsk.Protocol = 3 zsk.Flags = dns.ZONE zskPrivate, err = zsk.Generate(2048) log.Fatale(err) } ecfg := &madns.EngineConfig { Backend: b, KSK: ksk, KSKPrivate: kskPrivate, ZSK: zsk, ZSKPrivate: zskPrivate, } e, err := madns.NewEngine(ecfg) if err != nil { return } s.engine = e return } func (s *Server) loadKey(fn, privateFn string) (k *dns.DNSKEY, privatek dns.PrivateKey, err error) { f, err := os.Open(fn) if err != nil { return } rr, err := dns.ReadRR(f, fn) if err != nil { return } k, ok := rr.(*dns.DNSKEY) if !ok { err = fmt.Errorf("Loaded record from key file, but it wasn't a DNSKEY") return } privatef, err := os.Open(privateFn) if err != nil { return } privatek, err = k.ReadPrivateKey(privatef, privateFn) log.Fatale(err) return } func (s *Server) Run() { s.mux = dns.NewServeMux() s.mux.Handle(".", s.engine) s.udpListener = s.runListener("udp") s.tcpListener = s.runListener("tcp") log.Info("Ready.") // wait sig := make(chan os.Signal) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) for { s := <-sig fmt.Printf("Signal %v received, stopping.", s) break } } func (s *Server) doRunListener(ds *dns.Server) { err := ds.ListenAndServe() log.Fatale(err) } func (s *Server) runListener(net string) *dns.Server { ds := &dns.Server { Addr: s.cfg.Bind, Net: net, Handler: s.mux, } go s.doRunListener(ds) return ds }