From 60549cfa09d4f080a1ae6d9f7d0c7f02237a7140 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 20 Dec 2018 23:49:15 +0000 Subject: [PATCH 1/3] Adds special keyword 'hide' for masking built-in nodeinfo defaults --- src/yggdrasil/nodeinfo.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/yggdrasil/nodeinfo.go b/src/yggdrasil/nodeinfo.go index f525bec..5e71a6e 100644 --- a/src/yggdrasil/nodeinfo.go +++ b/src/yggdrasil/nodeinfo.go @@ -108,9 +108,14 @@ func (m *nodeinfo) setNodeInfo(given interface{}) error { if nodeinfomap, ok := given.(map[string]interface{}); ok { for key, value := range nodeinfomap { if _, ok := newnodeinfo[key]; ok { + if value == "hide" { + delete(newnodeinfo, key) + } continue } - newnodeinfo[key] = value + if value != "hide" { + newnodeinfo[key] = value + } } } if newjson, err := json.Marshal(newnodeinfo); err == nil { From 586deed0f93349f8ea6dd6c8cfb0fb53b1eb1069 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 21 Dec 2018 09:56:34 +0000 Subject: [PATCH 2/3] Add NodeInfoPrivacy option for not including defaults, and also check for null/"null" instead of "hide" --- cmd/yggdrasil/main.go | 1 + src/config/config.go | 1 + src/yggdrasil/core.go | 6 +++--- src/yggdrasil/nodeinfo.go | 19 ++++++++++++------- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go index 5a9db26..2b6d2f0 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/yggdrasil/main.go @@ -71,6 +71,7 @@ func generateConfig(isAutoconf bool) *nodeConfig { cfg.SessionFirewall.AllowFromDirect = true cfg.SessionFirewall.AllowFromRemote = true cfg.SwitchOptions.MaxTotalQueueSize = yggdrasil.SwitchQueueTotalMinSize + cfg.NodeInfoPrivacy = false return &cfg } diff --git a/src/config/config.go b/src/config/config.go index b5a1f89..192f435 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -19,6 +19,7 @@ type NodeConfig struct { SessionFirewall SessionFirewall `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."` TunnelRouting TunnelRouting `comment:"Allow tunneling non-Yggdrasil traffic over Yggdrasil. This effectively\nallows you to use Yggdrasil to route to, or to bridge other networks,\nsimilar to a VPN tunnel. Tunnelling works between any two nodes and\ndoes not require them to be directly peered."` SwitchOptions SwitchOptions `comment:"Advanced options for tuning the switch. Normally you will not need\nto edit these options."` + NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."` NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."` //Net NetConfig `comment:"Extended options for connecting to peers over other networks."` } diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 99330e1..e38274f 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -125,7 +125,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { c.admin.init(c, nc.AdminListen) c.nodeinfo.init(c) - c.nodeinfo.setNodeInfo(nc.NodeInfo) + c.nodeinfo.setNodeInfo(nc.NodeInfo, nc.NodeInfoPrivacy) if err := c.tcp.init(c, nc.Listen, nc.ReadTimeout); err != nil { c.log.Println("Failed to start TCP interface") @@ -248,8 +248,8 @@ func (c *Core) GetNodeInfo() nodeinfoPayload { } // Sets the nodeinfo. -func (c *Core) SetNodeInfo(nodeinfo interface{}) { - c.nodeinfo.setNodeInfo(nodeinfo) +func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) { + c.nodeinfo.setNodeInfo(nodeinfo, nodeinfoprivacy) } // Sets the output logger of the Yggdrasil node after startup. This may be diff --git a/src/yggdrasil/nodeinfo.go b/src/yggdrasil/nodeinfo.go index 5e71a6e..89a90a2 100644 --- a/src/yggdrasil/nodeinfo.go +++ b/src/yggdrasil/nodeinfo.go @@ -96,29 +96,34 @@ func (m *nodeinfo) getNodeInfo() nodeinfoPayload { } // Set the current node's nodeinfo -func (m *nodeinfo) setNodeInfo(given interface{}) error { +func (m *nodeinfo) setNodeInfo(given interface{}, privacy bool) error { m.myNodeInfoMutex.Lock() defer m.myNodeInfoMutex.Unlock() - newnodeinfo := map[string]interface{}{ + defaults := map[string]interface{}{ "buildname": GetBuildName(), "buildversion": GetBuildVersion(), "buildplatform": runtime.GOOS, "buildarch": runtime.GOARCH, } + newnodeinfo := make(map[string]interface{}) + if !privacy { + for k, v := range defaults { + newnodeinfo[k] = v + } + } if nodeinfomap, ok := given.(map[string]interface{}); ok { for key, value := range nodeinfomap { - if _, ok := newnodeinfo[key]; ok { - if value == "hide" { + if _, ok := defaults[key]; ok { + if strvalue, strok := value.(string); strok && strvalue == "null" || value == nil { delete(newnodeinfo, key) } continue } - if value != "hide" { - newnodeinfo[key] = value - } + newnodeinfo[key] = value } } if newjson, err := json.Marshal(newnodeinfo); err == nil { + m.core.log.Println(string(newjson)) if len(newjson) > 16384 { return errors.New("NodeInfo exceeds max length of 16384 bytes") } From f6b00759896c068a4e28865340c723a977778ffa Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 21 Dec 2018 10:04:32 +0000 Subject: [PATCH 3/3] Case-insensitive checking of null if string, don't print the nodeinfo again --- src/yggdrasil/nodeinfo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/nodeinfo.go b/src/yggdrasil/nodeinfo.go index 89a90a2..b907632 100644 --- a/src/yggdrasil/nodeinfo.go +++ b/src/yggdrasil/nodeinfo.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "runtime" + "strings" "sync" "time" @@ -114,7 +115,7 @@ func (m *nodeinfo) setNodeInfo(given interface{}, privacy bool) error { if nodeinfomap, ok := given.(map[string]interface{}); ok { for key, value := range nodeinfomap { if _, ok := defaults[key]; ok { - if strvalue, strok := value.(string); strok && strvalue == "null" || value == nil { + if strvalue, strok := value.(string); strok && strings.EqualFold(strvalue, "null") || value == nil { delete(newnodeinfo, key) } continue @@ -123,7 +124,6 @@ func (m *nodeinfo) setNodeInfo(given interface{}, privacy bool) error { } } if newjson, err := json.Marshal(newnodeinfo); err == nil { - m.core.log.Println(string(newjson)) if len(newjson) > 16384 { return errors.New("NodeInfo exceeds max length of 16384 bytes") }