2014-10-22 15:14:16 +00:00
package server
2014-11-13 10:55:51 +00:00
2014-10-22 15:14:16 +00:00
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"
2014-11-14 09:40:46 +00:00
import "path/filepath"
2014-10-22 15:14:16 +00:00
2014-11-14 08:51:57 +00:00
const version = "1.0"
2014-10-22 15:14:16 +00:00
type Server struct {
2014-11-13 10:55:51 +00:00
cfg ServerConfig
2014-10-22 15:14:16 +00:00
2014-11-13 10:55:51 +00:00
engine madns . Engine
2014-10-22 15:14:16 +00:00
2014-11-13 10:55:51 +00:00
mux * dns . ServeMux
udpListener * dns . Server
tcpListener * dns . Server
2014-10-22 15:14:16 +00:00
}
type ServerConfig struct {
2014-11-13 10:55:51 +00:00
Bind string ` default:":53" usage:"Address to bind to (e.g. 0.0.0.0:53)" `
2014-11-13 11:14:15 +00:00
PublicKey string ` default:"" usage:"Path to the DNSKEY KSK public key file" `
PrivateKey string ` default:"" usage:"Path to the KSK's corresponding private key file" `
2014-11-13 10:55:51 +00:00
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" `
2014-11-14 09:40:46 +00:00
CacheMaxEntries int ` default:"100" usage:"Maximum name cache entries" `
2014-11-13 10:55:51 +00:00
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-25 13:50:51 +00:00
ConfigDir string // path to interpret filenames relative to
2014-11-14 09:40:46 +00:00
}
func ( cfg * ServerConfig ) cpath ( s string ) string {
return filepath . Join ( cfg . ConfigDir , s )
2014-10-22 15:14:16 +00:00
}
func NewServer ( cfg * ServerConfig ) ( s * Server , err error ) {
2014-11-13 10:55:51 +00:00
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
}
ecfg := & madns . EngineConfig {
2014-11-25 13:50:51 +00:00
Backend : b ,
2014-11-14 08:51:57 +00:00
VersionString : "ncdns/" + version ,
2014-11-13 10:55:51 +00:00
}
// key setup
if cfg . PublicKey != "" {
2014-12-04 12:04:14 +00:00
ecfg . KSK , ecfg . KSKPrivate , err = s . loadKey ( cfg . PublicKey , cfg . PrivateKey )
2014-11-13 10:55:51 +00:00
if err != nil {
return nil , err
}
}
if cfg . ZonePublicKey != "" {
2014-12-04 12:04:14 +00:00
ecfg . ZSK , ecfg . ZSKPrivate , err = s . loadKey ( cfg . ZonePublicKey , cfg . ZonePrivateKey )
2014-11-13 10:55:51 +00:00
if err != nil {
return nil , err
}
}
if ecfg . KSK != nil && ecfg . ZSK == nil {
return nil , fmt . Errorf ( "Must specify ZSK if KSK is specified" )
}
e , err := madns . NewEngine ( ecfg )
if err != nil {
return
}
s . engine = e
return
2014-10-22 15:14:16 +00:00
}
func ( s * Server ) loadKey ( fn , privateFn string ) ( k * dns . DNSKEY , privatek dns . PrivateKey , err error ) {
2014-11-14 09:40:46 +00:00
fn = s . cfg . cpath ( fn )
privateFn = s . cfg . cpath ( privateFn )
2014-11-13 10:55:51 +00:00
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
2014-10-22 15:14:16 +00:00
}
2014-11-14 08:51:57 +00:00
func ( s * Server ) Start ( ) error {
2014-11-13 10:55:51 +00:00
s . mux = dns . NewServeMux ( )
s . mux . Handle ( "." , s . engine )
s . udpListener = s . runListener ( "udp" )
s . tcpListener = s . runListener ( "tcp" )
2014-11-14 08:51:57 +00:00
return nil
}
2014-10-22 15:14:16 +00:00
func ( s * Server ) doRunListener ( ds * dns . Server ) {
2014-11-13 10:55:51 +00:00
err := ds . ListenAndServe ( )
log . Fatale ( err )
2014-10-22 15:14:16 +00:00
}
func ( s * Server ) runListener ( net string ) * dns . Server {
2014-11-13 10:55:51 +00:00
ds := & dns . Server {
Addr : s . cfg . Bind ,
Net : net ,
Handler : s . mux ,
}
go s . doRunListener ( ds )
return ds
2014-10-22 15:14:16 +00:00
}