diff --git a/.gitignore b/.gitignore index 676c272..d28577c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -go.sum etherguard-go etherguard-go-vpp vendor diff --git a/.vscode/launch.json b/.vscode/launch.json index 3892f63..ef84fd7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,7 +12,7 @@ "program": "${workspaceFolder}", "buildFlags": "-tags 'novpp'", "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, - "args":["-config","example_config/super_mode/s1.yaml","-mode","super","-example"], + "args":["-config","example_config/super_mode/s1.yaml","-mode","super"/*,"-example"*/], }, { "name": "Launch Edge", @@ -22,7 +22,17 @@ "program": "${workspaceFolder}", "buildFlags": "-tags 'novpp'", "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, - "args":["-config","example_config/super_mode/n1.yaml","-mode","edge","-example"], + "args":["-config","example_config/super_mode/n1.yaml","-mode","edge"/*,"-example"*/], + } + { + "name": "Launch GenCfg", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}", + "buildFlags": "-tags 'novpp'", + "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, + "args":["-config","example_config/super_mode/gensuper.yaml","-mode","gencfg","-cfgmode","super"/*,"-example"*/], } ] } \ No newline at end of file diff --git a/README_zh.md b/README_zh.md index 2d90360..fa6ef2c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -53,27 +53,10 @@ Usage of ./etherguard-go-vpp: 內建小工具可以快速生成設定檔,搞定私鑰公鑰等等,暫時只支援Super模式 -可以參考下面的配置,但是 `/tmp/test` , `example.com` , `192.168.76.0/24` , `fd95:71cb:a3df:e586::/64` , `fe80::a3df:0/112` 請記得換掉 +首先按需求修改`example_config/super_mode/gensuper.yaml` ``` -$ ./etherguard-go -mode gencfg -cfgmode super -``` -然後按照提示輸入即可 -``` -Config save path (eg_generated_configs) :/tmp/test -SuperConfig template path(optional) : -EdgeTamplatePath template path(optional) : -Network name (eg_net) : -SuperNode ListenPort (12369) : 3456 -EdgeAPI prefix (/eg_net/eg_api) : -IPv4/domain of your supernode (optional) :example.com -IPv6/domain of your supernode (optional) :example.com -URL(use domain would be better) of the EdgeAPI provided by supernode (http://example.com:3456/eg_net/eg_api) : -Number of your nodes :100 -MacAddress Prefix (36:23:DA:2D) : -IPv4 block(optional) :192.168.76.0/24 -IPv6 block(optional) :fd95:71cb:a3df:e586::/64 -IPv6LL block(optional) :fe80::a3df:0/112 +$ ./etherguard-go -mode gencfg -cfgmode super -config example_config/super_mode/gensuper.yaml ``` 順帶一提,最後三個欄位,IP的部分可以直接省略沒關係 @@ -81,6 +64,18 @@ IPv6LL block(optional) :fe80::a3df:0/112 和VPN本身運作完全無關 VPN起來以後,自己手動加ip也行 +把一個super,2個edge分別搬去三台機器 +或是2台機器,super和edge可以是同一台 + +然後在Supernode執行 +``` +./etherguard-go -config [設定檔位置] -mode super +``` +然後在EdgeNode執行 +``` +./etherguard-go -config [設定檔位置] -mode edge +``` + ## Build ### No-vpp version diff --git a/example_config/super_mode/gensuper.yaml b/example_config/super_mode/gensuper.yaml new file mode 100644 index 0000000..60674ce --- /dev/null +++ b/example_config/super_mode/gensuper.yaml @@ -0,0 +1,16 @@ +Config output dir: /tmp/eg_gen +ConfigTemplate for super node: "" +ConfigTemplate for edge node: "" +Network name: eg_net +Super Node: + Listen port: 3456 + EdgeAPI prefix: /eg_net/eg_api + Endpoint(IPv4)(optional): example.com + Endpoint(IPv6)(optional): example.com + Endpoint(EdgeAPI): http://example.com:3456/eg_net/eg_api +Edge Node: + Node IDs: "[1~100]" + MacAddress prefix: "" + IPv4 range: 192.168.76.0/24 + IPv6 range: fd95:71cb:a3df:e586::/64 + IPv6 LL range: fe80::a3df:0/112 \ No newline at end of file diff --git a/example_config/systemd/etherguard-edge.service b/example_config/systemd/etherguard-edge.service index 4a4386f..f1fdb81 100644 --- a/example_config/systemd/etherguard-edge.service +++ b/example_config/systemd/etherguard-edge.service @@ -8,7 +8,7 @@ After=network.target User=root Group=root WorkingDirectory=/etc/eggo -Type=simple +Type=notify ExecStart=etherguard-go -config /etc/eggo/edge.yaml -mode edge Nice=5 diff --git a/example_config/systemd/etherguard-super.service b/example_config/systemd/etherguard-super.service index 77f5265..d030bf2 100644 --- a/example_config/systemd/etherguard-super.service +++ b/example_config/systemd/etherguard-super.service @@ -8,7 +8,7 @@ After=network.target User=nobody Group=nogroup WorkingDirectory=/etc/eggo -Type=simple +Type=notify #ExecStartPre=+chgrp nogroup /var/run/wireguard #ExecStartPre=+chmod 775 /var/run/wireguard ExecStart=etherguard-go -config /etc/eggo/super.yaml -mode super -no-uapi diff --git a/gencfg/example_conf.go b/gencfg/example_conf.go new file mode 100644 index 0000000..41b1994 --- /dev/null +++ b/gencfg/example_conf.go @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved. + */ + +package gencfg + +import ( + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" +) + +func GetExampleEdgeConf(templatePath string) mtypes.EdgeConfig { + tconfig := mtypes.EdgeConfig{} + if templatePath != "" { + err := mtypes.ReadYaml(templatePath, &tconfig) + if err == nil { + return tconfig + } + } + v1 := mtypes.Vertex(1) + v2 := mtypes.Vertex(2) + tconfig = mtypes.EdgeConfig{ + Interface: mtypes.InterfaceConf{ + IType: "tap", + Name: "tap1", + VPPIFaceID: 1, + VPPBridgeID: 4242, + MacAddrPrefix: "AA:BB:CC:DD", + MTU: 1416, + RecvAddr: "127.0.0.1:4001", + SendAddr: "127.0.0.1:5001", + L2HeaderMode: "nochg", + }, + NodeID: 1, + NodeName: "Node01", + PostScript: "", + DefaultTTL: 200, + L2FIBTimeout: 3600, + PrivKey: "6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=", + ListenPort: 0, + LogLevel: mtypes.LoggerInfo{ + LogLevel: "error", + LogTransit: false, + LogControl: true, + LogNormal: false, + LogInternal: true, + LogNTP: true, + }, + DynamicRoute: mtypes.DynamicRouteInfo{ + SendPingInterval: 16, + PeerAliveTimeout: 70, + DupCheckTimeout: 40, + ConnTimeOut: 20, + ConnNextTry: 5, + AdditionalCost: 10, + SaveNewPeers: true, + SuperNode: mtypes.SuperInfo{ + UseSuperNode: true, + PSKey: "iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=", + EndpointV4: "127.0.0.1:3000", + PubKeyV4: "LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=", + EndpointV6: "[::1]:3000", + PubKeyV6: "HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=", + EndpointEdgeAPIUrl: "http://127.0.0.1:3000/eg_api", + SuperNodeInfoTimeout: 50, + SkipLocalIP: false, + }, + P2P: mtypes.P2PInfo{ + UseP2P: false, + SendPeerInterval: 20, + GraphRecalculateSetting: mtypes.GraphRecalculateSetting{ + StaticMode: false, + JitterTolerance: 50, + JitterToleranceMultiplier: 1.1, + DampingResistance: 0.8, + TimeoutCheckInterval: 5, + RecalculateCoolDown: 5, + }, + }, + NTPConfig: mtypes.NTPInfo{ + UseNTP: true, + MaxServerUse: 8, + SyncTimeInterval: 3600, + NTPTimeout: 3, + Servers: []string{ + "time.google.com", + "time1.google.com", + "time2.google.com", + "time3.google.com", + "time4.google.com", + "time1.facebook.com", + "time2.facebook.com", + "time3.facebook.com", + "time4.facebook.com", + "time5.facebook.com", + "time.cloudflare.com", + "time.apple.com", + "time.asia.apple.com", + "time.euro.apple.com", + "time.windows.com", + "pool.ntp.org", + "0.pool.ntp.org", + "1.pool.ntp.org", + "2.pool.ntp.org", + "3.pool.ntp.org", + }, + }, + }, + NextHopTable: mtypes.NextHopTable{ + mtypes.Vertex(1): { + mtypes.Vertex(2): &v2, + }, + mtypes.Vertex(2): { + mtypes.Vertex(1): &v1, + }, + }, + ResetConnInterval: 86400, + Peers: []mtypes.PeerInfo{ + { + NodeID: 2, + PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=", + PSKey: "juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs=", + EndPoint: "127.0.0.1:3002", + Static: true, + }, + }, + } + g := path.NewGraph(3, false, tconfig.DynamicRoute.P2P.GraphRecalculateSetting, tconfig.DynamicRoute.NTPConfig, mtypes.LoggerInfo{}) + + g.UpdateLatency(1, 2, 0.5, 99999, 0, false, false) + g.UpdateLatency(2, 1, 0.5, 99999, 0, false, false) + g.UpdateLatency(2, 3, 0.5, 99999, 0, false, false) + g.UpdateLatency(3, 2, 0.5, 99999, 0, false, false) + g.UpdateLatency(2, 4, 0.5, 99999, 0, false, false) + g.UpdateLatency(4, 2, 0.5, 99999, 0, false, false) + g.UpdateLatency(3, 4, 0.5, 99999, 0, false, false) + g.UpdateLatency(4, 3, 0.5, 99999, 0, false, false) + g.UpdateLatency(5, 3, 0.5, 99999, 0, false, false) + g.UpdateLatency(3, 5, 0.5, 99999, 0, false, false) + g.UpdateLatency(6, 4, 0.5, 99999, 0, false, false) + g.UpdateLatency(4, 6, 0.5, 99999, 0, false, false) + _, next, _ := g.FloydWarshall(false) + tconfig.NextHopTable = next + return tconfig +} + +func GetExampleSuperConf(templatePath string) mtypes.SuperConfig { + sconfig := mtypes.SuperConfig{} + if templatePath != "" { + err := mtypes.ReadYaml(templatePath, &sconfig) + if err == nil { + return sconfig + } + } + + v1 := mtypes.Vertex(1) + v2 := mtypes.Vertex(2) + + random_passwd := mtypes.RandomStr(8, "passwd") + + sconfig = mtypes.SuperConfig{ + NodeName: "NodeSuper", + PostScript: "", + PrivKeyV4: "mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=", + PrivKeyV6: "+EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=", + ListenPort: 3000, + ListenPort_EdgeAPI: "3000", + ListenPort_ManageAPI: "3000", + API_Prefix: "/eg_api", + LogLevel: mtypes.LoggerInfo{ + LogLevel: "normal", + LogTransit: false, + LogControl: true, + LogNormal: false, + LogInternal: true, + LogNTP: true, + }, + RePushConfigInterval: 30, + PeerAliveTimeout: 70, + HttpPostInterval: 50, + SendPingInterval: 15, + Passwords: mtypes.Passwords{ + ShowState: random_passwd + "_showstate", + AddPeer: random_passwd + "_addpeer", + DelPeer: random_passwd + "_delpeer", + UpdatePeer: random_passwd + "_updatepeer", + UpdateSuper: random_passwd + "_updatesuper", + }, + GraphRecalculateSetting: mtypes.GraphRecalculateSetting{ + StaticMode: false, + JitterTolerance: 50, + JitterToleranceMultiplier: 1.01, + DampingResistance: 0.8, + TimeoutCheckInterval: 5, + RecalculateCoolDown: 5, + }, + NextHopTable: mtypes.NextHopTable{ + mtypes.Vertex(1): { + mtypes.Vertex(2): &v2, + }, + mtypes.Vertex(2): { + mtypes.Vertex(1): &v1, + }, + }, + EdgeTemplate: "example_config/super_mode/n1.yaml", + UsePSKForInterEdge: true, + Peers: []mtypes.SuperPeerInfo{ + { + NodeID: 1, + Name: "Node_01", + PubKey: "ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I=", + PSKey: "iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=", + AdditionalCost: 10, + }, + { + NodeID: 2, + Name: "Node_02", + PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=", + PSKey: "juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs=", + AdditionalCost: 10, + }, + }, + } + return sconfig +} diff --git a/gencfg/gencfgPM.go b/gencfg/gencfgPM.go new file mode 100644 index 0000000..e70cc05 --- /dev/null +++ b/gencfg/gencfgPM.go @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved. + */ + + package gencfg + + \ No newline at end of file diff --git a/gencfg/gencfgSM.go b/gencfg/gencfgSM.go new file mode 100644 index 0000000..57c477d --- /dev/null +++ b/gencfg/gencfgSM.go @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved. + */ + +package gencfg + +import ( + "bufio" + "fmt" + "io/ioutil" + "math" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/device" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/tap" + yaml "gopkg.in/yaml.v2" +) + +var gencfg_reader *bufio.Reader + +func readFLn(promptF string, checkFn func(string) error, defaultAns func() string, args ...interface{}) string { + defaultans := defaultAns() + if defaultans != "" { + fmt.Printf(promptF+" ("+defaultans+") :", args...) + } else { + fmt.Printf(promptF+" :", args...) + } + text, err := gencfg_reader.ReadString('\n') + if err != nil { + panic(err) + } + text = strings.Replace(text, "\n", "", -1) + if text == "" { + text = defaultans + } + if err := checkFn(text); err != nil { + fmt.Println(err) + return readFLn(promptF, checkFn, defaultAns, args...) + } + return text +} + +func ParseIDs(s string) ([]int, int, int, error) { + ret := make([]int, 0) + if len(s) <= 3 { + return ret, 0, 0, fmt.Errorf("Parse Error: %v", s) + } + if s[0] != '[' { + return ret, 0, 0, fmt.Errorf("Parse Error: %v", s) + } + if s[len(s)-1] != ']' { + return ret, 0, 0, fmt.Errorf("Parse Error: %v", s) + } + s = s[1 : len(s)-1] + as := strings.Split(s, ",") + min := math.MaxUint16 + max := 0 + for i, es := range as { + if strings.Contains(es, "~") { + esl := strings.SplitN(es, "~", 2) + si, err := strconv.ParseInt(esl[0], 10, 16) + if err != nil { + return ret, min, max, err + } + ei, err := strconv.ParseInt(esl[1], 10, 16) + if err != nil { + return ret, min, max, err + } + if si >= ei { + return ret, min, max, fmt.Errorf("end %v must > start %v", ei, si) + } + if int(si) < 0 { + return ret, min, max, fmt.Errorf("node ID < 0 at element %v", i) + } + if min > int(si) { + min = int(si) + } + if int(si) < max { + return ret, min, max, fmt.Errorf("list out of order at the %vth element: %v", i, es) + } else if int(si) == max { + return ret, min, max, fmt.Errorf("duplicate id in the %vth element: %v", i, es) + } + max = int(ei) + for ; si <= ei; si++ { + ret = append(ret, int(si)) + } + } else { + si, err := strconv.ParseInt(es, 10, 16) + if err != nil { + return ret, min, max, err + } + if int(si) < max { + return ret, min, max, fmt.Errorf("List out of order at the %vth element!", i) + } else if int(si) == max { + return ret, min, max, fmt.Errorf("duplicate id in the %vth element", i) + } + if min > int(si) { + min = int(si) + } + max = int(si) + ret = append(ret, int(si)) + } + } + return ret, min, max, nil +} + +func printExampleSMCfg() { + tconfig := SMCfg{} + toprint, _ := yaml.Marshal(tconfig) + fmt.Print(string(toprint)) +} + +func GenSuperCfg(SMCinfigPath string, printExample bool) (err error) { + SMCfg := SMCfg{} + if printExample { + printExampleSMCfg() + return + } + err = mtypes.ReadYaml(SMCinfigPath, &SMCfg) + if err != nil { + return err + } + + s := SMCfg.ConfigOutputDir + err = os.MkdirAll(s, 0o700) + if err != nil { + return err + } + files, err := os.ReadDir(s) + if err != nil { + return err + } + if len(files) > 0 { + return fmt.Errorf(s + " not empty") + } + + CfgSavePath := s + + s = SMCfg.SuperConfigTemplate + if s != "" { + var sconfig mtypes.SuperConfig + err = mtypes.ReadYaml(s, &sconfig) + if err != nil { + fmt.Printf("Error read config: %v\t%v\n", s, err) + return err + } + } + + SuperTamplatePath := s + + s = SMCfg.EdgeConfigTemplate + if s != "" { + var econfig mtypes.EdgeConfig + err = mtypes.ReadYaml(s, &econfig) + if err != nil { + fmt.Printf("Error read config: %v\t%v\n", s, err) + return err + } + } + EdgeTamplatePath := s + + sconfig := GetExampleSuperConf(SuperTamplatePath) + + s = SMCfg.NetworkName + + if len(s) > 10 { + return fmt.Errorf("Name too long") + } + allowed := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" + for _, c := range []byte(s) { + if strings.Contains(allowed, string(c)) == false { + return fmt.Errorf("Name can only contain %v", allowed) + } + } + + NetworkName := s + + ListenPort := fmt.Sprintf("%v", SMCfg.Supernode.ListenPort) + + API_Prefix := SMCfg.Supernode.EdgeAPI_Prefix + s = SMCfg.Supernode.EndpointV4 + if s != "" { + _, err = conn.LookupIP(s+":"+ListenPort, 4) + if err != nil { + return err + } + + } + EndpointV4 := s + s = SMCfg.Supernode.EndpointV6 + if s != "" { + if strings.Contains(s, ":") && (s[0] != '[' || s[len(s)-1] != ']') { + return fmt.Errorf("Invalid IPv6 format, please use [%v] instead", s) + } + _, err = conn.LookupIP(s+":"+ListenPort, 6) + if err != nil { + return + } + } else if EndpointV4 == "" { + return fmt.Errorf("Muse provide at lease v4 v6 address") + } + + EndpointV6 := s + + EndpointEdgeAPIUrl := SMCfg.Supernode.Endpoint_EdgeAPI + + sconfig.NodeName = NetworkName + "SP" + sconfig.API_Prefix = API_Prefix + sconfig.ListenPort, _ = strconv.Atoi(ListenPort) + sconfig.ListenPort_EdgeAPI = ListenPort + sconfig.ListenPort_ManageAPI = ListenPort + sconfig.NextHopTable = make(mtypes.NextHopTable) + sconfig.EdgeTemplate = EdgeTamplatePath + + NodeIDs, _, ModeIDmax, err := ParseIDs(SMCfg.EdgeNode.NodeIDs) + if err != nil { + return + } + s = SMCfg.EdgeNode.MacPrefix + + if s != "" { + _, err = tap.GetMacAddr(s, uint32(ModeIDmax)) + if err != nil { + return err + } + } else { + pbyte := mtypes.RandomBytes(4, []byte{0xaa, 0xbb, 0xcc, 0xdd}) + pbyte[0] &^= 0b00000001 + pbyte[0] |= 0b00000010 + s = fmt.Sprintf("%X:%X:%X:%X", pbyte[0], pbyte[1], pbyte[2], pbyte[3]) + } + MacPrefix := s + s = SMCfg.EdgeNode.IPv4Range + if s != "" { + _, _, err = tap.GetIP(4, s, uint32(ModeIDmax)) + if err != nil { + return err + } + } + IPv4Block := s + + s = SMCfg.EdgeNode.IPv6Range + if s != "" { + _, _, err = tap.GetIP(6, s, uint32(ModeIDmax)) + if err != nil { + return err + } + } + IPv6Block := s + + s = SMCfg.EdgeNode.IPv6LLRange + if s != "" { + _, _, err = tap.GetIP(6, s, uint32(ModeIDmax)) + if err != nil { + return err + } + } + IPv6LLBlock := s + + SuperPeerInfo := make([]mtypes.SuperPeerInfo, 0, ModeIDmax) + PrivKeyS4 := device.NoisePrivateKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) + PubKeyS4 := PrivKeyS4.PublicKey() + PrivKeyS6 := device.NoisePrivateKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) + PubKeyS6 := PrivKeyS6.PublicKey() + sconfig.PrivKeyV4 = PrivKeyS4.ToString() + sconfig.PrivKeyV6 = PrivKeyS6.ToString() + allec := make(map[mtypes.Vertex]mtypes.EdgeConfig) + peerceconf := GetExampleEdgeConf(EdgeTamplatePath) + peerceconf.Peers = []mtypes.PeerInfo{} + peerceconf.NextHopTable = make(mtypes.NextHopTable) + for _, ii := range NodeIDs { + i := mtypes.Vertex(ii) + PSKeyE := device.NoisePresharedKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) + PrivKeyE := device.NoisePrivateKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) + PubKeyE := PrivKeyE.PublicKey() + idstr := fmt.Sprintf("%0"+strconv.Itoa(len(strconv.Itoa(ModeIDmax)))+"d", i) + + allec[i] = peerceconf + peerceconf.DynamicRoute.SuperNode.EndpointV4 = EndpointV4 + ":" + ListenPort + peerceconf.DynamicRoute.SuperNode.EndpointV6 = EndpointV6 + ":" + ListenPort + peerceconf.DynamicRoute.SuperNode.EndpointEdgeAPIUrl = EndpointEdgeAPIUrl + peerceconf.Interface.MacAddrPrefix = MacPrefix + peerceconf.Interface.IPv4CIDR = IPv4Block + peerceconf.Interface.IPv6CIDR = IPv6Block + peerceconf.Interface.IPv6LLPrefix = IPv6LLBlock + + peerceconf.NodeID = i + peerceconf.NodeName = NetworkName + idstr + peerceconf.Interface.Name = NetworkName + idstr + peerceconf.DynamicRoute.SuperNode.PubKeyV4 = PubKeyS4.ToString() + peerceconf.DynamicRoute.SuperNode.PubKeyV6 = PubKeyS6.ToString() + peerceconf.DynamicRoute.SuperNode.PSKey = PSKeyE.ToString() + peerceconf.PrivKey = PrivKeyE.ToString() + + SuperPeerInfo = append(SuperPeerInfo, mtypes.SuperPeerInfo{ + NodeID: i, + Name: NetworkName + idstr, + PubKey: PubKeyE.ToString(), + PSKey: PSKeyE.ToString(), + AdditionalCost: peerceconf.DynamicRoute.AdditionalCost, + SkipLocalIP: peerceconf.DynamicRoute.SuperNode.SkipLocalIP, + }) + mtypesBytes, _ := yaml.Marshal(peerceconf) + ioutil.WriteFile(filepath.Join(CfgSavePath, NetworkName+"_edge"+idstr+".yaml"), mtypesBytes, 0o600) + fmt.Println(filepath.Join(CfgSavePath, NetworkName+"_edge"+idstr+".yaml")) + } + sconfig.Peers = SuperPeerInfo + mtypesBytes, _ := yaml.Marshal(sconfig) + ioutil.WriteFile(filepath.Join(CfgSavePath, NetworkName+"_super.yaml"), mtypesBytes, 0o600) + fmt.Println(filepath.Join(CfgSavePath, NetworkName+"_super.yaml")) + return nil +} diff --git a/gencfg/types.go b/gencfg/types.go new file mode 100644 index 0000000..750f3e3 --- /dev/null +++ b/gencfg/types.go @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved. + */ + +package gencfg + +type SMCfg struct { + ConfigOutputDir string `yaml:"Config output dir"` + SuperConfigTemplate string `yaml:"ConfigTemplate for super node"` + EdgeConfigTemplate string `yaml:"ConfigTemplate for edge node"` + NetworkName string `yaml:"Network name"` + Supernode struct { + ListenPort int `yaml:"Listen port"` + EdgeAPI_Prefix string `yaml:"EdgeAPI prefix"` + EndpointV4 string `yaml:"Endpoint(IPv4)(optional)"` + EndpointV6 string `yaml:"Endpoint(IPv6)(optional)"` + Endpoint_EdgeAPI string `yaml:"Endpoint(EdgeAPI)"` + } `yaml:"Super Node"` + EdgeNode struct { + NodeIDs string `yaml:"Node IDs"` + MacPrefix string `yaml:"MacAddress prefix"` + IPv4Range string `yaml:"IPv4 range"` + IPv6Range string `yaml:"IPv6 range"` + IPv6LLRange string `yaml:"IPv6 LL range"` + } `yaml:"Edge Node"` +} + +type PMG struct { + ConfigOutputDir string `yaml:"Config output dir"` + EdgeConfigTemplate string `yaml:"ConfigTemplate for edge node"` + NetworkName string `yaml:"Network name"` + EdgeNodes []struct { + NodeID string `yaml:"Node ID"` + Endpoint string `yaml:"Endpoint(optional)"` + } `yaml:"Edge Nodes"` + DistanceMatrix string `yaml:"Distance matrix for all nodes"` +} diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e5f5a40 --- /dev/null +++ b/go.sum @@ -0,0 +1,86 @@ +git.fd.io/govpp.git v0.3.6-0.20210927044411-385ccc0d8ba9 h1:QFHVGWCWf6e226vMy1zU614eC3glrfJO2CwREUk8D6s= +git.fd.io/govpp.git v0.3.6-0.20210927044411-385ccc0d8ba9/go.mod h1:OCVd4W8SH+666KRQoMj6PM+oipLDZAHhqMz9B1TGbgI= +git.fd.io/govpp.git/extras v0.0.0-20211129071605-0a0c03d45954 h1:F4tLgA7dY1lY1GQ6D7dMiLie39FV6QXinM7BU9cRENY= +git.fd.io/govpp.git/extras v0.0.0-20211129071605-0a0c03d45954/go.mod h1:GhryuN3x7qZ/wYLlEiPUVi6glJvh5S5V6E+XASV4774= +github.com/KusakabeSi/go-cache v0.0.0-20210823132304-22b5b1d22b41 h1:o6o1+n8vqD/Qsxw26x7aLH6QQzPGGmQdKQqQRpkA/ac= +github.com/KusakabeSi/go-cache v0.0.0-20210823132304-22b5b1d22b41/go.mod h1:u+fcGXuY9eUnv1Lw58RgBJcfNxv8rT2jHNI3tdDUHp0= +github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw= +github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= +github.com/bennyscetbun/jsongo v1.1.0/go.mod h1:suxbVmjBV8+A2BBAM5EYVh6Uj8j3rqJhzWf3hv7Ff8U= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ftrvxmtrx/fd v0.0.0-20150925145434-c6d800382fff/go.mod h1:yUhRXHewUVJ1k89wHKP68xfzk7kwXUx/DV1nx4EBMbw= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lunixbochs/struc v0.0.0-20200521075829-a4cb8d33dbbe h1:ewr1srjRCmcQogPQ/NCx6XCk6LGVmsVCc9Y3vvPZj+Y= +github.com/lunixbochs/struc v0.0.0-20200521075829-a4cb8d33dbbe/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.1.0 h1:e3YP4dN/HYPpGh29X1ZkcxcEICsOls9huyVCRBaxjq8= +github.com/onsi/gomega v1.1.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/wk8/go-ordered-map v0.2.0 h1:KlvGyHstD1kkGZkPtHCyCfRYS0cz84uk6rrW/Dnhdtk= +github.com/wk8/go-ordered-map v0.2.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8= +golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index dac92e1..8cbebe3 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,6 @@ package main import ( "flag" "fmt" - "io/ioutil" "os" "runtime" "syscall" @@ -16,10 +15,10 @@ import ( nonSecureRand "math/rand" + "github.com/KusakabeSi/EtherGuard-VPN/gencfg" "github.com/KusakabeSi/EtherGuard-VPN/ipc" "github.com/KusakabeSi/EtherGuard-VPN/path" "github.com/KusakabeSi/EtherGuard-VPN/tap" - yaml "gopkg.in/yaml.v2" ) const ( @@ -36,15 +35,6 @@ func printUsage() { fmt.Printf("Usage: %s -s/c CONFIG-PATH\n", os.Args[0]) } -func readYaml(filePath string, out interface{}) (err error) { - yamlFile, err := ioutil.ReadFile(filePath) - if err != nil { - return - } - err = yaml.Unmarshal(yamlFile, out) - return -} - var ( tconfig = flag.String("config", "", "Config path for the interface.") mode = flag.String("mode", "", "Running mode. [super|edge|solve|gencfg]") @@ -84,9 +74,9 @@ func main() { case "gencfg": switch *cfgmode { case "super": - err = genSuperCfg() + err = gencfg.GenSuperCfg(*tconfig, *printExample) default: - err = fmt.Errorf("gencfg: generate config for %v mode are not implement.", *cfgmode) + err = fmt.Errorf("gencfg: generate config for %v mode are not implement", *cfgmode) } default: diff --git a/main_edge.go b/main_edge.go index 94f7d35..0ea7dad 100644 --- a/main_edge.go +++ b/main_edge.go @@ -19,6 +19,7 @@ import ( "github.com/KusakabeSi/EtherGuard-VPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/device" + "github.com/KusakabeSi/EtherGuard-VPN/gencfg" "github.com/KusakabeSi/EtherGuard-VPN/mtypes" "github.com/KusakabeSi/EtherGuard-VPN/path" "github.com/KusakabeSi/EtherGuard-VPN/tap" @@ -26,145 +27,11 @@ import ( ) func printExampleEdgeConf() { - tconfig := getExampleEdgeConf("") + tconfig := gencfg.GetExampleEdgeConf("") toprint, _ := yaml.Marshal(tconfig) fmt.Print(string(toprint)) } -func getExampleEdgeConf(templatePath string) mtypes.EdgeConfig { - tconfig := mtypes.EdgeConfig{} - if templatePath != "" { - err := readYaml(templatePath, &tconfig) - if err == nil { - return tconfig - } - } - v1 := mtypes.Vertex(1) - v2 := mtypes.Vertex(2) - tconfig = mtypes.EdgeConfig{ - Interface: mtypes.InterfaceConf{ - IType: "tap", - Name: "tap1", - VPPIFaceID: 1, - VPPBridgeID: 4242, - MacAddrPrefix: "AA:BB:CC:DD", - MTU: 1416, - RecvAddr: "127.0.0.1:4001", - SendAddr: "127.0.0.1:5001", - L2HeaderMode: "nochg", - }, - NodeID: 1, - NodeName: "Node01", - PostScript: "", - DefaultTTL: 200, - L2FIBTimeout: 3600, - PrivKey: "6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=", - ListenPort: 0, - LogLevel: mtypes.LoggerInfo{ - LogLevel: "error", - LogTransit: false, - LogControl: true, - LogNormal: false, - LogInternal: true, - LogNTP: true, - }, - DynamicRoute: mtypes.DynamicRouteInfo{ - SendPingInterval: 16, - PeerAliveTimeout: 70, - DupCheckTimeout: 40, - ConnTimeOut: 20, - ConnNextTry: 5, - AdditionalCost: 10, - SaveNewPeers: true, - SuperNode: mtypes.SuperInfo{ - UseSuperNode: true, - PSKey: "iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=", - EndpointV4: "127.0.0.1:3000", - PubKeyV4: "LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=", - EndpointV6: "[::1]:3000", - PubKeyV6: "HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=", - EndpointEdgeAPIUrl: "http://127.0.0.1:3000/eg_api", - SuperNodeInfoTimeout: 50, - SkipLocalIP: false, - }, - P2P: mtypes.P2PInfo{ - UseP2P: false, - SendPeerInterval: 20, - GraphRecalculateSetting: mtypes.GraphRecalculateSetting{ - StaticMode: false, - JitterTolerance: 20, - JitterToleranceMultiplier: 1.1, - TimeoutCheckInterval: 5, - RecalculateCoolDown: 5, - }, - }, - NTPConfig: mtypes.NTPInfo{ - UseNTP: true, - MaxServerUse: 8, - SyncTimeInterval: 3600, - NTPTimeout: 3, - Servers: []string{ - "time.google.com", - "time1.google.com", - "time2.google.com", - "time3.google.com", - "time4.google.com", - "time1.facebook.com", - "time2.facebook.com", - "time3.facebook.com", - "time4.facebook.com", - "time5.facebook.com", - "time.cloudflare.com", - "time.apple.com", - "time.asia.apple.com", - "time.euro.apple.com", - "time.windows.com", - "pool.ntp.org", - "0.pool.ntp.org", - "1.pool.ntp.org", - "2.pool.ntp.org", - "3.pool.ntp.org", - }, - }, - }, - NextHopTable: mtypes.NextHopTable{ - mtypes.Vertex(1): { - mtypes.Vertex(2): &v2, - }, - mtypes.Vertex(2): { - mtypes.Vertex(1): &v1, - }, - }, - ResetConnInterval: 86400, - Peers: []mtypes.PeerInfo{ - { - NodeID: 2, - PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=", - PSKey: "juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs=", - EndPoint: "127.0.0.1:3002", - Static: true, - }, - }, - } - g := path.NewGraph(3, false, tconfig.DynamicRoute.P2P.GraphRecalculateSetting, tconfig.DynamicRoute.NTPConfig, mtypes.LoggerInfo{}) - - g.UpdateLatency(1, 2, 0.5, 99999, 0, false, false) - g.UpdateLatency(2, 1, 0.5, 99999, 0, false, false) - g.UpdateLatency(2, 3, 0.5, 99999, 0, false, false) - g.UpdateLatency(3, 2, 0.5, 99999, 0, false, false) - g.UpdateLatency(2, 4, 0.5, 99999, 0, false, false) - g.UpdateLatency(4, 2, 0.5, 99999, 0, false, false) - g.UpdateLatency(3, 4, 0.5, 99999, 0, false, false) - g.UpdateLatency(4, 3, 0.5, 99999, 0, false, false) - g.UpdateLatency(5, 3, 0.5, 99999, 0, false, false) - g.UpdateLatency(3, 5, 0.5, 99999, 0, false, false) - g.UpdateLatency(6, 4, 0.5, 99999, 0, false, false) - g.UpdateLatency(4, 6, 0.5, 99999, 0, false, false) - _, next, _ := g.FloydWarshall(false) - tconfig.NextHopTable = next - return tconfig -} - func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (err error) { if printExample { printExampleEdgeConf() @@ -174,7 +41,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( //printExampleConf() //return - err = readYaml(configPath, &econfig) + err = mtypes.ReadYaml(configPath, &econfig) if err != nil { fmt.Printf("Error read config: %v\t%v\n", configPath, err) return err diff --git a/main_gencfg.go b/main_gencfg.go deleted file mode 100644 index d9f62dd..0000000 --- a/main_gencfg.go +++ /dev/null @@ -1,229 +0,0 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved. - */ - -package main - -import ( - "bufio" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/KusakabeSi/EtherGuard-VPN/conn" - "github.com/KusakabeSi/EtherGuard-VPN/device" - "github.com/KusakabeSi/EtherGuard-VPN/mtypes" - "github.com/KusakabeSi/EtherGuard-VPN/tap" - yaml "gopkg.in/yaml.v2" -) - -var gencfg_reader *bufio.Reader - -func readFLn(promptF string, checkFn func(string) error, defaultAns func() string, args ...interface{}) string { - defaultans := defaultAns() - if defaultans != "" { - fmt.Printf(promptF+" ("+defaultans+") :", args...) - } else { - fmt.Printf(promptF+" :", args...) - } - text, err := gencfg_reader.ReadString('\n') - if err != nil { - panic(err) - } - text = strings.Replace(text, "\n", "", -1) - if text == "" { - text = defaultans - } - if err := checkFn(text); err != nil { - fmt.Println(err) - return readFLn(promptF, checkFn, defaultAns, args...) - } - return text -} - -func genSuperCfg() error { - gencfg_reader = bufio.NewReader(os.Stdin) - - noCheck := func(string) error { - return nil - } - - noDefault := func() string { - return "" - } - - CfgSavePath := readFLn("Config save path", func(s string) (err error) { - err = os.MkdirAll(s, 0o700) - if err != nil { - return - } - files, err := os.ReadDir(s) - if err != nil { - return - } - if len(files) > 0 { - return fmt.Errorf(s + " not empty") - } - return - }, func() string { return filepath.Join(".", "eg_generated_configs") }) - SuperTamplatePath := readFLn("SuperConfig template path(optional)", func(s string) (err error) { - if s != "" { - var sconfig mtypes.SuperConfig - err = readYaml(s, &sconfig) - if err != nil { - fmt.Printf("Error read config: %v\t%v\n", s, err) - return err - } - } - return - }, noDefault) - EdgeTamplatePath := readFLn("EdgeTamplatePath template path(optional)", func(s string) (err error) { - if s != "" { - var econfig mtypes.EdgeConfig - err = readYaml(s, &econfig) - if err != nil { - fmt.Printf("Error read config: %v\t%v\n", s, err) - return err - } - } - return - }, noDefault) - - sconfig := getExampleSuperConf(SuperTamplatePath) - - NetworkName := readFLn("Network name", func(s string) (err error) { - if len(s) > 10 { - return fmt.Errorf("Name too long") - } - allowed := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" - for _, c := range []byte(s) { - if strings.Contains(allowed, string(c)) == false { - return fmt.Errorf("Name can only contain %v", allowed) - } - } - return - }, func() string { return "eg_net" }) - - ListenPort := readFLn("SuperNode ListenPort", func(s string) (err error) { - _, err = strconv.ParseUint(s, 10, 16) - return - }, func() string { return "12369" }) - - API_Prefix := readFLn("EdgeAPI prefix", noCheck, func() string { return "/" + NetworkName + "/eg_api" }) - EndpointV4 := readFLn("IPv4/domain of your supernode (optional)", func(s string) (err error) { - if s != "" { - _, err = conn.LookupIP(s+":"+ListenPort, 4) - } - return - }, noDefault) - EndpointV6 := readFLn("IPv6/domain of your supernode (optional)", func(s string) (err error) { - if s != "" { - if strings.Contains(s, ":") && (s[0] != '[' || s[len(s)-1] != ']') { - return fmt.Errorf("Invalid IPv6 format, please use [%v] instead", s) - } - _, err = conn.LookupIP(s+":"+ListenPort, 6) - } else if EndpointV4 == "" { - return fmt.Errorf("Muse provide at lease v4 v6 address") - } - return - }, noDefault) - EndpointEdgeAPIUrl := readFLn("URL(use domain would be better) of the EdgeAPI provided by supernode", noCheck, func() string { return fmt.Sprintf("http://%v:%v%v", EndpointV4, ListenPort, API_Prefix) }) - - sconfig.NodeName = NetworkName + "SP" - sconfig.API_Prefix = API_Prefix - sconfig.ListenPort, _ = strconv.Atoi(ListenPort) - sconfig.ListenPort_EdgeAPI = ListenPort - sconfig.ListenPort_ManageAPI = ListenPort - sconfig.NextHopTable = make(mtypes.NextHopTable) - sconfig.EdgeTemplate = EdgeTamplatePath - - NodeNum := readFLn("Number of your nodes", func(s string) (err error) { - _, err = strconv.ParseInt(s, 10, 16) - return - }, noDefault) - MaxNode, _ := strconv.ParseInt(NodeNum, 10, 16) - - MacPrefix := readFLn("MacAddress Prefix", func(s string) (err error) { - _, err = tap.GetMacAddr(s, uint32(MaxNode)) - return - }, func() string { - pbyte := mtypes.RandomBytes(4, []byte{0xaa, 0xbb, 0xcc, 0xdd}) - pbyte[0] &^= 0b00000001 - pbyte[0] |= 0b00000010 - return fmt.Sprintf("%X:%X:%X:%X", pbyte[0], pbyte[1], pbyte[2], pbyte[3]) - }) - IPv4Block := readFLn("IPv4 block(optional)", func(s string) (err error) { - if s != "" { - _, _, err = tap.GetIP(4, s, uint32(MaxNode)) - } - return err - }, noDefault) - IPv6Block := readFLn("IPv6 block(optional)", func(s string) (err error) { - if s != "" { - _, _, err = tap.GetIP(6, s, uint32(MaxNode)) - } - return err - }, noDefault) - IPv6LLBlock := readFLn("IPv6LL block(optional)", func(s string) (err error) { - if s != "" { - _, _, err = tap.GetIP(6, s, uint32(MaxNode)) - } - return err - }, noDefault) - - SuperPeerInfo := make([]mtypes.SuperPeerInfo, 0, MaxNode) - PrivKeyS4 := device.NoisePrivateKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) - PubKeyS4 := PrivKeyS4.PublicKey() - PrivKeyS6 := device.NoisePrivateKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) - PubKeyS6 := PrivKeyS6.PublicKey() - sconfig.PrivKeyV4 = PrivKeyS4.ToString() - sconfig.PrivKeyV6 = PrivKeyS6.ToString() - allec := make(map[mtypes.Vertex]mtypes.EdgeConfig) - peerceconf := getExampleEdgeConf(EdgeTamplatePath) - peerceconf.Peers = []mtypes.PeerInfo{} - peerceconf.NextHopTable = make(mtypes.NextHopTable) - for i := mtypes.Vertex(1); i <= mtypes.Vertex(MaxNode); i++ { - PSKeyE := device.NoisePresharedKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) - PrivKeyE := device.NoisePrivateKey(mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte{}))) - PubKeyE := PrivKeyE.PublicKey() - idstr := fmt.Sprintf("%0"+strconv.Itoa(len(NodeNum))+"d", i) - - allec[i] = peerceconf - peerceconf.DynamicRoute.SuperNode.EndpointV4 = EndpointV4 + ":" + ListenPort - peerceconf.DynamicRoute.SuperNode.EndpointV6 = EndpointV6 + ":" + ListenPort - peerceconf.DynamicRoute.SuperNode.EndpointEdgeAPIUrl = EndpointEdgeAPIUrl - peerceconf.Interface.MacAddrPrefix = MacPrefix - peerceconf.Interface.IPv4CIDR = IPv4Block - peerceconf.Interface.IPv6CIDR = IPv6Block - peerceconf.Interface.IPv6LLPrefix = IPv6LLBlock - - peerceconf.NodeID = i - peerceconf.NodeName = NetworkName + idstr - peerceconf.Interface.Name = NetworkName + idstr - peerceconf.DynamicRoute.SuperNode.PubKeyV4 = PubKeyS4.ToString() - peerceconf.DynamicRoute.SuperNode.PubKeyV6 = PubKeyS6.ToString() - peerceconf.DynamicRoute.SuperNode.PSKey = PSKeyE.ToString() - peerceconf.PrivKey = PrivKeyE.ToString() - - SuperPeerInfo = append(SuperPeerInfo, mtypes.SuperPeerInfo{ - NodeID: i, - Name: NetworkName + idstr, - PubKey: PubKeyE.ToString(), - PSKey: PSKeyE.ToString(), - AdditionalCost: peerceconf.DynamicRoute.AdditionalCost, - SkipLocalIP: peerceconf.DynamicRoute.SuperNode.SkipLocalIP, - }) - mtypesBytes, _ := yaml.Marshal(peerceconf) - ioutil.WriteFile(filepath.Join(CfgSavePath, NetworkName+"_edge"+idstr+".yaml"), mtypesBytes, 0o600) - fmt.Println(filepath.Join(CfgSavePath, NetworkName+"_edge"+idstr+".yaml")) - } - sconfig.Peers = SuperPeerInfo - mtypesBytes, _ := yaml.Marshal(sconfig) - ioutil.WriteFile(filepath.Join(CfgSavePath, NetworkName+"_super.yaml"), mtypesBytes, 0o600) - fmt.Println(filepath.Join(CfgSavePath, NetworkName+"_super.yaml")) - return nil -} diff --git a/main_httpserver.go b/main_httpserver.go index ebc413c..9f67e40 100644 --- a/main_httpserver.go +++ b/main_httpserver.go @@ -499,9 +499,12 @@ func edge_post_nodeinfo(w http.ResponseWriter, r *http.Request) { pong_msg.AdditionalCost = AdditionalCost_use } applied_pones = append(applied_pones, pong_msg) + if httpobj.http_sconfig.LogLevel.LogControl { + fmt.Println("Control: Unpack from : Post body " + pong_msg.ToString()) + } } } - changed := httpobj.http_graph.UpdateLatencyMulti(client_report.Pongs, true, true) + changed := httpobj.http_graph.UpdateLatencyMulti(applied_pones, true, true) if changed { NhTable := httpobj.http_graph.GetNHTable(true) NhTablestr, _ := json.Marshal(NhTable) diff --git a/main_super.go b/main_super.go index d9c2e66..5c8045e 100644 --- a/main_super.go +++ b/main_super.go @@ -23,6 +23,7 @@ import ( "github.com/KusakabeSi/EtherGuard-VPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/device" + "github.com/KusakabeSi/EtherGuard-VPN/gencfg" "github.com/KusakabeSi/EtherGuard-VPN/ipc" "github.com/KusakabeSi/EtherGuard-VPN/mtypes" "github.com/KusakabeSi/EtherGuard-VPN/path" @@ -61,90 +62,11 @@ func checkNhTable(NhTable mtypes.NextHopTable, peers []mtypes.SuperPeerInfo) err } func printExampleSuperConf() { - sconfig := getExampleSuperConf("") + sconfig := gencfg.GetExampleSuperConf("") scprint, _ := yaml.Marshal(sconfig) fmt.Print(string(scprint)) } -func getExampleSuperConf(templatePath string) mtypes.SuperConfig { - sconfig := mtypes.SuperConfig{} - if templatePath != "" { - err := readYaml(templatePath, &sconfig) - if err == nil { - return sconfig - } - } - - v1 := mtypes.Vertex(1) - v2 := mtypes.Vertex(2) - - random_passwd := mtypes.RandomStr(8, "passwd") - - sconfig = mtypes.SuperConfig{ - NodeName: "NodeSuper", - PostScript: "", - PrivKeyV4: "mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=", - PrivKeyV6: "+EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=", - ListenPort: 3000, - ListenPort_EdgeAPI: "3000", - ListenPort_ManageAPI: "3000", - API_Prefix: "/eg_api", - LogLevel: mtypes.LoggerInfo{ - LogLevel: "normal", - LogTransit: false, - LogControl: true, - LogNormal: false, - LogInternal: true, - LogNTP: true, - }, - RePushConfigInterval: 30, - PeerAliveTimeout: 70, - HttpPostInterval: 50, - SendPingInterval: 15, - Passwords: mtypes.Passwords{ - ShowState: random_passwd + "_showstate", - AddPeer: random_passwd + "_addpeer", - DelPeer: random_passwd + "_delpeer", - UpdatePeer: random_passwd + "_updatepeer", - UpdateSuper: random_passwd + "_updatesuper", - }, - GraphRecalculateSetting: mtypes.GraphRecalculateSetting{ - StaticMode: false, - JitterTolerance: 5, - JitterToleranceMultiplier: 1.01, - TimeoutCheckInterval: 5, - RecalculateCoolDown: 5, - }, - NextHopTable: mtypes.NextHopTable{ - mtypes.Vertex(1): { - mtypes.Vertex(2): &v2, - }, - mtypes.Vertex(2): { - mtypes.Vertex(1): &v1, - }, - }, - EdgeTemplate: "example_config/super_mode/n1.yaml", - UsePSKForInterEdge: true, - Peers: []mtypes.SuperPeerInfo{ - { - NodeID: 1, - Name: "Node_01", - PubKey: "ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I=", - PSKey: "iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=", - AdditionalCost: 10, - }, - { - NodeID: 2, - Name: "Node_02", - PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=", - PSKey: "juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs=", - AdditionalCost: 10, - }, - }, - } - return sconfig -} - func Super(configPath string, useUAPI bool, printExample bool, bindmode string) (err error) { if printExample { printExampleSuperConf() @@ -152,13 +74,13 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) } var sconfig mtypes.SuperConfig - err = readYaml(configPath, &sconfig) + err = mtypes.ReadYaml(configPath, &sconfig) if err != nil { fmt.Printf("Error read config: %v\t%v\n", configPath, err) return err } httpobj.http_sconfig = &sconfig - http_econfig_tmp := getExampleEdgeConf(sconfig.EdgeTemplate) + http_econfig_tmp := gencfg.GetExampleEdgeConf(sconfig.EdgeTemplate) httpobj.http_econfig_tmp = &http_econfig_tmp NodeName := sconfig.NodeName if len(NodeName) > 32 { diff --git a/mtypes/config.go b/mtypes/config.go index ec5728b..d6aaf03 100644 --- a/mtypes/config.go +++ b/mtypes/config.go @@ -160,6 +160,7 @@ type GraphRecalculateSetting struct { StaticMode bool `yaml:"StaticMode"` JitterTolerance float64 `yaml:"JitterTolerance"` JitterToleranceMultiplier float64 `yaml:"JitterToleranceMultiplier"` + DampingResistance float64 `yaml:"DampingResistance"` TimeoutCheckInterval float64 `yaml:"TimeoutCheckInterval"` RecalculateCoolDown float64 `yaml:"RecalculateCoolDown"` } diff --git a/mtypes/functions.go b/mtypes/functions.go index 3f24849..7026f15 100644 --- a/mtypes/functions.go +++ b/mtypes/functions.go @@ -8,6 +8,8 @@ import ( "io/ioutil" nonSecureRand "math/rand" "time" + + "gopkg.in/yaml.v2" ) func S2TD(secs float64) time.Duration { @@ -69,3 +71,12 @@ func GUzip(bytesIn []byte) (ret []byte, err error) { } return ioutil.ReadAll(r) } + +func ReadYaml(filePath string, out interface{}) (err error) { + yamlFile, err := ioutil.ReadFile(filePath) + if err != nil { + return + } + err = yaml.Unmarshal(yamlFile, out) + return +} diff --git a/path/path.go b/path/path.go index 5d37bc0..08b4505 100644 --- a/path/path.go +++ b/path/path.go @@ -41,6 +41,7 @@ type IG struct { StaticMode bool JitterTolerance float64 JitterToleranceMultiplier float64 + DampingResistance float64 SuperNodeInfoTimeout time.Duration RecalculateCoolDown time.Duration TimeoutCheckInterval time.Duration @@ -64,6 +65,7 @@ func NewGraph(num_node int, IsSuperMode bool, theconfig mtypes.GraphRecalculateS StaticMode: theconfig.StaticMode, JitterTolerance: theconfig.JitterTolerance, JitterToleranceMultiplier: theconfig.JitterToleranceMultiplier, + DampingResistance: theconfig.DampingResistance, RecalculateCoolDown: mtypes.S2TD(theconfig.RecalculateCoolDown), TimeoutCheckInterval: mtypes.S2TD(theconfig.TimeoutCheckInterval), ntp_info: ntpinfo, @@ -87,8 +89,8 @@ func (g *IG) GetWeightType(x float64) (y float64) { return y } -func (g *IG) ShouldUpdate(u mtypes.Vertex, v mtypes.Vertex, newval float64) bool { - oldval := math.Abs(g.OldWeight(u, v, false) * 1000) +func (g *IG) ShouldUpdate(oldval float64, newval float64) bool { + oldval = math.Abs(oldval * 1000) newval = math.Abs(newval * 1000) if g.IsSuperMode { if g.JitterTolerance > 0.001 && g.JitterToleranceMultiplier >= 1 { @@ -110,7 +112,8 @@ func (g *IG) CheckAnyShouldUpdate() bool { for v, _ := range vert { if u != v { newVal := g.Weight(u, v, false) - if g.ShouldUpdate(u, v, newVal) { + oldVal := g.OldWeight(u, v, false) + if g.ShouldUpdate(oldVal, newVal) { return true } } @@ -176,13 +179,13 @@ func (g *IG) UpdateLatency(src mtypes.Vertex, dst mtypes.Vertex, val float64, Ti } func (g *IG) UpdateLatencyMulti(pong_info []mtypes.PongMsg, recalculate bool, checkchange bool) (changed bool) { - g.edgelock.Lock() should_update := false for _, pong_msg := range pong_info { u := pong_msg.Src_nodeID v := pong_msg.Dst_nodeID - w := pong_msg.Timediff + w_in := pong_msg.Timediff + w := w_in additionalCost := pong_msg.AdditionalCost if additionalCost < 0 { additionalCost = 0 @@ -194,9 +197,12 @@ func (g *IG) UpdateLatencyMulti(pong_info []mtypes.PongMsg, recalculate bool, ch g.edges[u] = make(map[mtypes.Vertex]*Latency) } g.edgelock.Unlock() - should_update = should_update || g.ShouldUpdate(u, v, w) + oldval := g.OldWeight(u, v, false) g.edgelock.Lock() - + if oldval != Infinity { + w = oldval*g.DampingResistance + w_in*(1-g.DampingResistance) + } + should_update = should_update || g.ShouldUpdate(oldval, w) if _, ok := g.edges[u][v]; ok { g.edges[u][v].ping = w g.edges[u][v].validUntil = time.Now().Add(mtypes.S2TD(pong_msg.TimeToAlive)) @@ -409,9 +415,11 @@ func Path(u, v mtypes.Vertex, next mtypes.NextHopTable) (path []mtypes.Vertex) { } func (g *IG) SetNHTable(nh mtypes.NextHopTable) { // set nhTable from supernode + g.edgelock.Lock() g.nhTable = nh g.changed = true g.NhTableExpire = time.Now().Add(g.SuperNodeInfoTimeout) + g.edgelock.Unlock() } func (g *IG) GetNHTable(recalculate bool) mtypes.NextHopTable { @@ -499,7 +507,7 @@ func Solve(filePath string, pe bool) error { return nil } - g := NewGraph(3, false, mtypes.GraphRecalculateSetting{ }, mtypes.NTPInfo{}, mtypes.LoggerInfo{LogInternal: true}) + g := NewGraph(3, false, mtypes.GraphRecalculateSetting{}, mtypes.NTPInfo{}, mtypes.LoggerInfo{LogInternal: true}) inputb, err := ioutil.ReadFile(filePath) if err != nil { return err