From 2c3074a979b1d67c5c3060441b437dbe12196044 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 21 Jun 2018 09:53:35 +0100 Subject: [PATCH 1/6] Update build script to strip by default, allow debug -d and UPX -u flags --- build | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/build b/build index d7e31991..7f800c37 100755 --- a/build +++ b/build @@ -1,11 +1,25 @@ #!/bin/sh +while getopts ud option +do + case "${option}" + in + u) UPX=true;; + d) DEBUG=true;; + esac +done export GOPATH=$PWD echo "Downloading..." go get -d -v go get -d -v yggdrasil for file in *.go ; do echo "Building: $file" - go build $@ $file - #go build -ldflags="-s -w" -v $file - #upx --brute ${file/.go/} + #go build $@ $file + if [ $DEBUG ]; then + go build -tags debug -v $file + else + go build -ldflags="-s -w" -v $file + fi + if [ $UPX ]; then + upx --brute ${file/.go/} + fi done From c4d28c4f65075584fdd773eb9732c00a84dcf5fe Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 21 Jun 2018 09:29:05 -0500 Subject: [PATCH 2/6] Update build More portable way to strip the `.go` extension from files when packing with upx. --- build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build b/build index 7f800c37..c07e5eac 100755 --- a/build +++ b/build @@ -20,6 +20,6 @@ for file in *.go ; do go build -ldflags="-s -w" -v $file fi if [ $UPX ]; then - upx --brute ${file/.go/} + upx --brute ${file%.go} fi done From 1a60e89ada6545d60e6c9d78c2d28f2b1b3f510c Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 21 Jun 2018 16:03:46 +0100 Subject: [PATCH 3/6] Add yggdrasilconf for testing with vyatta-yggdrasil --- contrib/config/yggdrasilconf.go | 97 +++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 contrib/config/yggdrasilconf.go diff --git a/contrib/config/yggdrasilconf.go b/contrib/config/yggdrasilconf.go new file mode 100644 index 00000000..12048c3a --- /dev/null +++ b/contrib/config/yggdrasilconf.go @@ -0,0 +1,97 @@ +package main + +/* +This is a small utility that is designed to accompany the vyatta-yggdrasil +package. It takes a HJSON configuration file, makes changes to it based on +the command line arguments, and then spits out an updated file. +*/ + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "strconv" + + "golang.org/x/text/encoding/unicode" + "github.com/neilalexander/hjson-go" + + "yggdrasil/config" +) + +type nodeConfig = config.NodeConfig + +func main() { + useconffile := flag.String("useconffile", "/etc/yggdrasil.conf", "update config at specified file path") + flag.Parse() + cfg := nodeConfig{} + var config []byte + var err error + config, err = ioutil.ReadFile(*useconffile) + if err != nil { + panic(err) + } + if bytes.Compare(config[0:2], []byte{0xFF, 0xFE}) == 0 || + bytes.Compare(config[0:2], []byte{0xFE, 0xFF}) == 0 { + utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM) + decoder := utf.NewDecoder() + config, err = decoder.Bytes(config) + if err != nil { + panic(err) + } + } + var dat map[string]interface{} + if err := hjson.Unmarshal(config, &dat); err != nil { + panic(err) + } + confJson, err := json.Marshal(dat) + if err != nil { + panic(err) + } + json.Unmarshal(confJson, &cfg) + switch flag.Arg(0) { + case "setMTU": + cfg.IfMTU, err = strconv.Atoi(flag.Arg(1)) + if err != nil { + cfg.IfMTU = 1280 + } + if mtu, _ := strconv.Atoi(flag.Arg(1)); mtu < 1280 { + cfg.IfMTU = 1280 + } + case "setIfName": + cfg.IfName = flag.Arg(1) + case "setListen": + cfg.Listen = flag.Arg(1) + case "setAdminListen": + cfg.AdminListen = flag.Arg(1) + case "setIfTapMode": + if flag.Arg(1) == "true" { + cfg.IfTAPMode = true + } else { + cfg.IfTAPMode = false + } + case "addPeer": + found := false + for _, v := range cfg.Peers { + if v == flag.Arg(1) { + found = true + } + } + if !found { + cfg.Peers = append(cfg.Peers, flag.Arg(1)) + } + case "removePeer": + for k, v := range cfg.Peers { + if v == flag.Arg(1) { + cfg.Peers = append(cfg.Peers[:k], cfg.Peers[k+1:]...) + } + } + } + bs, err := hjson.Marshal(cfg) + if err != nil { + panic(err) + } + fmt.Println(string(bs)) + return +} From f599a1a2c159f9feb71aefb140555610b6e37e98 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 21 Jun 2018 10:32:16 -0500 Subject: [PATCH 4/6] start the pprof based on an env variable in debug builds, otherwise remove the flag/release.go stuff --- src/yggdrasil/debug.go | 14 ++++++++++++++ src/yggdrasil/release.go | 14 -------------- yggdrasil.go | 7 ------- 3 files changed, 14 insertions(+), 21 deletions(-) delete mode 100644 src/yggdrasil/release.go diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index 2cf90401..f95bfa3d 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -20,6 +20,20 @@ import "regexp" import _ "net/http/pprof" import "net/http" import "runtime" +import "os" + +// Start the profiler in debug builds, if the required environment variable is set. +func init() { + envVarName := "PPROFLISTEN" + hostPort := os.Getenv(envVarName) + switch { + case hostPort == "": + fmt.Printf("DEBUG: %s not set, profiler not started.\n", envVarName) + default: + fmt.Printf("DEBUG: Starting pprof on %s\n", hostPort) + go func() { fmt.Println(http.ListenAndServe(hostPort, nil)) }() + } +} // Starts the function profiler. This is only supported when built with // '-tags build'. diff --git a/src/yggdrasil/release.go b/src/yggdrasil/release.go deleted file mode 100644 index 3b136904..00000000 --- a/src/yggdrasil/release.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build !debug - -package yggdrasil - -import ( - "errors" - "log" -) - -// Starts the function profiler. This is only supported when built with -// '-tags build'. -func StartProfiler(_ *log.Logger) error { - return errors.New("Release builds do not support -pprof, build using '-tags debug'") -} diff --git a/yggdrasil.go b/yggdrasil.go index d29c65b7..20b4aa08 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -82,7 +82,6 @@ func doGenconf() string { // The main function is responsible for configuring and starting Yggdrasil. func main() { // Configure the command line parameters. - pprof := flag.Bool("pprof", false, "Run pprof, see http://localhost:6060/debug/pprof/") genconf := flag.Bool("genconf", false, "print a new config to stdout") useconf := flag.Bool("useconf", false, "read config from stdin") useconffile := flag.String("useconffile", "", "read config from specified file path") @@ -203,12 +202,6 @@ func main() { } // Create a new logger that logs output to stdout. logger := log.New(os.Stdout, "", log.Flags()) - // If the -pprof flag was provided then start the pprof service on port 6060. - if *pprof { - if err := yggdrasil.StartProfiler(logger); err != nil { - logger.Println(err) - } - } // Setup the Yggdrasil node itself. The node{} type includes a Core, so we // don't need to create this manually. n := node{} From 19014a198eb1a94f884a3a7086dde85f35e9f596 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 21 Jun 2018 10:38:31 -0500 Subject: [PATCH 5/6] randomize the delay after tcp disconnects, to prevent synchronization issues --- src/yggdrasil/tcp.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 5408b6bf..1e62f469 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -17,6 +17,7 @@ package yggdrasil import ( "errors" "fmt" + "math/rand" "net" "sync" "sync/atomic" @@ -112,6 +113,7 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string) { defer func() { // Block new calls for a little while, to mitigate livelock scenarios time.Sleep(tcp_timeout) + time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) iface.mutex.Lock() delete(iface.calls, saddr) iface.mutex.Unlock() From 254be42614a656b53c4aa3ce485d06e4cdc52fd4 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 21 Jun 2018 10:39:43 -0500 Subject: [PATCH 6/6] gofmt --- contrib/config/yggdrasilconf.go | 86 ++++++++++++++++----------------- src/yggdrasil/tcp.go | 4 +- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/contrib/config/yggdrasilconf.go b/contrib/config/yggdrasilconf.go index 12048c3a..bc6e1326 100644 --- a/contrib/config/yggdrasilconf.go +++ b/contrib/config/yggdrasilconf.go @@ -9,13 +9,13 @@ the command line arguments, and then spits out an updated file. import ( "bytes" "encoding/json" - "flag" + "flag" "fmt" "io/ioutil" - "strconv" + "strconv" - "golang.org/x/text/encoding/unicode" "github.com/neilalexander/hjson-go" + "golang.org/x/text/encoding/unicode" "yggdrasil/config" ) @@ -23,8 +23,8 @@ import ( type nodeConfig = config.NodeConfig func main() { - useconffile := flag.String("useconffile", "/etc/yggdrasil.conf", "update config at specified file path") - flag.Parse() + useconffile := flag.String("useconffile", "/etc/yggdrasil.conf", "update config at specified file path") + flag.Parse() cfg := nodeConfig{} var config []byte var err error @@ -50,44 +50,44 @@ func main() { panic(err) } json.Unmarshal(confJson, &cfg) - switch flag.Arg(0) { - case "setMTU": - cfg.IfMTU, err = strconv.Atoi(flag.Arg(1)) - if err != nil { - cfg.IfMTU = 1280 - } - if mtu, _ := strconv.Atoi(flag.Arg(1)); mtu < 1280 { - cfg.IfMTU = 1280 - } - case "setIfName": - cfg.IfName = flag.Arg(1) - case "setListen": - cfg.Listen = flag.Arg(1) - case "setAdminListen": - cfg.AdminListen = flag.Arg(1) - case "setIfTapMode": - if flag.Arg(1) == "true" { - cfg.IfTAPMode = true - } else { - cfg.IfTAPMode = false - } - case "addPeer": - found := false - for _, v := range cfg.Peers { - if v == flag.Arg(1) { - found = true - } - } - if !found { - cfg.Peers = append(cfg.Peers, flag.Arg(1)) - } - case "removePeer": - for k, v := range cfg.Peers { - if v == flag.Arg(1) { - cfg.Peers = append(cfg.Peers[:k], cfg.Peers[k+1:]...) - } - } - } + switch flag.Arg(0) { + case "setMTU": + cfg.IfMTU, err = strconv.Atoi(flag.Arg(1)) + if err != nil { + cfg.IfMTU = 1280 + } + if mtu, _ := strconv.Atoi(flag.Arg(1)); mtu < 1280 { + cfg.IfMTU = 1280 + } + case "setIfName": + cfg.IfName = flag.Arg(1) + case "setListen": + cfg.Listen = flag.Arg(1) + case "setAdminListen": + cfg.AdminListen = flag.Arg(1) + case "setIfTapMode": + if flag.Arg(1) == "true" { + cfg.IfTAPMode = true + } else { + cfg.IfTAPMode = false + } + case "addPeer": + found := false + for _, v := range cfg.Peers { + if v == flag.Arg(1) { + found = true + } + } + if !found { + cfg.Peers = append(cfg.Peers, flag.Arg(1)) + } + case "removePeer": + for k, v := range cfg.Peers { + if v == flag.Arg(1) { + cfg.Peers = append(cfg.Peers[:k], cfg.Peers[k+1:]...) + } + } + } bs, err := hjson.Marshal(cfg) if err != nil { panic(err) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 1e62f469..db57b568 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -17,7 +17,7 @@ package yggdrasil import ( "errors" "fmt" - "math/rand" + "math/rand" "net" "sync" "sync/atomic" @@ -113,7 +113,7 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string) { defer func() { // Block new calls for a little while, to mitigate livelock scenarios time.Sleep(tcp_timeout) - time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) + time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) iface.mutex.Lock() delete(iface.calls, saddr) iface.mutex.Unlock()