2017-12-29 07:16:20 +03:00
package main
2018-05-27 04:40:19 +03:00
import "encoding/json"
2017-12-29 07:16:20 +03:00
import "encoding/hex"
import "flag"
import "fmt"
import "io/ioutil"
import "net"
import "os"
import "os/signal"
2018-02-19 00:16:47 +03:00
import "syscall"
2017-12-29 07:16:20 +03:00
import "time"
2018-01-09 11:08:54 +03:00
import "regexp"
2018-03-07 22:41:56 +03:00
import "math/rand"
2017-12-29 07:16:20 +03:00
import _ "net/http/pprof"
import "net/http"
import "log"
import "runtime"
2018-04-19 17:30:40 +03:00
import "yggdrasil"
import "yggdrasil/config"
2017-12-29 07:16:20 +03:00
2018-02-19 00:16:47 +03:00
import "github.com/kardianos/minwinsvc"
2018-05-09 15:54:31 +03:00
import "github.com/neilalexander/hjson-go"
import "github.com/mitchellh/mapstructure"
2018-02-16 17:12:44 +03:00
2018-04-19 17:30:40 +03:00
type nodeConfig = config . NodeConfig
type Core = yggdrasil . Core
2017-12-29 07:16:20 +03:00
type node struct {
2018-01-05 01:37:51 +03:00
core Core
2017-12-29 07:16:20 +03:00
}
func ( n * node ) init ( cfg * nodeConfig , logger * log . Logger ) {
2018-05-23 13:28:20 +03:00
boxPub , err := hex . DecodeString ( cfg . EncryptionPublicKey )
2018-01-05 01:37:51 +03:00
if err != nil {
panic ( err )
}
2018-05-23 13:28:20 +03:00
boxPriv , err := hex . DecodeString ( cfg . EncryptionPrivateKey )
2018-01-05 01:37:51 +03:00
if err != nil {
panic ( err )
}
2018-05-23 13:28:20 +03:00
sigPub , err := hex . DecodeString ( cfg . SigningPublicKey )
2018-01-05 01:37:51 +03:00
if err != nil {
panic ( err )
}
2018-05-23 13:28:20 +03:00
sigPriv , err := hex . DecodeString ( cfg . SigningPrivateKey )
2018-01-05 01:37:51 +03:00
if err != nil {
panic ( err )
}
n . core . DEBUG_init ( boxPub , boxPriv , sigPub , sigPriv )
n . core . DEBUG_setLogger ( logger )
2018-04-19 17:30:40 +03:00
2018-01-05 01:37:51 +03:00
logger . Println ( "Starting interface..." )
2018-02-10 02:42:55 +03:00
n . core . DEBUG_setupAndStartGlobalTCPInterface ( cfg . Listen ) // Listen for peers on TCP
2018-02-10 03:50:03 +03:00
n . core . DEBUG_setupAndStartGlobalUDPInterface ( cfg . Listen ) // Also listen on UDP, TODO allow separate configuration for ip/port to listen on each of these
2018-01-05 01:37:51 +03:00
logger . Println ( "Started interface" )
2018-01-21 03:17:15 +03:00
logger . Println ( "Starting admin socket..." )
n . core . DEBUG_setupAndStartAdminInterface ( cfg . AdminListen )
logger . Println ( "Started admin socket" )
2018-05-23 13:28:20 +03:00
for _ , pBoxStr := range cfg . AllowedEncryptionPublicKeys {
n . core . DEBUG_addAllowedEncryptionPublicKey ( pBoxStr )
2018-05-07 03:48:26 +03:00
}
2018-05-23 13:28:20 +03:00
for _ , ll := range cfg . MulticastInterfaces {
2018-05-23 13:13:53 +03:00
ifceExpr , err := regexp . Compile ( ll )
if err != nil {
panic ( err )
}
n . core . DEBUG_setIfceExpr ( ifceExpr )
}
n . core . DEBUG_setupAndStartMulticastInterface ( )
2018-05-07 03:48:26 +03:00
2018-01-05 01:37:51 +03:00
go func ( ) {
if len ( cfg . Peers ) == 0 {
return
}
for {
for _ , p := range cfg . Peers {
2018-04-26 17:23:21 +03:00
n . core . DEBUG_addPeer ( p )
2018-01-05 01:37:51 +03:00
time . Sleep ( time . Second )
}
time . Sleep ( time . Minute )
}
} ( )
2017-12-29 07:16:20 +03:00
}
2018-03-07 22:41:56 +03:00
func generateConfig ( isAutoconf bool ) * nodeConfig {
2018-01-05 01:37:51 +03:00
core := Core { }
bpub , bpriv := core . DEBUG_newBoxKeys ( )
spub , spriv := core . DEBUG_newSigKeys ( )
cfg := nodeConfig { }
2018-03-07 22:41:56 +03:00
if isAutoconf {
cfg . Listen = "[::]:0"
} else {
r1 := rand . New ( rand . NewSource ( time . Now ( ) . UnixNano ( ) ) )
2018-03-10 22:58:48 +03:00
cfg . Listen = fmt . Sprintf ( "[::]:%d" , r1 . Intn ( 65534 - 32768 ) + 32768 )
2018-03-07 22:41:56 +03:00
}
2018-02-12 00:45:44 +03:00
cfg . AdminListen = "[::1]:9001"
2018-05-23 13:28:20 +03:00
cfg . EncryptionPublicKey = hex . EncodeToString ( bpub [ : ] )
cfg . EncryptionPrivateKey = hex . EncodeToString ( bpriv [ : ] )
cfg . SigningPublicKey = hex . EncodeToString ( spub [ : ] )
cfg . SigningPrivateKey = hex . EncodeToString ( spriv [ : ] )
2018-01-05 01:37:51 +03:00
cfg . Peers = [ ] string { }
2018-05-23 13:28:20 +03:00
cfg . AllowedEncryptionPublicKeys = [ ] string { }
2018-05-27 04:40:19 +03:00
cfg . MulticastInterfaces = [ ] string { ".*" }
2018-03-03 15:30:54 +03:00
cfg . IfName = core . DEBUG_GetTUNDefaultIfName ( )
cfg . IfMTU = core . DEBUG_GetTUNDefaultIfMTU ( )
cfg . IfTAPMode = core . DEBUG_GetTUNDefaultIfTAPMode ( )
2018-04-19 17:30:40 +03:00
2018-01-05 01:37:51 +03:00
return & cfg
2017-12-29 07:16:20 +03:00
}
func doGenconf ( ) string {
2018-03-07 22:41:56 +03:00
cfg := generateConfig ( false )
2018-05-09 15:54:31 +03:00
bs , err := hjson . Marshal ( cfg )
2018-01-05 01:37:51 +03:00
if err != nil {
panic ( err )
}
return string ( bs )
2017-12-29 07:16:20 +03:00
}
var pprof = flag . Bool ( "pprof" , false , "Run pprof, see http://localhost:6060/debug/pprof/" )
var genconf = flag . Bool ( "genconf" , false , "print a new config to stdout" )
var useconf = flag . Bool ( "useconf" , false , "read config from stdin" )
2018-05-27 20:31:35 +03:00
var useconffile = flag . String ( "useconffile" , "" , "read config from specified file path" )
var normaliseconf = flag . Bool ( "normaliseconf" , false , "use in combination with either -useconf or -useconffile, outputs your configuration normalised" )
2017-12-29 07:16:20 +03:00
var autoconf = flag . Bool ( "autoconf" , false , "automatic mode (dynamic IP, peer with IPv6 neighbors)" )
func main ( ) {
2018-01-05 01:37:51 +03:00
flag . Parse ( )
var cfg * nodeConfig
switch {
case * autoconf :
2018-03-07 22:41:56 +03:00
cfg = generateConfig ( true )
2018-05-27 20:31:35 +03:00
case * useconffile != "" || * useconf :
2018-02-16 17:12:44 +03:00
var config [ ] byte
var err error
2018-05-27 20:31:35 +03:00
if * useconffile != "" {
config , err = ioutil . ReadFile ( * useconffile )
} else {
config , err = ioutil . ReadAll ( os . Stdin )
}
2018-01-05 01:37:51 +03:00
if err != nil {
panic ( err )
}
2018-03-07 22:41:56 +03:00
cfg = generateConfig ( false )
2018-05-09 15:54:31 +03:00
var dat map [ string ] interface { }
if err := hjson . Unmarshal ( config , & dat ) ; err != nil {
2018-05-09 16:03:28 +03:00
panic ( err )
}
2018-05-27 04:40:19 +03:00
confJson , err := json . Marshal ( dat )
if err != nil {
panic ( err )
}
json . Unmarshal ( confJson , & cfg )
2018-05-23 14:04:27 +03:00
// For now we will do a little bit to help the user adjust their
// configuration to match the new configuration format
changes := map [ string ] string {
2018-05-26 23:50:47 +03:00
"Multicast" : "" ,
"LinkLocal" : "MulticastInterfaces" ,
"BoxPub" : "EncryptionPublicKey" ,
"BoxPriv" : "EncryptionPrivateKey" ,
"SigPub" : "SigningPublicKey" ,
"SigPriv" : "SigningPrivateKey" ,
2018-05-23 14:32:26 +03:00
"AllowedBoxPubs" : "AllowedEncryptionPublicKeys" ,
2018-05-23 14:04:27 +03:00
}
for from , to := range changes {
2018-05-23 20:53:44 +03:00
if _ , ok := dat [ from ] ; ok {
if to == "" {
2018-05-23 14:04:27 +03:00
if ! * normaliseconf {
2018-05-23 20:53:44 +03:00
log . Println ( "Warning: Deprecated config option" , from , "- please remove" )
2018-05-23 14:04:27 +03:00
}
} else {
if ! * normaliseconf {
2018-05-23 20:53:44 +03:00
log . Println ( "Warning: Deprecated config option" , from , "- please rename to" , to )
2018-05-23 14:04:27 +03:00
}
if _ , ok := dat [ to ] ; ! ok {
dat [ to ] = dat [ from ]
}
}
}
}
2018-05-09 15:54:31 +03:00
if err = mapstructure . Decode ( dat , & cfg ) ; err != nil {
2018-01-05 01:37:51 +03:00
panic ( err )
}
2018-05-23 14:04:27 +03:00
if * normaliseconf {
bs , err := hjson . Marshal ( cfg )
if err != nil {
panic ( err )
}
fmt . Println ( string ( bs ) )
return
}
2018-01-05 01:37:51 +03:00
case * genconf :
fmt . Println ( doGenconf ( ) )
default :
flag . PrintDefaults ( )
}
if cfg == nil {
return
}
logger := log . New ( os . Stdout , "" , log . Flags ( ) )
if * pprof {
runtime . SetBlockProfileRate ( 1 )
go func ( ) { log . Println ( http . ListenAndServe ( "localhost:6060" , nil ) ) } ( )
}
// Setup
logger . Println ( "Initializing..." )
n := node { }
n . init ( cfg , logger )
2018-02-16 01:29:13 +03:00
if cfg . IfName != "none" {
logger . Println ( "Starting TUN/TAP..." )
} else {
logger . Println ( "Not starting TUN/TAP" )
}
2018-02-04 20:25:20 +03:00
//n.core.DEBUG_startTun(cfg.IfName) // 1280, the smallest supported MTU
2018-02-14 15:53:32 +03:00
n . core . DEBUG_startTunWithMTU ( cfg . IfName , cfg . IfTAPMode , cfg . IfMTU ) // Largest supported MTU
2018-01-05 01:37:51 +03:00
defer func ( ) {
logger . Println ( "Closing..." )
n . core . DEBUG_stopTun ( )
} ( )
logger . Println ( "Started..." )
2018-05-21 18:15:31 +03:00
address := ( * n . core . GetAddress ( ) ) [ : ]
subnet := ( * n . core . GetSubnet ( ) ) [ : ]
subnet = append ( subnet , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )
logger . Printf ( "Your IPv6 address is %s" , net . IP ( address ) . String ( ) )
logger . Printf ( "Your IPv6 subnet is %s/64" , net . IP ( subnet ) . String ( ) )
2018-01-05 01:37:51 +03:00
// Catch interrupt to exit gracefully
c := make ( chan os . Signal , 1 )
2018-02-19 00:16:47 +03:00
signal . Notify ( c , os . Interrupt , syscall . SIGTERM )
// Create a function to capture the service being stopped on Windows
winTerminate := func ( ) {
2018-02-19 00:32:55 +03:00
c <- os . Interrupt
}
2018-02-19 00:16:47 +03:00
minwinsvc . SetOnExit ( winTerminate )
// Wait for the terminate/interrupt signal
2018-01-05 01:37:51 +03:00
<- c
logger . Println ( "Stopping..." )
2017-12-29 07:16:20 +03:00
}