2014-10-22 15:14:16 +00:00
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" `
2014-11-11 10:35:48 +00:00
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" `
2014-10-22 15:14:16 +00:00
}
func NewServer ( cfg * ServerConfig ) ( s * Server , err error ) {
s = & Server { }
s . cfg = * cfg
bcfg := & backend . Config {
RPCUsername : cfg . NamecoinRPCUsername ,
RPCPassword : cfg . NamecoinRPCPassword ,
2014-11-12 09:38:20 +00:00
RPCAddress : cfg . NamecoinRPCAddress ,
2014-10-22 15:14:16 +00:00
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
}