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
}
2014-11-13 03:02:57 +00:00
ecfg := & madns . EngineConfig {
Backend : b ,
}
2014-10-22 15:14:16 +00:00
2014-11-13 03:02:57 +00:00
// key setup
if cfg . PublicKey != "" {
ksk , kskPrivate , err := s . loadKey ( cfg . PublicKey , cfg . PrivateKey )
if err != nil {
return nil , err
}
ecfg . KSK = ksk
ecfg . KSKPrivate = kskPrivate
}
2014-10-22 15:14:16 +00:00
if cfg . ZonePublicKey != "" {
2014-11-13 03:02:57 +00:00
zsk , zskPrivate , err := s . loadKey ( cfg . ZonePublicKey , cfg . ZonePrivateKey )
if err != nil {
return nil , err
}
ecfg . ZSK = zsk
ecfg . ZSKPrivate = zskPrivate
2014-10-22 15:14:16 +00:00
}
2014-11-13 03:02:57 +00:00
if ecfg . KSK != nil && ecfg . ZSK == nil {
return nil , fmt . Errorf ( "Must specify ZSK if KSK is specified" )
2014-10-22 15:14:16 +00:00
}
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
}