mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-30 07:05:06 +03:00
Break out cmd/yggdrasil a bit, tweaks
This commit is contained in:
parent
74201e7cfd
commit
8057d80ec9
3 changed files with 123 additions and 112 deletions
47
cmd/yggdrasil/config.go
Normal file
47
cmd/yggdrasil/config.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config.NodeConfig {
|
||||||
|
// Use a configuration file. If -useconf, the configuration will be read
|
||||||
|
// from stdin. If -useconffile, the configuration will be read from the
|
||||||
|
// filesystem.
|
||||||
|
var conf []byte
|
||||||
|
var err error
|
||||||
|
if *useconffile != "" {
|
||||||
|
// Read the file from the filesystem
|
||||||
|
conf, err = ioutil.ReadFile(*useconffile)
|
||||||
|
} else {
|
||||||
|
// Read the file from stdin.
|
||||||
|
conf, err = ioutil.ReadAll(os.Stdin)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// If there's a byte order mark - which Windows 10 is now incredibly fond of
|
||||||
|
// throwing everywhere when it's converting things into UTF-16 for the hell
|
||||||
|
// of it - remove it and decode back down into UTF-8. This is necessary
|
||||||
|
// because hjson doesn't know what to do with UTF-16 and will panic
|
||||||
|
if bytes.Compare(conf[0:2], []byte{0xFF, 0xFE}) == 0 ||
|
||||||
|
bytes.Compare(conf[0:2], []byte{0xFE, 0xFF}) == 0 {
|
||||||
|
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
||||||
|
decoder := utf.NewDecoder()
|
||||||
|
conf, err = decoder.Bytes(conf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Generate blank configuration
|
||||||
|
cfg := config.GenerateConfig()
|
||||||
|
// ... and then update it with the supplied HJSON input
|
||||||
|
if err := cfg.UnmarshalHJSON(conf); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return cfg
|
||||||
|
}
|
|
@ -1,19 +1,15 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.org/x/text/encoding/unicode"
|
|
||||||
|
|
||||||
"github.com/gologme/log"
|
"github.com/gologme/log"
|
||||||
gsyslog "github.com/hashicorp/go-syslog"
|
gsyslog "github.com/hashicorp/go-syslog"
|
||||||
"github.com/hjson/hjson-go"
|
"github.com/hjson/hjson-go"
|
||||||
|
@ -36,44 +32,6 @@ type node struct {
|
||||||
admin admin.AdminSocket
|
admin admin.AdminSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config.NodeConfig {
|
|
||||||
// Use a configuration file. If -useconf, the configuration will be read
|
|
||||||
// from stdin. If -useconffile, the configuration will be read from the
|
|
||||||
// filesystem.
|
|
||||||
var conf []byte
|
|
||||||
var err error
|
|
||||||
if *useconffile != "" {
|
|
||||||
// Read the file from the filesystem
|
|
||||||
conf, err = ioutil.ReadFile(*useconffile)
|
|
||||||
} else {
|
|
||||||
// Read the file from stdin.
|
|
||||||
conf, err = ioutil.ReadAll(os.Stdin)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// If there's a byte order mark - which Windows 10 is now incredibly fond of
|
|
||||||
// throwing everywhere when it's converting things into UTF-16 for the hell
|
|
||||||
// of it - remove it and decode back down into UTF-8. This is necessary
|
|
||||||
// because hjson doesn't know what to do with UTF-16 and will panic
|
|
||||||
if bytes.Compare(conf[0:2], []byte{0xFF, 0xFE}) == 0 ||
|
|
||||||
bytes.Compare(conf[0:2], []byte{0xFE, 0xFF}) == 0 {
|
|
||||||
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
|
||||||
decoder := utf.NewDecoder()
|
|
||||||
conf, err = decoder.Bytes(conf)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Generate blank configuration
|
|
||||||
cfg := config.GenerateConfig()
|
|
||||||
// ... and then update it with the supplied HJSON input
|
|
||||||
if err := cfg.UnmarshalHJSON(conf); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
// The main function is responsible for configuring and starting Yggdrasil.
|
// The main function is responsible for configuring and starting Yggdrasil.
|
||||||
func main() {
|
func main() {
|
||||||
// Configure the command line parameters.
|
// Configure the command line parameters.
|
||||||
|
@ -87,10 +45,10 @@ func main() {
|
||||||
logging := flag.String("logging", "info,warn,error", "comma-separated list of logging levels to enable")
|
logging := flag.String("logging", "info,warn,error", "comma-separated list of logging levels to enable")
|
||||||
logto := flag.String("logto", "stdout", "file path to log to, \"syslog\" or \"stdout\"")
|
logto := flag.String("logto", "stdout", "file path to log to, \"syslog\" or \"stdout\"")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// Setup the Yggdrasil node itself. The node{} type includes a Core, so we
|
// Setup the Yggdrasil node itself. The node{} type includes a Core, so we
|
||||||
// don't need to create this manually.
|
// don't need to create this manually.
|
||||||
n := node{}
|
n := node{}
|
||||||
|
// Parse command line parameters, this will tell us what to do.
|
||||||
var err error
|
var err error
|
||||||
switch {
|
switch {
|
||||||
case *ver:
|
case *ver:
|
||||||
|
@ -164,9 +122,6 @@ func main() {
|
||||||
logger = log.New(os.Stdout, "", log.Flags())
|
logger = log.New(os.Stdout, "", log.Flags())
|
||||||
logger.Warnln("Logging defaulting to stdout")
|
logger.Warnln("Logging defaulting to stdout")
|
||||||
}
|
}
|
||||||
//logger.EnableLevel("error")
|
|
||||||
//logger.EnableLevel("warn")
|
|
||||||
//logger.EnableLevel("info")
|
|
||||||
if levels := strings.Split(*logging, ","); len(levels) > 0 {
|
if levels := strings.Split(*logging, ","); len(levels) > 0 {
|
||||||
for _, level := range levels {
|
for _, level := range levels {
|
||||||
l := strings.TrimSpace(level)
|
l := strings.TrimSpace(level)
|
||||||
|
@ -178,19 +133,20 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now start Yggdrasil - this starts the DHT, router, switch and other core
|
// Parse the encryption keys from the config
|
||||||
// components needed for Yggdrasil to operate
|
|
||||||
var boxPrivBytes, sigPrivBytes []byte
|
var boxPrivBytes, sigPrivBytes []byte
|
||||||
var boxPrivKey crypto.BoxPrivKey
|
var boxPrivKey crypto.BoxPrivKey
|
||||||
var sigPrivKey crypto.SigPrivKey
|
var sigPrivKey crypto.SigPrivKey
|
||||||
if boxPrivBytes, err = hex.DecodeString(n.config.EncryptionPrivateKey); err != nil {
|
if boxPrivBytes, err = hex.DecodeString(n.config.EncryptionPrivateKey); err != nil {
|
||||||
panic(err)
|
logger.Fatalln("Unable to parse EncryptionPrivateKey:", err)
|
||||||
}
|
}
|
||||||
copy(boxPrivKey[:], boxPrivBytes[:])
|
copy(boxPrivKey[:], boxPrivBytes[:])
|
||||||
if sigPrivBytes, err = hex.DecodeString(n.config.SigningPrivateKey); err != nil {
|
if sigPrivBytes, err = hex.DecodeString(n.config.SigningPrivateKey); err != nil {
|
||||||
panic(err)
|
logger.Fatalln("Unable to parse SigningPrivateKey:", err)
|
||||||
}
|
}
|
||||||
copy(sigPrivKey[:], sigPrivBytes[:])
|
copy(sigPrivKey[:], sigPrivBytes[:])
|
||||||
|
// Now start Yggdrasil - this starts the DHT, router, switch and other core
|
||||||
|
// components needed for Yggdrasil to operate
|
||||||
err = n.core.Start(&boxPrivKey, &sigPrivKey, logger)
|
err = n.core.Start(&boxPrivKey, &sigPrivKey, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorln("An error occurred during startup")
|
logger.Errorln("An error occurred during startup")
|
||||||
|
@ -205,6 +161,7 @@ func main() {
|
||||||
}
|
}
|
||||||
// Start the multicast interface
|
// Start the multicast interface
|
||||||
n.multicast.Init(&n.core, logger, nil)
|
n.multicast.Init(&n.core, logger, nil)
|
||||||
|
n.multicast.SetLinkLocalTCPPort(n.config.LinkLocalTCPPort)
|
||||||
if err := n.multicast.Start(); err != nil {
|
if err := n.multicast.Start(); err != nil {
|
||||||
logger.Errorln("An error occurred starting multicast:", err)
|
logger.Errorln("An error occurred starting multicast:", err)
|
||||||
}
|
}
|
||||||
|
@ -262,65 +219,3 @@ func (n *node) shutdown() {
|
||||||
n.tuntap.Stop()
|
n.tuntap.Stop()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
|
|
||||||
current := n.config
|
|
||||||
|
|
||||||
// Allow by default if the session firewall is disabled
|
|
||||||
if !current.SessionFirewall.Enable {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare for checking whitelist/blacklist
|
|
||||||
var box crypto.BoxPubKey
|
|
||||||
// Reject blacklisted nodes
|
|
||||||
for _, b := range current.SessionFirewall.BlacklistEncryptionPublicKeys {
|
|
||||||
key, err := hex.DecodeString(b)
|
|
||||||
if err == nil {
|
|
||||||
copy(box[:crypto.BoxPubKeyLen], key)
|
|
||||||
if box == *pubkey {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow whitelisted nodes
|
|
||||||
for _, b := range current.SessionFirewall.WhitelistEncryptionPublicKeys {
|
|
||||||
key, err := hex.DecodeString(b)
|
|
||||||
if err == nil {
|
|
||||||
copy(box[:crypto.BoxPubKeyLen], key)
|
|
||||||
if box == *pubkey {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow outbound sessions if appropriate
|
|
||||||
if current.SessionFirewall.AlwaysAllowOutbound {
|
|
||||||
if initiator {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look and see if the pubkey is that of a direct peer
|
|
||||||
var isDirectPeer bool
|
|
||||||
for _, peer := range n.core.GetPeers() {
|
|
||||||
if peer.PublicKey == *pubkey {
|
|
||||||
isDirectPeer = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow direct peers if appropriate
|
|
||||||
if current.SessionFirewall.AllowFromDirect && isDirectPeer {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow remote nodes if appropriate
|
|
||||||
if current.SessionFirewall.AllowFromRemote && !isDirectPeer {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, default-deny if not matching any of the above rules
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
69
cmd/yggdrasil/session.go
Normal file
69
cmd/yggdrasil/session.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
|
||||||
|
current := n.config
|
||||||
|
|
||||||
|
// Allow by default if the session firewall is disabled
|
||||||
|
if !current.SessionFirewall.Enable {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare for checking whitelist/blacklist
|
||||||
|
var box crypto.BoxPubKey
|
||||||
|
// Reject blacklisted nodes
|
||||||
|
for _, b := range current.SessionFirewall.BlacklistEncryptionPublicKeys {
|
||||||
|
key, err := hex.DecodeString(b)
|
||||||
|
if err == nil {
|
||||||
|
copy(box[:crypto.BoxPubKeyLen], key)
|
||||||
|
if box == *pubkey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow whitelisted nodes
|
||||||
|
for _, b := range current.SessionFirewall.WhitelistEncryptionPublicKeys {
|
||||||
|
key, err := hex.DecodeString(b)
|
||||||
|
if err == nil {
|
||||||
|
copy(box[:crypto.BoxPubKeyLen], key)
|
||||||
|
if box == *pubkey {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow outbound sessions if appropriate
|
||||||
|
if current.SessionFirewall.AlwaysAllowOutbound {
|
||||||
|
if initiator {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look and see if the pubkey is that of a direct peer
|
||||||
|
var isDirectPeer bool
|
||||||
|
for _, peer := range n.core.GetPeers() {
|
||||||
|
if peer.PublicKey == *pubkey {
|
||||||
|
isDirectPeer = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow direct peers if appropriate
|
||||||
|
if current.SessionFirewall.AllowFromDirect && isDirectPeer {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow remote nodes if appropriate
|
||||||
|
if current.SessionFirewall.AllowFromRemote && !isDirectPeer {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, default-deny if not matching any of the above rules
|
||||||
|
return false
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue