diff --git a/README_zh.md b/README_zh.md index 2620478..8efc3d6 100644 --- a/README_zh.md +++ b/README_zh.md @@ -82,8 +82,6 @@ VPN起來以後,自己手動加ip也行 $ ./etherguard-go -mode gencfg -cfgmode super -config example_config/super_mode/gensuper.yaml ``` - - 把一個super,2個edge分別搬去三台機器 或是2台機器,super和edge可以是同一台 diff --git a/device/peer.go b/device/peer.go index 88e6624..4e87250 100644 --- a/device/peer.go +++ b/device/peer.go @@ -154,7 +154,7 @@ type Peer struct { LastPacketReceivedAdd1Sec atomic.Value // *time.Time - SingleWayLatency float64 + SingleWayLatency atomic.Value stopping sync.WaitGroup // routines pending stop ID mtypes.Vertex @@ -245,7 +245,7 @@ func (device *Device) NewPeer(pk NoisePublicKey, id mtypes.Vertex, isSuper bool, peer.cookieGenerator.Init(pk) peer.device = device peer.endpoint_trylist = NewEndpoint_trylist(peer, mtypes.S2TD(device.EdgeConfig.DynamicRoute.PeerAliveTimeout)) - peer.SingleWayLatency = mtypes.Infinity + peer.SingleWayLatency.Store(mtypes.Infinity) peer.queue.outbound = newAutodrainingOutboundQueue(device) peer.queue.inbound = newAutodrainingInboundQueue(device) peer.queue.staged = make(chan *QueueOutboundElement, QueueStagedSize) diff --git a/device/receive.go b/device/receive.go index 3e7b584..52584b2 100644 --- a/device/receive.go +++ b/device/receive.go @@ -470,39 +470,76 @@ func (peer *Peer) RoutineSequentialReceiver() { packet_type = elem.Type if device.IsSuperNode { - switch dst_nodeID { - case mtypes.NodeID_AllPeer: + if packet_type.IsControl_Edge2Super() { should_process = true + } else { + device.log.Errorf("received unsupported packet_type %v from %v %v", packet_type, src_nodeID, peer.endpoint.DstToString()) + goto skip + } + switch dst_nodeID { case mtypes.NodeID_SuperNode: should_process = true default: - device.log.Errorf("Invalid dst_nodeID received. Check your code for bug") + device.log.Errorf("received invalid dst_nodeID %v from %v %v", dst_nodeID, src_nodeID, peer.endpoint.DstToString()) + goto skip } } else { - switch dst_nodeID { - case mtypes.NodeID_Boardcast: - should_receive = true - should_transfer = true - case mtypes.NodeID_SuperNode: - should_process = true - case mtypes.NodeID_AllPeer: - packet := elem.packet[path.EgHeaderLen:] //true packet - if device.CheckNoDup(packet) { + // Set should_receive and should_process + if packet_type.IsNormal() { + switch dst_nodeID { + case device.ID: + should_receive = true + case mtypes.NodeID_Broadcast: + should_receive = true + case mtypes.NodeID_AllPeer: + should_receive = true + } + } + if packet_type.IsControl_Edge2Edge() { + switch dst_nodeID { + case device.ID: should_process = true + case mtypes.NodeID_Broadcast: + should_process = true + case mtypes.NodeID_AllPeer: + should_process = true + } + } + if packet_type.IsControl_Super2Edge() { + if peer.ID == mtypes.NodeID_SuperNode { + switch dst_nodeID { + case device.ID: + should_process = true + case mtypes.NodeID_SuperNode: + should_process = true + } + + } else { + device.log.Errorf("received ServerUpdate packet from non supernode %v %v", src_nodeID, peer.endpoint.DstToString()) + goto skip + } + } + + // Set should_transfer + switch dst_nodeID { + case mtypes.NodeID_Broadcast: + should_transfer = true + case mtypes.NodeID_AllPeer: + packet := elem.packet[path.EgHeaderLen:] //packet body + if device.CheckNoDup(packet) { should_transfer = true } else { - should_process = false - should_transfer = false if device.LogLevel.LogTransit { - fmt.Printf("Transit: Duplicate packet received from %d through %d , src_nodeID = %d . Dropeed.\n", peer.ID, device.ID, src_nodeID) + fmt.Printf("Transit: Duplicate packet received from %d through %d , src_nodeID = %d . Dropped.\n", peer.ID, device.ID, src_nodeID) } + goto skip } case device.ID: - if packet_type == path.NormalPacket { - should_receive = true - } else { - should_process = true - } + should_transfer = false + case mtypes.NodeID_SuperNode: + should_transfer = false + case mtypes.NodeID_Invalid: + should_transfer = false default: if device.graph.Next(device.ID, dst_nodeID) != mtypes.NodeID_Invalid { should_transfer = true @@ -517,7 +554,7 @@ func (peer *Peer) RoutineSequentialReceiver() { device.log.Verbosef("TTL is 0 %v", dst_nodeID) } else { EgHeader.SetTTL(l2ttl - 1) - if dst_nodeID == mtypes.NodeID_Boardcast { //Regular transfer algorithm + if dst_nodeID == mtypes.NodeID_Broadcast { //Regular transfer algorithm device.TransitBoardcastPacket(src_nodeID, peer.ID, elem.Type, elem.packet, MessageTransportOffsetContent) } else if dst_nodeID == mtypes.NodeID_AllPeer { // Control Message will try send to every know node regardless the connectivity skip_list := make(map[mtypes.Vertex]bool) @@ -534,7 +571,7 @@ func (peer *Peer) RoutineSequentialReceiver() { if device.LogLevel.LogTransit { fmt.Printf("Transit: Transfer packet from %d through %d to %d\n", peer.ID, device.ID, peer_out.ID) } - device.SendPacket(peer_out, elem.Type, elem.packet, MessageTransportOffsetContent) + go device.SendPacket(peer_out, elem.Type, elem.packet, MessageTransportOffsetContent) } } } diff --git a/device/receivesendproc.go b/device/receivesendproc.go index 3f6fe2e..7de3eed 100644 --- a/device/receivesendproc.go +++ b/device/receivesendproc.go @@ -309,17 +309,20 @@ func (device *Device) server_process_Pong(peer *Peer, content mtypes.PongMsg) er func (device *Device) process_ping(peer *Peer, content mtypes.PingMsg) error { Timediff := device.graph.GetCurrentTime().Sub(content.Time).Seconds() - peer.SingleWayLatency = Timediff + NewTimediff := peer.SingleWayLatency.Load().(float64) + DR := NewTimediff * device.EdgeConfig.DynamicRoute.P2P.GraphRecalculateSetting.DampingResistance + NewTimediff = NewTimediff*DR + Timediff*(1-DR) + peer.SingleWayLatency.Store(NewTimediff) PongMSG := mtypes.PongMsg{ Src_nodeID: content.Src_nodeID, Dst_nodeID: device.ID, - Timediff: Timediff, + Timediff: NewTimediff, TimeToAlive: device.EdgeConfig.DynamicRoute.PeerAliveTimeout, AdditionalCost: device.EdgeConfig.DynamicRoute.AdditionalCost, } if device.EdgeConfig.DynamicRoute.P2P.UseP2P && time.Now().After(device.graph.NhTableExpire) { - device.graph.UpdateLatency(content.Src_nodeID, device.ID, PongMSG.Timediff, device.EdgeConfig.DynamicRoute.PeerAliveTimeout, device.EdgeConfig.DynamicRoute.AdditionalCost, true, false) + device.graph.UpdateLatencyMulti([]mtypes.PongMsg{PongMSG}, true, false) } body, err := mtypes.GetByte(&PongMSG) if err != nil { @@ -887,7 +890,7 @@ func (device *Device) RoutinePostPeerInfo(startchan <-chan struct{}) { RequestID: 0, Src_nodeID: device.ID, Dst_nodeID: id, - Timediff: peer.SingleWayLatency, + Timediff: peer.SingleWayLatency.Load().(float64), TimeToAlive: time.Since(*peer.LastPacketReceivedAdd1Sec.Load().(*time.Time)).Seconds() + device.EdgeConfig.DynamicRoute.PeerAliveTimeout, } pongs = append(pongs, pong) @@ -989,7 +992,7 @@ func (device *Device) RoutineSpreadAllMyNeighbor() { timeout := mtypes.S2TD(device.EdgeConfig.DynamicRoute.P2P.SendPeerInterval) for { device.process_RequestPeerMsg(mtypes.QueryPeerMsg{ - Request_ID: uint32(mtypes.NodeID_Boardcast), + Request_ID: uint32(mtypes.NodeID_Broadcast), }) time.Sleep(timeout) } diff --git a/device/send.go b/device/send.go index 5a51f00..0705036 100644 --- a/device/send.go +++ b/device/send.go @@ -256,9 +256,9 @@ func (device *Device) RoutineReadFromTUN() { dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:]) // lookup peer if tap.IsNotUnicast(dstMacAddr) { - dst_nodeID = mtypes.NodeID_Boardcast + dst_nodeID = mtypes.NodeID_Broadcast } else if val, ok := device.l2fib.Load(dstMacAddr); !ok { //Lookup failed - dst_nodeID = mtypes.NodeID_Boardcast + dst_nodeID = mtypes.NodeID_Broadcast } else { dst_nodeID = val.(*IdAndTime).ID } @@ -275,7 +275,7 @@ func (device *Device) RoutineReadFromTUN() { continue } - if dst_nodeID != mtypes.NodeID_Boardcast { + if dst_nodeID != mtypes.NodeID_Broadcast { var peer *Peer next_id := device.graph.Next(device.ID, dst_nodeID) if next_id != mtypes.NodeID_Invalid { diff --git a/example_config/static_mode/n1.yaml b/example_config/static_mode/EgNet_edge1.yaml similarity index 87% rename from example_config/static_mode/n1.yaml rename to example_config/static_mode/EgNet_edge1.yaml index 5236178..bde9a9a 100644 --- a/example_config/static_mode/n1.yaml +++ b/example_config/static_mode/EgNet_edge1.yaml @@ -3,7 +3,7 @@ Interface: Name: tap1 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: 8E:AA:C8:4B + MacAddrPrefix: DA:21:10:81 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -12,17 +12,17 @@ Interface: SendAddr: 127.0.0.1:5001 L2HeaderMode: kbdbg NodeID: 1 -NodeName: Node1 +NodeName: EgNet1 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: Fe9Q6K5L6xTVbx/zFc07tnQuo+pkeyrhfoTQ3BF5GRM= +PrivKey: LFFQqPBQ84x2AQ9BCI+0wG8nr+Y6yXHqhXkMCb4HCmg= ListenPort: 3001 LogLevel: LogLevel: error LogTransit: true - LogControl: true LogNormal: true + LogControl: true LogInternal: true LogNTP: true DynamicRoute: @@ -100,8 +100,8 @@ NextHopTable: ResetConnInterval: 86400 Peers: - NodeID: 2 - PubKey: MC8dHNj8u/RrK9iL6ln+AaGZWkMrDl+8aUoyxbsBZC4= - PSKey: kWDwCaC11UvYjfiXBMwYpR6Pujo1vaVW8JTusp1Kkrw= + PubKey: 0r2o9Hb36gYVgD3VSKCH18MVOZw0BvzcJ6TOTo6Cc1g= + PSKey: lFq67qp9LXL3PtlEJ3SGg3c/6++Ljy2I8i/k0Xcibvk= EndPoint: 127.0.0.1:3002 - PersistentKeepalive: 30 + PersistentKeepalive: 0 Static: true diff --git a/example_config/static_mode/n2.yaml b/example_config/static_mode/EgNet_edge2.yaml similarity index 79% rename from example_config/static_mode/n2.yaml rename to example_config/static_mode/EgNet_edge2.yaml index 85fa7bf..7293c34 100644 --- a/example_config/static_mode/n2.yaml +++ b/example_config/static_mode/EgNet_edge2.yaml @@ -3,7 +3,7 @@ Interface: Name: tap1 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: 8E:AA:C8:4B + MacAddrPrefix: DA:21:10:81 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -12,17 +12,17 @@ Interface: SendAddr: 127.0.0.1:5001 L2HeaderMode: kbdbg NodeID: 2 -NodeName: Node2 +NodeName: EgNet2 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: WaeR98bFhy0rxw7unsaTo7aR2RmySo9l185IZqPWl1c= +PrivKey: M8SxYCTHCPES/yPqcKP4mr+AoMAx9sgUmk64FCJIv6k= ListenPort: 3002 LogLevel: LogLevel: error LogTransit: true - LogControl: true LogNormal: true + LogControl: true LogInternal: true LogNTP: true DynamicRoute: @@ -100,20 +100,20 @@ NextHopTable: ResetConnInterval: 86400 Peers: - NodeID: 1 - PubKey: iDhQA9pgL01Gb0MrPzbiV80P4Uv3+uY/s+wNTQye0Qo= - PSKey: kWDwCaC11UvYjfiXBMwYpR6Pujo1vaVW8JTusp1Kkrw= + PubKey: fnc7bfFTf7B23hwtARPpX14tCeZwNfDhGCJctBpMfA8= + PSKey: lFq67qp9LXL3PtlEJ3SGg3c/6++Ljy2I8i/k0Xcibvk= EndPoint: 127.0.0.1:3001 PersistentKeepalive: 0 Static: true - NodeID: 3 - PubKey: 1vg9bSyqjDL8oUdqpKXn/RR96cjTHPCBga0vaw86WzU= - PSKey: f2/34zUTLx8RP9cYisESoQlxz55oGZlTemqxv25VVa8= + PubKey: ymNpm430tiph3rMSVnQzDAxmK9+3jdcRFi6e96xmQUI= + PSKey: Y86PZY1ldgoyzPJxEqei5Vg5zlzkJkoO77LJfxV8alE= EndPoint: 127.0.0.1:3003 PersistentKeepalive: 0 Static: true - NodeID: 4 - PubKey: WkBYMUcQwWwUlDYh7uLu4YefiH1yXb3Tkf3wGEtE6HY= - PSKey: zkG1ywPqS4MiGofuWmxHHBs8YBlnYd04B4T9IhkbXYM= + PubKey: 9YSIkihv/+aeukOaWwsR9EKvO1DM9+5kN53a/osTpmA= + PSKey: QHyrrls0KT2dvBKtoWkZvq5NQ+Xyjm0YgbMUzCCRw34= EndPoint: 127.0.0.1:3004 - PersistentKeepalive: 30 + PersistentKeepalive: 0 Static: true diff --git a/example_config/static_mode/n3.yaml b/example_config/static_mode/EgNet_edge3.yaml similarity index 79% rename from example_config/static_mode/n3.yaml rename to example_config/static_mode/EgNet_edge3.yaml index 0ff078e..dbca261 100644 --- a/example_config/static_mode/n3.yaml +++ b/example_config/static_mode/EgNet_edge3.yaml @@ -3,7 +3,7 @@ Interface: Name: tap1 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: 8E:AA:C8:4B + MacAddrPrefix: DA:21:10:81 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -12,17 +12,17 @@ Interface: SendAddr: 127.0.0.1:5001 L2HeaderMode: kbdbg NodeID: 3 -NodeName: Node3 +NodeName: EgNet3 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: vNUFWbZXySk2dTl5R9UEG73p+4IQmywvC1uQStf0vao= +PrivKey: cTO/GUSYHoj5mKczCyQu/ckPiDMEygkUbXcY3RafGEE= ListenPort: 3003 LogLevel: LogLevel: error LogTransit: true - LogControl: true LogNormal: true + LogControl: true LogInternal: true LogNTP: true DynamicRoute: @@ -99,21 +99,21 @@ NextHopTable: 5: 4 ResetConnInterval: 86400 Peers: -- NodeID: 5 - PubKey: AarP7cL6TVmFyHRZLXuxFGr5uQghsp57ydsJdj+lGzs= - PSKey: +TU8Zi8dr/UBqNyW/MYMgJiqkLnRbHW4ExQYQ2eNEag= - EndPoint: 127.0.0.1:3005 - PersistentKeepalive: 0 - Static: true - NodeID: 2 - PubKey: MC8dHNj8u/RrK9iL6ln+AaGZWkMrDl+8aUoyxbsBZC4= - PSKey: f2/34zUTLx8RP9cYisESoQlxz55oGZlTemqxv25VVa8= + PubKey: 0r2o9Hb36gYVgD3VSKCH18MVOZw0BvzcJ6TOTo6Cc1g= + PSKey: Y86PZY1ldgoyzPJxEqei5Vg5zlzkJkoO77LJfxV8alE= EndPoint: 127.0.0.1:3002 PersistentKeepalive: 0 Static: true - NodeID: 4 - PubKey: WkBYMUcQwWwUlDYh7uLu4YefiH1yXb3Tkf3wGEtE6HY= - PSKey: 8HN+PBGDKmBFCDlWIyNUFFYS4X6ONGXI32AIKXSnUqU= + PubKey: 9YSIkihv/+aeukOaWwsR9EKvO1DM9+5kN53a/osTpmA= + PSKey: SQyLomXDeknBIFezUKardOviAmNS+YZ1XTvZtYVlOtE= EndPoint: 127.0.0.1:3004 - PersistentKeepalive: 30 + PersistentKeepalive: 0 + Static: true +- NodeID: 5 + PubKey: x66hOjYXoZjL1FI3OVtf/CWittsnvmezKV6sW0v5FXQ= + PSKey: ChWBQurfGNZE5xIlhi9EUvZrQPBvkFsfrPaD6tyqSYg= + EndPoint: 127.0.0.1:3005 + PersistentKeepalive: 0 Static: true diff --git a/example_config/static_mode/n4.yaml b/example_config/static_mode/EgNet_edge4.yaml similarity index 79% rename from example_config/static_mode/n4.yaml rename to example_config/static_mode/EgNet_edge4.yaml index 13c7c14..4ff6ae7 100644 --- a/example_config/static_mode/n4.yaml +++ b/example_config/static_mode/EgNet_edge4.yaml @@ -3,7 +3,7 @@ Interface: Name: tap1 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: 8E:AA:C8:4B + MacAddrPrefix: DA:21:10:81 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -12,17 +12,17 @@ Interface: SendAddr: 127.0.0.1:5001 L2HeaderMode: kbdbg NodeID: 4 -NodeName: Node4 +NodeName: EgNet4 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: sn0BUwyNxfmgePYi6O6a8pFDKiLaCz6jk3ws+covRTA= +PrivKey: ai9XXdezwamYHf7EvzmLGlMp7mUg+hZwoqLefzwHWVM= ListenPort: 3004 LogLevel: LogLevel: error LogTransit: true - LogControl: true LogNormal: true + LogControl: true LogInternal: true LogNTP: true DynamicRoute: @@ -100,20 +100,20 @@ NextHopTable: ResetConnInterval: 86400 Peers: - NodeID: 2 - PubKey: MC8dHNj8u/RrK9iL6ln+AaGZWkMrDl+8aUoyxbsBZC4= - PSKey: zkG1ywPqS4MiGofuWmxHHBs8YBlnYd04B4T9IhkbXYM= + PubKey: 0r2o9Hb36gYVgD3VSKCH18MVOZw0BvzcJ6TOTo6Cc1g= + PSKey: QHyrrls0KT2dvBKtoWkZvq5NQ+Xyjm0YgbMUzCCRw34= EndPoint: 127.0.0.1:3002 PersistentKeepalive: 0 Static: true - NodeID: 3 - PubKey: 1vg9bSyqjDL8oUdqpKXn/RR96cjTHPCBga0vaw86WzU= - PSKey: 8HN+PBGDKmBFCDlWIyNUFFYS4X6ONGXI32AIKXSnUqU= + PubKey: ymNpm430tiph3rMSVnQzDAxmK9+3jdcRFi6e96xmQUI= + PSKey: SQyLomXDeknBIFezUKardOviAmNS+YZ1XTvZtYVlOtE= EndPoint: 127.0.0.1:3003 PersistentKeepalive: 0 Static: true - NodeID: 6 - PubKey: GH6ra6xhDezskkJrr/DXPi93vtmhi96DFBJ3s8U20EA= - PSKey: f50pI53AQ6RoTGEnTSjl5YJhuMS/xiJjwtPuiP0xMUM= + PubKey: f6kHXq3qPLocdM0CZEkoumOHevrabzqOBFG5vg9cjDc= + PSKey: crsb9pbTY/Bei7TugjPNtg4dVKVzjwC/A6AjlSVoqbQ= EndPoint: 127.0.0.1:3006 - PersistentKeepalive: 30 + PersistentKeepalive: 0 Static: true diff --git a/example_config/static_mode/n5.yaml b/example_config/static_mode/EgNet_edge5.yaml similarity index 87% rename from example_config/static_mode/n5.yaml rename to example_config/static_mode/EgNet_edge5.yaml index 55fa33f..4dfd665 100644 --- a/example_config/static_mode/n5.yaml +++ b/example_config/static_mode/EgNet_edge5.yaml @@ -3,7 +3,7 @@ Interface: Name: tap1 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: 8E:AA:C8:4B + MacAddrPrefix: DA:21:10:81 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -12,17 +12,17 @@ Interface: SendAddr: 127.0.0.1:5001 L2HeaderMode: kbdbg NodeID: 5 -NodeName: Node5 +NodeName: EgNet5 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: Blk9f1+NiC2fVCZpUBG34G9hrcLThemk/1Zd/dET6AA= +PrivKey: hBNK6Wu/Cl2MOXVA/F8yZsqIQ5eeIYCKPJeLu7i/190= ListenPort: 3005 LogLevel: LogLevel: error LogTransit: true - LogControl: true LogNormal: true + LogControl: true LogInternal: true LogNTP: true DynamicRoute: @@ -100,8 +100,8 @@ NextHopTable: ResetConnInterval: 86400 Peers: - NodeID: 3 - PubKey: 1vg9bSyqjDL8oUdqpKXn/RR96cjTHPCBga0vaw86WzU= - PSKey: +TU8Zi8dr/UBqNyW/MYMgJiqkLnRbHW4ExQYQ2eNEag= + PubKey: ymNpm430tiph3rMSVnQzDAxmK9+3jdcRFi6e96xmQUI= + PSKey: ChWBQurfGNZE5xIlhi9EUvZrQPBvkFsfrPaD6tyqSYg= EndPoint: 127.0.0.1:3003 - PersistentKeepalive: 30 + PersistentKeepalive: 0 Static: true diff --git a/example_config/static_mode/n6.yaml b/example_config/static_mode/EgNet_edge6.yaml similarity index 87% rename from example_config/static_mode/n6.yaml rename to example_config/static_mode/EgNet_edge6.yaml index 46c8184..794cf15 100644 --- a/example_config/static_mode/n6.yaml +++ b/example_config/static_mode/EgNet_edge6.yaml @@ -3,7 +3,7 @@ Interface: Name: tap1 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: 8E:AA:C8:4B + MacAddrPrefix: DA:21:10:81 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -12,17 +12,17 @@ Interface: SendAddr: 127.0.0.1:5001 L2HeaderMode: kbdbg NodeID: 6 -NodeName: Node6 +NodeName: EgNet6 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: h03OJ1d8cVGF8TemiWWTla7RCIMtInhUnjs2CBb8AT8= +PrivKey: ao6wfUYOG3FBYYPlb+VtXk2ZiK6j/6ac75Y9VuKd2Vs= ListenPort: 3006 LogLevel: LogLevel: error LogTransit: true - LogControl: true LogNormal: true + LogControl: true LogInternal: true LogNTP: true DynamicRoute: @@ -100,8 +100,8 @@ NextHopTable: ResetConnInterval: 86400 Peers: - NodeID: 4 - PubKey: WkBYMUcQwWwUlDYh7uLu4YefiH1yXb3Tkf3wGEtE6HY= - PSKey: f50pI53AQ6RoTGEnTSjl5YJhuMS/xiJjwtPuiP0xMUM= + PubKey: 9YSIkihv/+aeukOaWwsR9EKvO1DM9+5kN53a/osTpmA= + PSKey: crsb9pbTY/Bei7TugjPNtg4dVKVzjwC/A6AjlSVoqbQ= EndPoint: 127.0.0.1:3004 - PersistentKeepalive: 30 + PersistentKeepalive: 0 Static: true diff --git a/example_config/static_mode/README_zh.md b/example_config/static_mode/README_zh.md index ac56c26..647be8f 100644 --- a/example_config/static_mode/README_zh.md +++ b/example_config/static_mode/README_zh.md @@ -1,84 +1,105 @@ # Etherguard -[English](README.md) - -Static Mode的[範例配置檔](./)的說明文件 +[English](README.md) | [中文](#) ## Static Mode 沒有自動選路,沒有握手伺服器 +類似原本的wireguard,一切都要提前配置好 +設定檔裡面的`NextHopTable`部分,只有此模式會生效 -十分類似原本的wireguard,一切都要提前配置好 - -但是除了peer以外,還要額外配置轉發表,所有人共用一份轉發表 - -設定檔裡面的`nexthoptable`部分,只有此模式會生效 - -這個模式下,不存在任何的Control Message,斷線偵測甚麼的也不會有 +這個模式下,不存在任何的Control Message,斷線偵測什麼的也不會有 請務必保持提前定義好的拓樸。不然如果存在中轉,中轉節點斷了,部分連線就會中斷 +## Quick Start +首先,按照需求修改`genstatic.yaml` + +```yaml +Config output dir: /tmp/eg_gen_static # 設定檔輸出位置 +ConfigTemplate for edge node: "" # 設定檔Template +Network name: "EgNet" +Edge Node: + MacAddress prefix: "" # 留空隨機產生 + IPv4 range: 192.168.76.0/24 # 順帶一提,IP的部分可以直接省略沒關係 + IPv6 range: fd95:71cb:a3df:e586::/64 # 這個欄位唯一的目的只是在啟動以後,調用ip命令,幫tap接口加個ip + IPv6 LL range: fe80::a3df:0/112 # 和VPN本身運作完全無關 +Edge Nodes: # 所有的節點相關設定 + 1: + Endpoint(optional): 127.0.0.1:3001 + 2: + Endpoint(optional): 127.0.0.1:3002 + 3: + Endpoint(optional): 127.0.0.1:3003 + 4: + Endpoint(optional): 127.0.0.1:3004 + 5: + Endpoint(optional): 127.0.0.1:3005 + 6: + Endpoint(optional): 127.0.0.1:3006 +Distance matrix for all nodes: |- # 左邊是起點,上面是終點,Inf代表此二節點不相連 ,數值代表相連。數值大小代表通過成本(通常是延遲) + X 1 2 3 4 5 6 + 1 0 1.0 Inf Inf Inf Inf + 2 1.0 0 1.0 1.0 Inf Inf + 3 Inf 1.0 0 1 1.0 Inf + 4 Inf 1.0 1.0 0 Inf 1.0 + 5 Inf Inf 1.0 Inf 1.0 Inf + 6 Inf Inf Inf 1.0 Inf 1.0 +``` +接著執行這個,就會生成所需設定檔了。 +``` +./etherguard-go -mode gencfg -cfgmode static -config example_config/static_mode/genstatic.yaml +``` + +把這些設定檔不捨去對應節點,然後再執行 +``` +./etherguard-go -config [設定檔位置] -mode edge +``` +就可以了 + +確認運作以後,可以關閉不必要的log增加性能 + +## Documentation + +Static Mode的說明文件 + 這份[範例配置檔](./)的網路拓樸如圖所示 !["Topology"](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/static_mode/Example_static.png) 發出封包時,會設定起始ID=自己的Node ID,終點ID則是看Dst Mac Address。 -如果Dst MacAddr是廣播地址,或是不在自己的對應表裡面,就會設定終點=Boardcast +如果Dst MacAddr是廣播地址,或是不在自己的對應表裡面,就會設定終點=Broadcast 收到封包的時候,如果`dst==自己ID`,就會收下,不轉給任何人。 同時還會看它的 Src Mac Address 和 Src NodeID ,並加入對應表 這樣下次傳給他就可以直接傳給目標,而不用廣播給全節點了 所以設定檔中的轉發表如下表。格式是yaml的巢狀dictionary -轉發/發送封包時,直接查詢 `NhTable[起點][終點]=下一跳` +轉發/發送封包時,直接查詢`NhTable` 就知道下面一個封包要轉給誰了 +NextHopTable 是長這樣的資料結構,`NhTable[起點][終點]=下一跳` + ```yaml -nexthoptable: +NextHopTable: 1: 2: 2 3: 2 - 4: 2 - 5: 2 - 6: 2 2: 1: 1 3: 3 - 4: 4 - 5: 3 - 6: 4 + 3: 1: 2 2: 2 - 4: 4 - 5: 5 - 6: 4 - 4: - 1: 2 - 2: 2 - 3: 3 - 5: 3 - 6: 6 - 5: - 1: 3 - 2: 3 - 3: 3 - 4: 3 - 6: 3 - 6: - 1: 4 - 2: 4 - 3: 4 - 4: 4 - 5: 4 ``` -### Boardcast -比較特別的是`終點ID=Boardcast`的情況。 +### Broadcast +比較特別的是`終點ID=Broadcast`的情況。 -假設今天的狀況:我是4號,我收到`起點ID = 1,終點ID=boardcast`的封包 +假設今天的狀況:我是4號,我收到`起點ID = 1,終點ID=Broadcast`的封包 我應該只轉給6號就好,而不會轉給3號。 因為3號會收到來自2號的封包,自己就不用重複遞送了 -因此我有設計,如果`終點ID = Boardcast`,就會檢查Src到自己的所有鄰居,會不會經過自己 +因此我有設計,如果`終點ID = Broadcast`,就會檢查Src到自己的所有鄰居,會不會經過自己 **1 -> 6** 會經過自己: [1 2 4 6] **1 -> 3** 不會: [1 2 3] 2號是封包來源跳過檢查 @@ -94,189 +115,97 @@ nexthoptable: ``` X 1 2 3 4 5 6 -1 0 0.5 Inf Inf Inf Inf -2 0.5 0 0.5 0.5 Inf Inf -3 Inf 0.5 0 0.5 0.5 Inf -4 Inf 0.5 0.5 0 Inf 0.5 -5 Inf Inf 0.5 Inf 0 Inf -6 Inf Inf Inf 0.5 Inf 0 +1 0 1.0 Inf Inf Inf Inf +2 1.0 0 1.0 1.0 Inf Inf +3 Inf 1.0 0 1 1.0 Inf +4 Inf 1.0 1.0 0 Inf 1.0 +5 Inf Inf 1.0 Inf 1.0 Inf +6 Inf Inf Inf 1.0 Inf 1.0 ``` 之後用這個指令就能輸出用Floyd Warshall算好的轉發表了,填入設定檔即可 -``` -./etherguard-go -config example_config/static_mode/path.txt -mode slove -NextHopTable: - 1: - 2: 2 - 3: 2 - 4: 2 - 5: 2 - 6: 2 - 2: - 1: 1 - 3: 3 - 4: 4 - 5: 3 - 6: 4 - 3: - 1: 2 - 2: 2 - 4: 4 - 5: 5 - 6: 4 - 4: - 1: 2 - 2: 2 - 3: 3 - 5: 3 - 6: 6 - 5: - 1: 3 - 2: 3 - 3: 3 - 4: 3 - 6: 3 - 6: - 1: 4 - 2: 4 - 3: 4 - 4: 4 - 5: 4 -``` +### EdgeNode Config Parameter -程式還會額外輸出一些資訊,像是路徑表。 -會標示所有的起點終點組合的封包路徑,還有行經距離 -``` -Human readable: -src dist path -1 -> 2 0.500000 [1 2] -1 -> 3 1.000000 [1 2 3] -1 -> 4 1.000000 [1 2 4] -1 -> 5 1.500000 [1 2 3 5] -1 -> 6 1.500000 [1 2 4 6] -2 -> 1 0.500000 [2 1] -2 -> 3 0.500000 [2 3] -2 -> 4 0.500000 [2 4] -2 -> 5 1.000000 [2 3 5] -2 -> 6 1.000000 [2 4 6] -3 -> 1 1.000000 [3 2 1] -3 -> 2 0.500000 [3 2] -3 -> 4 0.500000 [3 4] -3 -> 5 0.500000 [3 5] -3 -> 6 1.000000 [3 4 6] -4 -> 1 1.000000 [4 2 1] -4 -> 2 0.500000 [4 2] -4 -> 3 0.500000 [4 3] -4 -> 5 1.000000 [4 3 5] -4 -> 6 0.500000 [4 6] -5 -> 1 1.500000 [5 3 2 1] -5 -> 2 1.000000 [5 3 2] -5 -> 3 0.500000 [5 3] -5 -> 4 1.000000 [5 3 4] -5 -> 6 1.500000 [5 3 4 6] -6 -> 1 1.500000 [6 4 2 1] -6 -> 2 1.000000 [6 4 2] -6 -> 3 1.000000 [6 4 3] -6 -> 4 0.500000 [6 4] -6 -> 5 1.500000 [6 4 3 5] -``` +Key | Description +-------------- |:----- +[Interface](#Interface)| 接口相關設定。VPN有兩端,一端是VPN網路,另一端則是本地接口 +NodeID | 節點ID。節點之間辨識身分用的,同一網路內節點ID不能重複 +NodeName | 節點名稱 +PostScript | 初始化完畢之後要跑的腳本 +DefaultTTL | TTL,etherguard層使用,和乙太層不共通 +L2FIBTimeout | MacAddr-> NodeID 查找表的 timeout(秒) ,類似ARP table +PrivKey | 私鑰,和wireguard規格一樣 +ListenPort | 監聽的udp埠 +[LogLevel](#LogLevel)| 紀錄log +[DynamicRoute](../super_mode/README_zh.md#DynamicRoute) | 動態路由相關設定,Static模式用不到 +NextHopTable | 轉發表, 下一跳 = `NhTable[起點][終點]` +ResetConnInterval | 如果對方是動態ip就要用這個。每隔一段時間就會重置連線,重新解析域名 +[Peers](#Peers) | 鄰居節點,和wireguard相同 -有些設定檔對應某些運作模式,這邊針對共同部分的設定做說明 +Interface | Description +---------------|:----- +[IType](#IType)| 接口類型,意味著從VPN網路收到的封包要丟去哪邊 +Name | 裝置名稱 +VPPIFaceID | VPP 的 interface ID。同一個VPP runtime內不能重複 +VPPBridgeID | VPP 的網橋ID。不使用VPP網橋功能的話填0 +MacAddrPrefix | MAC地址前綴。真正的 MAC 地址=[前綴]:[NodeID] +IPv4CIDR | 啟動以後,調用ip命令,幫tap接口加個ip。僅限tap有效 +IPv4CIDR | 啟動以後,調用ip命令,幫tap接口加個ip。僅限tap有效 +IPv6LLPrefix | 啟動以後,調用ip命令,幫tap接口加個ip。僅限tap有效 +MTU | 裝置MTU,僅限`tap` , `vpp` 模式有效 +RecvAddr | listen地址,收到的東西丟去 VPN 網路。僅限`*sock`生效 +SendAddr | 連線地址,VPN網路收到的東西丟去這個地址。僅限`*sock`生效 +[L2HeaderMode](#L2HeaderMode) | 僅限 `stdio` 生效。debug用途,有三種模式 -### Edge config +IType | Description +-----------|:----- +dummy | 收到的封包直接丟棄,但幫忙轉發。作為中繼節點,本身不加入網路使用 +stdio | 收到的封包丟stdout,stdin進來的資料丟入vpn網路,debug用途
需要參數: `MacAddrPrefix` && `L2HeaderMode` +udpsock | 收到的封包丟去一個udp socket
需要參數: `RecvAddr` && `SendAddr` +tcpsock | 收到的封包丟去一個tcp socket
需要參數: `RecvAddr` \|\| `SendAddr` +unixsock | 收到的封包丟去一個unix socket(SOCK_STREAM 模式)
需要參數: `RecvAddr` \|\| `SendAddr` +udpsock | 收到的封包丟去一個unix socket(SOCK_DGRAM 模式)
需要參數: `RecvAddr` \|\| `SendAddr` +udpsock | 收到的封包丟去一個unix socket(SOCK_SEQPACKET 模式)
需要參數: `RecvAddr` \|\| `SendAddr` +fd | 收到的封包丟去一個特定的file descriptor
需要參數: 無. 但是使用環境變數 `EG_FD_RX` && `EG_FD_TX` 來指定 +vpp | 使用libmemif使vpp加入VPN網路
需要參數: `Name` && `VPPIFaceID` && `VPPBridgeID` && `MacAddrPrefix` && `MTU` +tap | Linux的tap設備。讓linux加入VPN網路
需要參數: `Name` && `MacAddrPrefix` && `MTU`
可選參數:`IPv4CIDR` , `IPv6CIDR` , `IPv6LLPrefix` -1. `interface` - 1. `itype`: 裝置類型,意味著從VPN網路收到的封包要丟去哪個硬體 - 1. `dummy`: 收到的封包直接丟棄,也不發出任何封包。作為中繼節點使用 - 2. `stdio`: 收到的封包丟stdout,stdin進來的資料丟入vpn網路 - 需要參數: `macaddrprefix`,`l2headermode` - 3. `udpsock`: 把VPN網路收到的layer2封包讀寫去一個udp socket. - Paramaters: `recvaddr`,`sendaddr` - 3. `tcpsock`: 把VPN網路收到的layer2封包讀寫去一個tcp socket. - Paramaters: `recvaddr`,`sendaddr` - 3. `unixsock`: 把VPN網路收到的layer2封包讀寫去一個unix socket(SOCK_STREAM 模式). - Paramaters: `recvaddr`,`sendaddr` - 3. `unixgramsock`: 把VPN網路收到的layer2封包讀寫去一個unix socket(SOCK_DGRAM 模式). - Paramaters: `recvaddr`,`sendaddr` - 3. `unixpacketsock`: 把VPN網路收到的layer2封包讀寫去一個unix socket(SOCK_SEQPACKET 模式). - Paramaters: `recvaddr`,`sendaddr` - 3. `fd`: 把VPN網路收到的layer2封包讀寫去一個特定的file descriptor. - Paramaters: 無. 但是使用環境變數 `EG_FD_RX` 和 `EG_FD_TX` 來指定 - 4. `vpp`: 使用libmemif使vpp加入VPN網路 - 需要參數: `name`,`vppifaceid`,`vppbridgeid`,`macaddrprefix`,`mtu` - 5. `tap`: Linux的tap設備。讓linux加入VPN網路 - 需要參數: `name`,`macaddrprefix`,`mtu` - 2. `name` : 裝置名稱 - 3. `vppifaceid`: VPP 的 interface ID。一個VPP runtime內不能重複 - 4. `vppbridgeid`: VPP 的網橋ID。不使用VPP網橋功能的話填0 - 5. `macaddrprefix`: MAC地址前綴。真正的 MAC 地址=[前綴]:[NodeID]。 - 如果這邊填了完整6格長度,就忽略`NodeID` - 6. `recvaddr`: 僅限`XXXsock`生效。listen地址,收到的東西丟去 VPN 網路 - 7. `sendaddr`: 僅限`XXXsock`生效。連線地址,VPN網路收到的東西丟去這個地址 - 8. `l2headermode`: 僅限 `stdio` 生效。debug用途,有三種模式: - 1. `nochg`: 從 VPN 網路收到什麼,就往tap裝置發送什麼。不對封包作任何更動 - 2. `kbdbg`: 鍵盤bebug模式。搭配 `stdio` 模式,讓我 debug 用 - 因為前 12 byte 會用來做選路判斷,但是只是要debug,構造完整的封包就不是很方便 - 這個模式下,如果輸入b2content,就會幫你把b轉換成`FF:FF:FF:FF:FF:FF`, `2` 轉換成 `AA:BB:CC:DD:EE:02` 。封包內容變成 `b"0xffffffffffffaabbccddee02content"`。 - 用鍵盤就能輕鬆產生L2 header,查看選路的行為 - 3. `noL2`: 拔掉L2 Header的模式。 - 但是本VPN會查詢L2用作選路,所以會變成一律廣播 -2. `nodeid`: 節點ID。節點之間辨識身分用的,同一網路內節點ID不能重複 -3. `postscript`: etherguard初始化完畢之後要跑的腳本. -3. `nodename`: 節點名稱 -4. `defaultttl`: 預設ttl(etherguard層使用,和乙太層不共通) -5. `l2fibtimeout`: MacAddr-> NodeID 查找表的 timeout(秒) -5. `privkey`: 私鑰,和wireguard規格一樣 -5. `listenport`: 監聽的udp埠 -6. `loglevel`: 紀錄log - 1. `loglevel`: wireguard原本的log紀錄器的loglevel。 - 有`debug`,`error`,`slient`三種程度 - 2. `logtransit`: 轉送封包,也就是起點/終點都不是自己的封包的log - 3. `logcontrol`: Control Message的log - 4. `lognormal`: 收發普通封包,起點是自己or終點是自己的log - 5. `logntp`: NTP 同步時鐘相關的log -7. `dynamicroute`: 動態路由相關的設定。時間類設定單位都是秒 - 1. `sendpinginterval`: 發送Ping訊息的間隔 - 2. `dupchecktimeout`: 重複封包檢查的timeout。完全相同的封包收第二次會被丟棄 - 1. `peeralivetimeout`: 每次收到封包就重置,超過時間沒收到就標記該peer離線 - 3. `conntimeout`: 檢查peer離線的間格,如果標記離線,就切換下一個endpoint(supernode可能傳了多個endpoint過來) - 4. `savenewpeers`: 是否把下載來的鄰居資訊存到本地設定檔裡面 - 5. `supernode`: 參見[Super模式](example_config/super_mode/README_zh.md) - 6. `p2p` 參見 [P2P模式](example_config/p2p_mode/README_zh.md) - 7. `ntpconfig`: NTP 相關的設定 - 1. `usentp`: 是否使用ntp同步時鐘 - 2. `maxserveruse`: 一次對多連線幾個NTP伺服器 - 第一次會全部連一遍測延遲,之後每次都取延遲前n低的來用 - 3. `synctimeinterval`: 多久同步一次 - 4. `ntptimeout`: 多久算是超時 - 5. `servers`: NTP伺服器列表 -8. `nexthoptable`: 轉發表。只有Static模式會用到,參見 [Static模式](example_config/super_mode/README_zh.md) -9. `resetconninterval`: 如果對方是動態ip就要用這個。每隔一段時間就會重新解析domain。 -10. `peers`: 和wireguard一樣的peer資訊 - 1. `nodeid`: 對方的節點ID - 2. `pubkey`: 對方的公鑰 - 3. `pskey`: 對方的預共享金鑰。但是目前沒用(因為不能設定自己的),之後會加 - 4. `endpoint`: 對方的連線地址。如果roaming會覆寫設定檔 - 5. `static`: 設定成true的話,每隔`resetconninterval`秒就會重新解析一次domain,與此同時也不會被roaming覆寫 +L2HeaderMode | Description +---------------|:----- +nochg | 收到的封包丟stdout,stdin進來的資料丟入vpn網路,不對封包作任何更動 +kbdbg | 前 12byte 會用來做選路判斷
但是stdio模式下,使用鍵盤輸入一個Ethernet frame不太方便
此模式讓我快速產生Ethernet frame,debug更方便
`b`轉換成`FF:FF:FF:FF:FF:FF`
`2`轉換成 `AA:BB:CC:DD:EE:02`
輸入`b2aaaaa`就會變成`b"0xffffffffffffaabbccddee02aaaaa"` +noL2 | 讀取時拔掉L2 Header的模式
寫入時時一律使用廣播MacAddress -### Super config +LogLevel | Description +------------|:----- +LogLevel | wireguard原本的log紀錄器的loglevel
接受參數: `debug`,`error`,`slient` +LogTransit | 轉送封包,也就是起點/終點都不是自己的封包的log +LogNormal | 收發普通封包,起點是自己or終點是自己的log +LogControl | Control Message的log +LogInternal | 一些內部事件的log +LogNTP | NTP 同步時鐘相關的log - 參見 [example_config/super_mode/README_zh.md](example_config/super_mode/README_zh.md) - -### Quick start +Peers | Description +--------------------|:----- +NodeID | 對方的節點ID +PubKey | 對方的公鑰 +PSKey | 對方的預共享金鑰 +EndPoint | 對方的連線地址。如果漫遊,而且`Static=false`會覆寫設定檔 +PersistentKeepalive | wireguard的PersistentKeepalive參數 +Static | 關閉漫遊功能,每隔`ResetConnInterval`秒,重置回初始ip #### Run example config 在**不同terminal**分別執行以下命令 ``` -./etherguard-go -config example_config/super_mode/n1.yaml -mode edge -./etherguard-go -config example_config/super_mode/n2.yaml -mode edge -./etherguard-go -config example_config/super_mode/n3.yaml -mode edge -./etherguard-go -config example_config/super_mode/n4.yaml -mode edge -./etherguard-go -config example_config/super_mode/n5.yaml -mode edge -./etherguard-go -config example_config/super_mode/n6.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge1.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge2.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge3.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge4.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge5.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge6.yaml -mode edge ``` 因為本範例配置是stdio的kbdbg模式,stdin會讀入VPN網路 @@ -284,12 +213,7 @@ src dist path ``` b1message ``` -因為`l2headermode`是`kbdbg`,所以b1會被轉換成 12byte 的layer 2 header,b是廣播地址`FF:FF:FF:FF:FF:FF`,1是普通地址`AA:BB:CC:DD:EE:01`,message是後面的payload,然後再丟入VPN +因為`L2HeaderMode`是`kbdbg`,所以b1會被轉換成 12byte 的layer 2 header,b是廣播地址`FF:FF:FF:FF:FF:FF`,1是普通地址`AA:BB:CC:DD:EE:01`,message是後面的payload,然後再丟入VPN 此時應該要能夠在另一個視窗上看見字串b1message。前12byte被轉換回來了 -#### Run your own etherguard - -要正式使用,請將itype改成`tap`,並且修改各節點的公鑰私鑰和連線地址 -再關閉不必要的log增加性能,最後部屬到不同節點即可 - ## 下一篇: [Super Mode的運作](../super_mode/README_zh.md) \ No newline at end of file diff --git a/example_config/static_mode/genstatic.yaml b/example_config/static_mode/genstatic.yaml index 8aca6ed..fe78c05 100644 --- a/example_config/static_mode/genstatic.yaml +++ b/example_config/static_mode/genstatic.yaml @@ -1,6 +1,6 @@ Config output dir: /tmp/eg_gen_static -ConfigTemplate for edge node: "n1.yaml" -Network name: "Node" +ConfigTemplate for edge node: "" # "EgNet_edge1.yaml" +Network name: "EgNet" Edge Node: MacAddress prefix: "" IPv4 range: 192.168.76.0/24 @@ -9,27 +9,21 @@ Edge Node: Edge Nodes: 1: Endpoint(optional): 127.0.0.1:3001 - PersistentKeepalive: 30 2: Endpoint(optional): 127.0.0.1:3002 - PersistentKeepalive: 30 3: Endpoint(optional): 127.0.0.1:3003 - PersistentKeepalive: 30 4: Endpoint(optional): 127.0.0.1:3004 - PersistentKeepalive: 30 5: Endpoint(optional): 127.0.0.1:3005 - PersistentKeepalive: 30 6: Endpoint(optional): 127.0.0.1:3006 - PersistentKeepalive: 30 Distance matrix for all nodes: |- X 1 2 3 4 5 6 - 1 0 1 Inf Inf Inf Inf - 2 1 0 1 1 Inf Inf - 3 Inf 1 0 1 1 Inf - 4 Inf 1 1 0 Inf 1 - 5 Inf Inf 1 Inf 0 Inf - 6 Inf Inf Inf 1 Inf 0 \ No newline at end of file + 1 0 1.0 Inf Inf Inf Inf + 2 1.0 0 1.0 1.0 Inf Inf + 3 Inf 1.0 0 1 1.0 Inf + 4 Inf 1.0 1.0 0 Inf 1.0 + 5 Inf Inf 1.0 Inf 1.0 Inf + 6 Inf Inf Inf 1.0 Inf 1.0 \ No newline at end of file diff --git a/example_config/super_mode/EGS03.png b/example_config/super_mode/EGS03.png index 63e742b..00b7c56 100644 Binary files a/example_config/super_mode/EGS03.png and b/example_config/super_mode/EGS03.png differ diff --git a/example_config/super_mode/EGS08.png b/example_config/super_mode/EGS08.png new file mode 100644 index 0000000..6b363eb Binary files /dev/null and b/example_config/super_mode/EGS08.png differ diff --git a/example_config/super_mode/n1.yaml b/example_config/super_mode/Node_edge001.yaml similarity index 67% rename from example_config/super_mode/n1.yaml rename to example_config/super_mode/Node_edge001.yaml index 7c9d9f7..c956eba 100644 --- a/example_config/super_mode/n1.yaml +++ b/example_config/super_mode/Node_edge001.yaml @@ -1,28 +1,28 @@ Interface: IType: stdio - Name: tap1 + Name: Node001 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: AA:BB:CC:DD - IPv4CIDR: "" - IPv6CIDR: "" - IPv6LLPrefix: "" + MacAddrPrefix: CE:51:BA:B4 + IPv4CIDR: 192.168.76.0/24 + IPv6CIDR: fd95:71cb:a3df:e586::/64 + IPv6LLPrefix: fe80::a3df:0/112 MTU: 1416 RecvAddr: 127.0.0.1:4001 SendAddr: 127.0.0.1:5001 L2HeaderMode: kbdbg NodeID: 1 -NodeName: Node01 +NodeName: Node001 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: 6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M= -ListenPort: 0 +PrivKey: C0SXvffZh8nDqXYNzG4UqUJtSCiRMEj3ehX5o7QiJz0= +ListenPort: 3001 LogLevel: LogLevel: error - LogTransit: true + LogTransit: false LogControl: true - LogNormal: true + LogNormal: false LogInternal: true LogNTP: true DynamicRoute: @@ -35,12 +35,12 @@ DynamicRoute: SaveNewPeers: true SuperNode: 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 + PSKey: j2f9Fhdhw2O2zLqUqfL5nTFStjVWPnEXpw7Iqz6VX9M= + EndpointV4: 127.0.0.1:3456 + PubKeyV4: Id/VoZ6HmTU3FSqhxBUswfuHHB0mQxfzcbdoJNGBRzQ= + EndpointV6: :3456 + PubKeyV6: 40tADRhJTvaortwE5Ur4qNXhP+SOMX7ZuSvl251Yxnc= + EndpointEdgeAPIUrl: http://127.0.0.1:3456/eg_net/eg_api SkipLocalIP: false SuperNodeInfoTimeout: 50 P2P: @@ -48,8 +48,10 @@ DynamicRoute: SendPeerInterval: 20 GraphRecalculateSetting: StaticMode: false - JitterTolerance: 20 + ManualLatency: {} + JitterTolerance: 50 JitterToleranceMultiplier: 1.1 + DampingResistance: 0 TimeoutCheckInterval: 5 RecalculateCoolDown: 5 NTPConfig: @@ -80,4 +82,4 @@ DynamicRoute: - 3.pool.ntp.org NextHopTable: {} ResetConnInterval: 86400 -Peers: [] \ No newline at end of file +Peers: [] diff --git a/example_config/super_mode/n2.yaml b/example_config/super_mode/Node_edge002.yaml similarity index 66% rename from example_config/super_mode/n2.yaml rename to example_config/super_mode/Node_edge002.yaml index d713b2a..98d34e7 100644 --- a/example_config/super_mode/n2.yaml +++ b/example_config/super_mode/Node_edge002.yaml @@ -1,28 +1,28 @@ Interface: IType: stdio - Name: tap1 - VPPIFaceID: 2 + Name: Node002 + VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: AA:BB:CC:DD - IPv4CIDR: "" - IPv6CIDR: "" - IPv6LLPrefix: "" + MacAddrPrefix: CE:51:BA:B4 + IPv4CIDR: 192.168.76.0/24 + IPv6CIDR: fd95:71cb:a3df:e586::/64 + IPv6LLPrefix: fe80::a3df:0/112 MTU: 1416 RecvAddr: 127.0.0.1:4002 SendAddr: 127.0.0.1:5002 L2HeaderMode: kbdbg NodeID: 2 -NodeName: Node02 +NodeName: Node002 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: OH8BsVUU2Rqzeu9B2J5GPG8PUmxWfX8uVvNFZKhVF3o= -ListenPort: 0 +PrivKey: AErxhLXdZvidPZVXRYgD+84fa2qYWG9ft4MRuCbAtt8= +ListenPort: 3002 LogLevel: LogLevel: error - LogTransit: true + LogTransit: false LogControl: true - LogNormal: true + LogNormal: false LogInternal: true LogNTP: true DynamicRoute: @@ -35,12 +35,12 @@ DynamicRoute: SaveNewPeers: true SuperNode: UseSuperNode: true - PSKey: juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs= - EndpointV4: 127.0.0.1:3000 - PubKeyV4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= - EndpointV6: '[::1]:3000' - PubKeyV6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= - EndpointEdgeAPIUrl: http://127.0.0.1:3000/eg_api + PSKey: iCw096jsW2aWyMwPyzVEvL8C3XXqMpB+jOeWqDC34uU= + EndpointV4: 127.0.0.1:3456 + PubKeyV4: Id/VoZ6HmTU3FSqhxBUswfuHHB0mQxfzcbdoJNGBRzQ= + EndpointV6: :3456 + PubKeyV6: 40tADRhJTvaortwE5Ur4qNXhP+SOMX7ZuSvl251Yxnc= + EndpointEdgeAPIUrl: http://127.0.0.1:3456/eg_net/eg_api SkipLocalIP: false SuperNodeInfoTimeout: 50 P2P: @@ -48,8 +48,10 @@ DynamicRoute: SendPeerInterval: 20 GraphRecalculateSetting: StaticMode: false - JitterTolerance: 20 + ManualLatency: {} + JitterTolerance: 50 JitterToleranceMultiplier: 1.1 + DampingResistance: 0 TimeoutCheckInterval: 5 RecalculateCoolDown: 5 NTPConfig: @@ -80,4 +82,4 @@ DynamicRoute: - 3.pool.ntp.org NextHopTable: {} ResetConnInterval: 86400 -Peers: [] \ No newline at end of file +Peers: [] diff --git a/example_config/super_mode/n100.yaml b/example_config/super_mode/Node_edge100.yaml similarity index 67% rename from example_config/super_mode/n100.yaml rename to example_config/super_mode/Node_edge100.yaml index 3e2f94e..6faa2e5 100644 --- a/example_config/super_mode/n100.yaml +++ b/example_config/super_mode/Node_edge100.yaml @@ -1,12 +1,12 @@ Interface: IType: stdio - Name: tap1 - VPPIFaceID: 100 + Name: Node100 + VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: AA:BB:CC:DD - IPv4CIDR: "" - IPv6CIDR: "" - IPv6LLPrefix: "" + MacAddrPrefix: CE:51:BA:B4 + IPv4CIDR: 192.168.76.0/24 + IPv6CIDR: fd95:71cb:a3df:e586::/64 + IPv6LLPrefix: fe80::a3df:0/112 MTU: 1416 RecvAddr: 127.0.0.1:4100 SendAddr: 127.0.0.1:5100 @@ -16,13 +16,13 @@ NodeName: Node100 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: IJtpnkm9ytbuCukx4VBMENJKuLngo9KSsS1D60BqonQ= -ListenPort: 0 +PrivKey: a04BVvT+YbrX1ejjvMQVI6k5VRFlBkEX8tuLGWNyNrY= +ListenPort: 3100 LogLevel: LogLevel: error - LogTransit: true + LogTransit: false LogControl: true - LogNormal: true + LogNormal: false LogInternal: true LogNTP: true DynamicRoute: @@ -35,12 +35,12 @@ DynamicRoute: SaveNewPeers: true SuperNode: UseSuperNode: true - PSKey: j9dS/lYvL16svSeC5lh+ldlq2iZX2MWwZfM3NNWpULI= - EndpointV4: 127.0.0.1:3000 - PubKeyV4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= - EndpointV6: '[::1]:3000' - PubKeyV6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= - EndpointEdgeAPIUrl: http://127.0.0.1:3000/eg_api + PSKey: Gfp2RkPNrKTeGKrCJNEvSyiBqYYRmzVnVG6CBuUKUNc= + EndpointV4: 127.0.0.1:3456 + PubKeyV4: Id/VoZ6HmTU3FSqhxBUswfuHHB0mQxfzcbdoJNGBRzQ= + EndpointV6: :3456 + PubKeyV6: 40tADRhJTvaortwE5Ur4qNXhP+SOMX7ZuSvl251Yxnc= + EndpointEdgeAPIUrl: http://127.0.0.1:3456/eg_net/eg_api SkipLocalIP: false SuperNodeInfoTimeout: 50 P2P: @@ -48,8 +48,10 @@ DynamicRoute: SendPeerInterval: 20 GraphRecalculateSetting: StaticMode: false - JitterTolerance: 20 + ManualLatency: {} + JitterTolerance: 50 JitterToleranceMultiplier: 1.1 + DampingResistance: 0 TimeoutCheckInterval: 5 RecalculateCoolDown: 5 NTPConfig: @@ -80,4 +82,4 @@ DynamicRoute: - 3.pool.ntp.org NextHopTable: {} ResetConnInterval: 86400 -Peers: [] \ No newline at end of file +Peers: [] diff --git a/example_config/super_mode/Node_super.yaml b/example_config/super_mode/Node_super.yaml new file mode 100644 index 0000000..607488f --- /dev/null +++ b/example_config/super_mode/Node_super.yaml @@ -0,0 +1,55 @@ +NodeName: NodeSP +PostScript: "" +PrivKeyV4: 2P0mV5RkpFFyg+aLPK841sml5RobQGrxAV5ld4En9Kk= +PrivKeyV6: 9JrdnAk1ljXUTn9VFb1uFyey20tQEQuzJJtVueM4vsw= +ListenPort: 3456 +ListenPort_EdgeAPI: "3456" +ListenPort_ManageAPI: "3456" +API_Prefix: /eg_net/eg_api +RePushConfigInterval: 30 +HttpPostInterval: 50 +PeerAliveTimeout: 70 +SendPingInterval: 15 +LogLevel: + LogLevel: normal + LogTransit: false + LogNormal: false + LogControl: true + LogInternal: true + LogNTP: true +Passwords: + ShowState: passwd_showstate + AddPeer: passwd_addpeer + DelPeer: passwd_delpeer + UpdatePeer: passwd_updatepeer + UpdateSuper: passwd_updatesuper +GraphRecalculateSetting: + StaticMode: false + ManualLatency: {} + JitterTolerance: 30 + JitterToleranceMultiplier: 1.01 + DampingResistance: 0.9 + TimeoutCheckInterval: 5 + RecalculateCoolDown: 5 +NextHopTable: {} +EdgeTemplate: "" +UsePSKForInterEdge: true +Peers: +- NodeID: 1 + Name: Node001 + PubKey: awnuKYQOgCywkJbHAynqMzKi5QEGsG0w4iBy2Ja1MDQ= + PSKey: j2f9Fhdhw2O2zLqUqfL5nTFStjVWPnEXpw7Iqz6VX9M= + AdditionalCost: 10 + SkipLocalIP: false +- NodeID: 2 + Name: Node002 + PubKey: WUyblc/DZzPNU5sOQQS2lS0aP53zFEVNjqCHjkhkdzE= + PSKey: iCw096jsW2aWyMwPyzVEvL8C3XXqMpB+jOeWqDC34uU= + AdditionalCost: 10 + SkipLocalIP: false +- NodeID: 100 + Name: Node_100 + PubKey: Bax6wOJpisSVJtrU92ujn8D/2oGUyhyPrKTXkHbGamM= + PSKey: Gfp2RkPNrKTeGKrCJNEvSyiBqYYRmzVnVG6CBuUKUNc= + AdditionalCost: 1000 + SkipLocalIP: false diff --git a/example_config/super_mode/README_zh.md b/example_config/super_mode/README_zh.md index e813824..41225b2 100644 --- a/example_config/super_mode/README_zh.md +++ b/example_config/super_mode/README_zh.md @@ -1,42 +1,81 @@ # Etherguard -[English](README.md) - -Super Mode的[範例配置檔](./)的說明文件 -在了解Super Mode的運作之前,建議您先閱讀[Static Mode的運作](../static_mode/README_zh.md)方法,再閱讀本篇會比較好 +[English](README.md) | [中文](#) ## Super Mode Super Mode是受到[n2n](https://github.com/ntop/n2n)的啟發 -分為super node和edge node兩種節點 +分為SuperNode和EdgeNode兩種節點 -全部節點都會和supernode建立連線 -藉由supernode交換其他節點的資訊,以及udp打洞 -由supernode執行[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法),並把計算結果分發給全部edge node +全部節點都會和SuperNode建立連線 +藉由SuperNode交換其他節點的資訊,以及udp打洞 +由SuperNode執行[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法),並把計算結果分發給全部edge node -在edge node的super模式下,設定檔裡面的`nexthoptable`以及`peers`是無效的。 -這些資訊都是從super node上面下載 -同時,supernode會幫每個連線生成Preshared Key,分發給edge使用(如果`usepskforinteredge`有啟用的話)。 -```golang -psk = shs256("PubkeyPeerA" + "PubkeyPeerB" + "主廚特調當季精選海鹽")[:32] + +## Quick start + +首先按需求修改`gensuper.yaml` + +```yaml +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~10,11,19,23,29,31,55~66,88~99]" + MacAddress prefix: "" # 留空隨機產生 + IPv4 range: 192.168.76.0/24 # IP的部分可以直接省略沒關係 + IPv6 range: fd95:71cb:a3df:e586::/64 # 這個欄位唯一的目的只是在啟動以後,調用ip命令,幫tap接口加個ip + IPv6 LL range: fe80::a3df:0/112 # 和VPN本身運作完全無關 +``` +接著執行這個,就會生成所需設定檔了。 +``` +$ ./etherguard-go -mode gencfg -cfgmode super -config example_config/super_mode/gensuper.yaml ``` +把一個super,2個edge分別搬去三台機器 +或是2台機器,super和edge可以是同一台 + +在Supernode執行 +``` +./etherguard-go -config [設定檔位置] -mode super +``` +在EdgeNode執行 +``` +./etherguard-go -config [設定檔位置] -mode edge +``` + +## Documentation + +在了解Super Mode的運作之前,建議您先閱讀[Static Mode的運作](../static_mode/README_zh.md)方法,再閱讀本篇會比較好 + + +在EdgeNode的SuperMode下,設定檔裡面的`NextHopTable`以及`Peers`是無效的。 +這些資訊都是從SuperNode上面下載 +同時,SuperNode會幫每個連線生成pre-shared key,分發給edge使用(如果啟用`UsePSKForInterEdge`的話)。 + ### SuperMsg -但是比起Static mode,Super mode引入了一種新的 `終點ID` 叫做 `SuperMsg`。 -所有送往Super node的封包都會是這種類型。 -這種封包不會在edge node之間傳播,收到也會不會轉給任何人,如同`終點ID == 自己`一般 +但是比起StaticMode,SuperMode引入了一種新的 `終點ID` 叫做 `NodeID_SuperNode`。 +所有送往SuperNode的封包都會是這種類型。 +這種封包不會在EdgeNode之間傳播,收到也會不會轉給任何人,如同`終點ID == 自己`一般 ## Control Message -從Super mode開始,我們有了Static mode不存在的Control Message。他會控制EtherGuard一些行為 -在Super mode下,我們不會轉發任何控制消息。 我們只會直接接收或發送給目標。 +從SuperMode開始,我們有了StaticMode不存在的Control Message。他會控制EtherGuard一些行為 +在SuperMode下,我們不會轉發任何控制消息。 我們只會直接接收或發送給目標。 下面列出Super Mode會出現的Control message ### Register 具體運作方式類似這張圖 ![Register運作流程](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS01.png) -1. edge node發送`Register`給super node -2. super node收到以後就知道這個edge的endpoint IP和埠號。 +1. EdgeNode發送`Register`給sSuperNode +2. SuperNode收到以後就知道這個EdgeNode的Endpoint IP和Port number。 3. 更新進資料庫以後發布`UpdatePeerMsg`。 -4. 其他edge node收到以後就用HTTP API去下載完整的peer list。並且把自己沒有的peer通通加到本地 +4. 其他edge node收到以後就用HTTP EdgeAPI去下載完整的peer list。並且把自己沒有的peer通通加到本地 ### Ping/Pong 有了peer list以後,接下來的運作方式類似這張圖 @@ -46,18 +85,58 @@ Edge node 會嘗試向其他所有peer發送`Ping`,裡面會攜帶節點自己 收到`Ping`,就會產生一個`Pong`,並攜帶時間差。這個時間就是單向延遲 但是他不會把`Pong`送回給原節點,而是送給Super node +### AdditionalCost +有了各個節點的延遲以後,還不會立刻計算`Floyd-Warshall`,而是要先加上`AdditionalCost` + +以這張圖片的情境為例: +![EGS08](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS08.png) +Path | Latency |Cost|Win +--------|:--------|:---|:-- +A->B->C | 3ms | 3 | +A->C | 4ms | 4 | O + +但是這個情境,3ms 4ms 只相差1ms +為了這1ms而多繞一趟實在浪費,而且轉發本身也要時間 + +每個節點有了`AdditionalCost`參數,就能設定經過這個節點轉發,所需額外增加的成本 + +假如ABC全部設定了`AdditionalCost=10` +Path | Latency |AdditionalCost|Cost|Win +--------|:--------|:-------------|:---|:-- +A->B->C | 3ms | 20 | 23 | +A->C | 4ms | 10 | 14 | O + +A->C 就換選擇直連,不會為了省下1ms而繞路 +這邊`AdditionalCost=10`可以解釋為: 必須能省下10ms,才會繞這條路 + +這個參數也有別的用途 +針對流量比較貴的節點,可以設定`AdditionalCost=10000` +別人就不會走他中轉了,而是盡量繞別的路,或是直連 +除非別條路線全掛,只剩這挑Cost 10000的路線 + +還有一個用法,全部節點都設定`AdditionalCost=10000` +無視延遲,全節點都盡量直連,打動失敗才繞路 + ### UpdateNhTable Super node收到節點們傳來的Pong以後,就知道他們的單向延遲了。接下來的運作方式類似這張圖 ![image](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS03.png) Super node收到Pong以後,就會更新它裡面的`Distance matrix`,並且重新計算轉發表 如果有變動,就發布`UpdateNhTableMsg` -其他edge node收到以後就用HTTP API去下載完整的轉發表 +其他edge node收到以後就用HTTP EdgeAPI去下載完整的轉發表 -### UpdateError -通知edges有錯誤發生,關閉egde端程式 -發生在版本號不匹被,該edge的NodeID配置錯誤,還有該Edge被刪除時觸發 +### ServerUpdate +通知EdgeNode有事情發生 +1. 關閉EdgeNode程式 + * 版本號不匹配 + * 該edge的NodeID配置錯誤 + * 該Edge被刪除 +2. 通知EdgeNode有更新 + * UpdateNhTable + * UpdatePeer + * UpdateSuperParams -### HTTP API + +## HTTP EdgeAPI 為什麼要用HTTP額外下載呢?直接`UpdateXXX`夾帶資訊不好嗎? 因為udp是不可靠協議,能攜帶的內容量也有上限。 但是peer list包含了全部的peer資訊,長度不是固定的,可能超過 @@ -68,12 +147,15 @@ Super node收到Pong以後,就會更新它裡面的`Distance matrix`,並且 這樣super node收到HTTP API看到`state hash`就知道這個edge node確實有收到`UpdateXXX`了。 不然每隔一段時間就會重新發送`UpdateXXX`給該節點 +預設配置是走HTTP。但為**了你的安全著想,建議使用nginx反代理成https** +有想過SuperNode開發成直接支援https,但是證書動態更新太麻煩就沒有做了 + ## HTTP Manage API -HTTP還有一些個API,給前端使用,幫助管理整個網路 +HTTP還有5個Manage API,給前端使用,幫助管理整個網路 ### super/state ```bash -curl "http://127.0.0.1:3000/eg_api/manage/super/state?Password=passwd_showstate" +curl "http://127.0.0.1:3456/eg_net/eg_api/manage/super/state?Password=passwd_showstate" ``` 可以給前端看的,用來顯示現在各節點之間的單向延遲狀況 之後可以用來畫力導向圖。 @@ -145,10 +227,10 @@ curl "http://127.0.0.1:3000/eg_api/manage/super/state?Password=passwd_showstate" 再來是新增peer,可以不用重啟Supernode就新增Peer 範例: -``` -curl -X POST "http://127.0.0.1:3000/eg_api/manage/peer/add?Password=passwd_addpeer" \ +```bash +curl -X POST "http://127.0.0.1:3456/eg_net/eg_api/manage/peer/add?Password=passwd_addpeer" \ -H "Content-Type: application/x-www-form-urlencoded" \ - -d "NodeID=100&Name=Node_100&PubKey=6SuqwPH9pxGigtZDNp3PABZYfSEzDaBSwuThsUUAcyM=&AdditionalCost=1000&PSKey=j9dS%2FlYvL16svSeC5lh%2Bldlq2iZX2MWwZfM3NNWpULI%3D&SkipLocalIP=false" + -d "NodeID=100&Name=Node_100&PubKey=Bax6wOJpisSVJtrU92ujn8D%2F2oGUyhyPrKTXkHbGamM%3D&AdditionalCost=1000&PSKey=Gfp2RkPNrKTeGKrCJNEvSyiBqYYRmzVnVG6CBuUKUNc%3D&SkipLocalIP=false" ``` 參數: 1. URL query: Password: 新增peer用的密碼,在設定檔配置 @@ -172,13 +254,13 @@ curl -X POST "http://127.0.0.1:3000/eg_api/manage/peer/add?Password=passwd_addpe 設計上分別是給管理員使用,或是給加入網路的人,想離開網路使用 使用Password刪除可以刪除任意節點,以上面新增的節點為例,使用這個API即可刪除剛剛新增的節點 -``` -curl "http://127.0.0.1:3000/eg_api/manage/peer/del?Password=passwd_delpeer&NodeID=100" +```bash +curl "http://127.0.0.1:3456/eg_net/eg_api/manage/peer/del?Password=passwd_delpeer&NodeID=100" ``` 也可以使用privkey刪除,同上,但是只要附上privkey參數就好 -``` -curl "http://127.0.0.1:3000/eg_api/manage/peer/del?PrivKey=IJtpnkm9ytbuCukx4VBMENJKuLngo9KSsS1D60BqonQ=" +```bash +curl "http://127.0.0.1:3456/eg_net/eg_api/manage/peer/del?PrivKey=a04BVvT%2BYbrX1ejjvMQVI6k5VRFlBkEX8tuLGWNyNrY%3D" ``` 參數: @@ -193,65 +275,121 @@ curl "http://127.0.0.1:3000/eg_api/manage/peer/del?PrivKey=IJtpnkm9ytbuCukx4VBME ### peer/update 更新節點的一些參數 -``` -curl -X POST "http://127.0.0.1:12369/eg_net/eg_api/manage/peer/update?Password=e05znou1_updatepeer&NodeID=1" \ +```bash +curl -X POST "http://127.0.0.1:3456/eg_net/eg_api/eg_api/manage/peer/update?Password=e05znou1_updatepeer&NodeID=1" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "AdditionalCost=10&SkipLocalIP=false" ``` ### super/update 更新SuperNode的一些參數 -``` -curl -X POST "http://127.0.0.1:12369/eg_net/eg_api/manage/super/update?Password=e05znou1_updatesuper" \ +```bash +curl -X POST "http://127.0.0.1:3456/eg_net/eg_api/eg_api/manage/super/update?Password=e05znou1_updatesuper" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "SendPingInterval=15&HttpPostInterval=60&PeerAliveTimeout=70" ``` +### SuperNode Config Parameter -## Config Parameters +Key | Description +-------------- |:----- +NodeName| 節點名稱 +PostScript | 初始化完畢之後要跑的腳本 +PrivKeyV4 | IPv4通訊使用的私鑰 +PrivKeyV6 | IPv6通訊使用的私鑰 +ListenPort | udp監聽埠 +ListenPort_EdgeAPI | HTTP EdgeAPI 的監聽埠 +ListenPort_ManageAPI| HTTP ManageAPI 的監聽埠 +API_Prefix | HTTP API prefix +RePushConfigInterval| 重新push`UpdateXXX`的間格 +HttpPostInterval | EdgeNode 使用EdgeAPI回報狀態的頻率 +PeerAliveTimeout | 判定斷線Timeout +SendPingInterval | EdgeNode 之間使用Ping/Pong測量延遲的間格 +[LogLevel](../static_mode/README_zh.md#LogLevel)| 紀錄log +[Passwords](#Passwords) | HTTP ManageAPI 的密碼,5個API密碼是獨立的 +[GraphRecalculateSetting](#GraphRecalculateSetting) | 一些和[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法)相關的參數 +[NextHopTable](../static_mode/README_zh.md#NextHopTable) | StaticMode 模式下使用的轉發表 +EdgeTemplate | HTTP ManageAPI `peer/add` 返回的edge的參考設定檔 +UsePSKForInterEdge | 幫Edge生成PreSharedKey,供edge之間直接連線使用 +[Peers](#EdgeNodes) | EdgeNode資訊 -### Super mode的edge node有幾個參數 -1. `usesupernode`: 是否啟用Super mode -1. `pskey`: 和supernode建立連線用的Pre shared Key -1. `connurlv4`: Super node的IPv4連線地址 -1. `pubkeyv4`: Super node的IPv4工鑰 -1. `connurlv6`: Super node的IPv6連線地址 -1. `pubkeyv6`: Super node的IPv6工鑰 -1. `apiurl`: Super node的HTTP(S) API連線地址 -1. `supernodeinfotimeout`: Supernode Timeout -1. `httppostinterval`: 15 -1. `skiplocalip`: 打洞時,一律使用supernode蒐集到的外部ip,不使用edge自行回報的local ip +Passwords | Description +--------------------|:----- +ShowState | HTTP ManageAPI `super/state` 的密碼 +AddPeer | HTTP ManageAPI `peer/add` 的密碼 +DelPeer | HTTP ManageAPI `peer/del` 的密碼 +UpdatePeer | HTTP ManageAPI `peer/update` 的密碼 +UpdateSuper | HTTP ManageAPI `super/update` 的密碼 -### Super node本身的設定檔 +GraphRecalculateSetting | Description +--------------------|:----- +StaticMode | 關閉`Floyd-Warshall`演算法,只使用設定檔提供的NextHopTable`。SuperNode單純用來輔助打洞 +ManualLatency | 手動設定延遲,不採用EdgeNode回報的延遲(單位: 毫秒) +JitterTolerance | 抖動容許誤差,收到Pong以後,一個37ms,一個39ms,不會觸發重新計算
比較對象是上次更新使用的值。如果37 37 41 43 .. 100 ,每次變動一點點,總變動量超過域值還是會更新 +JitterToleranceMultiplier | 抖動容許誤差的放大係數,高ping的話允許更多誤差
https://www.desmos.com/calculator/raoti16r5n +DampingResistance | 防抖阻尼系數,`latency = latency_old * resistance + latency_in * (1-resistance)` +TimeoutCheckInterval | 週期性檢查節點的連線狀況,是否斷線需要重新規劃線路 +RecalculateCoolDown | Floyd-Warshal是O(n^3)時間複雜度,不能太常算。
設個冷卻時間
有節點加入/斷線觸發的重新計算,無視這個CoolDown -1. nodename: 節點名稱 -1. privkeyv4: ipv4用的私鑰 -1. privkeyv6: ipv6用的私鑰 -1. listenport: 監聽udp埠號 -1. loglevel: 參考 [README_zh.md](../README_zh.md) -1. repushconfiginterval: 重新push`UpdateXXX`的間格 -1. passwords: HTTP API 密碼 - 1. showstate: 節點資訊 - 1. addpeer: 新增peer - 1. delpeer: 刪除peer -1. graphrecalculatesetting: 一些和[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法)相關的參數 - 1. staticmode: 關閉Floyd-Warshall演算法,只使用一開始載入的nexthoptable。Supernode單純用來輔助打洞 - 1. recalculatecooldown: Floyd-Warshal是O(n^3)時間複雜度,不能太常算。設個冷卻時間 - 1. jittertolerance: 抖動容許誤差,收到Pong以後,一個37ms,一個39ms,不會觸發重新計算 - 1. jittertolerancemultiplier: 一樣是抖動容許誤差,但是高ping的話允許更多誤差 - https://www.desmos.com/calculator/raoti16r5n - 1. nodereporttimeout: 收到的`Pong`封包的有效期限。太久沒收到就變回Infinity - 1. timeoutcheckinterval: 固定間格檢查,有沒有人的Pong封包超過有效期限,要重算轉發表 -1. nexthoptable: 僅在`staticmode==true` 有效,手動設定的nexthoptable -1. edgetemplate: 給`addpeer`API用的。參考這個設定檔,顯示一個範例設定檔給edge -1. usepskforinteredge: 是否啟用edge間pre shares key通信。若啟用則幫edge們自動生成PSK -1. peers: Peer列表,參考 [README_zh.md](../README_zh.md) - 1. nodeid: Peer的節點ID - 1. name: Peer名稱(顯示在前端) - 1. pubkey: peer 公鑰 - 1. pskey: preshared key 該peer和本Supernode連線的PSK - 1. additionalcost: 此節點進行封包轉發的額外成本。單位: 毫秒 +Peers | Description +--------------------|:----- +NodeID | 節點ID +PubKey | 公鑰 +PSKey | 預共享金鑰 +[AdditionalCost](#AdditionalCost) | 繞路成本(單位: 毫秒)
設定-1代表使用EdgeNode自身設定 +SkipLocalIP | 打洞時,不使用EdgeNode回報的本地IP,僅使用SuperNode蒐集到的外部IP +### EdgeNode Config Parameter + +Key | Description +-------------- |:----- +[Interface](../static_mode/README_zh.md#Interface)| 接口相關設定。VPN有兩端,一端是VPN網路,另一端則是本地接口 +NodeID | 節點ID。節點之間辨識身分用的,同一網路內節點ID不能重複 +NodeName | 節點名稱 +PostScript | 初始化完畢之後要跑的腳本 +DefaultTTL | TTL,etherguard層使用,和乙太層不共通 +L2FIBTimeout | MacAddr-> NodeID 查找表的 timeout(秒) ,類似ARP table +PrivKey | 私鑰,和wireguard規格一樣 +ListenPort | 監聽的udp埠 +[LogLevel](../static_mode/README_zh.md#LogLevel)| 紀錄log +[DynamicRoute](#DynamicRoute) | 動態路由相關設定 +NextHopTable | 轉發表, SuperMode由SuperNode計算,EdgeNode用不到 +ResetConnInterval | 如果對方是動態ip就要用這個。每隔一段時間就會重置連線,重新解析域名 +[Peers](#Peers) | 鄰居節點,SuperMode從SuperNode計算,EdgeNode用不到 + +DynamicRoute | Description +--------------------|:----- +SendPingInterval | 發送Ping訊息的間隔(秒) +PeerAliveTimeout | 每次收到封包就重置,超過時間(秒)沒收到就標記該peer離線 +DupCheckTimeout | 重複封包檢查的timeout(秒)
完全相同的封包收第二次會被丟棄 +ConnTimeOut | 檢查peer離線的時間間格
如果標記離線,就切換下一個endpoint
SuperNode可能傳了多個endpoint過來 +ConnNextTry | 切換下一個endpoint的間隔 +[AdditionalCost](#AdditionalCost) | 繞路成本(毫秒)。僅限SuperNode設定-1時生效 +SaveNewPeers | 是否把下載來的鄰居資訊存到本地設定檔裡面 +[SuperNode](#SuperNode) | SuperNode相關設定 +P2P | P2P相關設定,SuperMode用不到 +[NTPConfig](#NTPConfig) | NTP時間同步相關設定 + +SuperNode | Description +---------------------|:----- +UseSuperNode | 是否啟用SuperNode +PSKey | 和SuperNode通訊用的PreShared Key +EndpointV4 | SuperNode的IPv4 Endpoint +PubKeyV4 | SuperNode的IPv4公鑰 +EndpointV6 | SuperNode的IPv6 Endpoint +PubKeyV6 | SuperNode的IPv6公鑰 +EndpointEdgeAPIUrl | SuperNode的EdgeAPI存取路徑 +SkipLocalIP | 不回報本地IP,避免和其他Edge內網直連 +SuperNodeInfoTimeout | 實驗性選項,SuperNode離線超時,切換成P2P模式
需先打開P2P模式
`UseP2P=false`本選項無效
P2P模式尚未測試,穩定性未知,不推薦使用 + + +NTPConfig | Description +--------------------|:----- +UseNTP | 是否使用NTP同步時間 +MaxServerUse | 向多少NTP伺服器發送請求 +SyncTimeInterval | 多久同步一次時間 +NTPTimeout | NTP伺服器連線Timeout +Servers | NTP伺服器列表 ## V4 V6 兩個公鑰 為什麼要分開IPv4和IPv6呢? @@ -284,12 +422,14 @@ Relay node其實也是一個edge node,只不過被設定成為interface=dummy 因為如果用127.0.0.1連接supernode,supernode看到封包的src IP就是127.0.0.1,就會把127.0.0.1分發給`Node_1`和`Node_2` `Node_1`和`Node_2`看到`Node_R`的連線地址是`127.0.0.1`,就連不上了 -## Quick start -執行此範例設定檔(請開三個terminal): +#### Run example config + +在**不同terminal**分別執行以下命令 + ```bash -./etherguard-go -config example_config/super_mode/s1.yaml -mode super -./etherguard-go -config example_config/super_mode/n1.yaml -mode edge -./etherguard-go -config example_config/super_mode/n2.yaml -mode edge +./etherguard-go -config example_config/super_mode/Node_super.yaml -mode super +./etherguard-go -config example_config/super_mode/Node_edge001.yaml -mode edge +./etherguard-go -config example_config/super_mode/Node_edge002.yaml -mode edge ``` 因為是stdio模式,stdin會讀入VPN網路 請在其中一個edge視窗中鍵入 diff --git a/example_config/super_mode/gensuper.yaml b/example_config/super_mode/gensuper.yaml index 54489f8..e3e0793 100644 --- a/example_config/super_mode/gensuper.yaml +++ b/example_config/super_mode/gensuper.yaml @@ -1,15 +1,15 @@ -Config output dir: /tmp/eg_gen +Config output dir: /tmp/eg_gen_super ConfigTemplate for super node: "" ConfigTemplate for edge node: "" -Network name: eg_net +Network name: EgNet 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 + Endpoint(IPv4)(optional): 127.0.0.1 + Endpoint(IPv6)(optional): + Endpoint(EdgeAPI): http://127.0.0.1:3456/eg_net/eg_api Edge Node: - Node IDs: "[1~10,11,19,23,29,31,55~66,88~99]" + Node IDs: "[1~2,100]" MacAddress prefix: "" IPv4 range: 192.168.76.0/24 IPv6 range: fd95:71cb:a3df:e586::/64 diff --git a/example_config/super_mode/s1.yaml b/example_config/super_mode/s1.yaml deleted file mode 100644 index 2ee7e03..0000000 --- a/example_config/super_mode/s1.yaml +++ /dev/null @@ -1,47 +0,0 @@ -NodeName: NodeSuper -PostScript: "" -PrivKeyV4: mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk= -PrivKeyV6: +EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I= -ListenPort: 3000 -ListenPort_EdgeAPI: "3000" -ListenPort_ManageAPI: "3000" -API_Prefix: /eg_api -RePushConfigInterval: 30 -HttpPostInterval: 50 -PeerAliveTimeout: 70 -SendPingInterval: 15 -LogLevel: - LogLevel: normal - LogTransit: true - LogControl: true - LogNormal: false - LogInternal: true - LogNTP: false -Passwords: - ShowState: passwd_showstate - AddPeer: passwd_addpeer - DelPeer: passwd_delpeer - UpdatePeer: passwd_updatepeer - UpdateSuper: passwd_updatesuper -GraphRecalculateSetting: - StaticMode: false - JitterTolerance: 5 - JitterToleranceMultiplier: 1.01 - TimeoutCheckInterval: 5 - RecalculateCoolDown: 5 -NextHopTable: {} -EdgeTemplate: example_config/super_mode/n1.yaml -UsePSKForInterEdge: true -Peers: -- NodeID: 1 - Name: Node_01 - PubKey: ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I= - PSKey: iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI= - AdditionalCost: 10 - SkipLocalIP: false -- NodeID: 2 - Name: Node_02 - PubKey: dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk= - PSKey: juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs= - AdditionalCost: 10 - SkipLocalIP: false diff --git a/example_config/super_mode/n1_fd.yaml b/example_config/super_mode/testfd/n1_fd.yaml similarity index 100% rename from example_config/super_mode/n1_fd.yaml rename to example_config/super_mode/testfd/n1_fd.yaml diff --git a/example_config/super_mode/n1_test_fd_mode.py b/example_config/super_mode/testfd/n1_test_fd_mode.py similarity index 100% rename from example_config/super_mode/n1_test_fd_mode.py rename to example_config/super_mode/testfd/n1_test_fd_mode.py diff --git a/example_config/super_mode/n1_test_fd_mode2.go b/example_config/super_mode/testfd/n1_test_fd_mode2.go similarity index 100% rename from example_config/super_mode/n1_test_fd_mode2.go rename to example_config/super_mode/testfd/n1_test_fd_mode2.go diff --git a/example_config/super_mode/n1_test_fd_mode2.py b/example_config/super_mode/testfd/n1_test_fd_mode2.py similarity index 100% rename from example_config/super_mode/n1_test_fd_mode2.py rename to example_config/super_mode/testfd/n1_test_fd_mode2.py diff --git a/gencfg/gencfgNM.go b/gencfg/gencfgNM.go index 111a81f..763d184 100644 --- a/gencfg/gencfgNM.go +++ b/gencfg/gencfgNM.go @@ -92,17 +92,18 @@ func GenNMCfg(NMCinfigPath string, printExample bool) (err error) { if !all_verts[NodeID] { return fmt.Errorf("duplicate definition: NodeID %v ", NodeID) } - _, err = conn.LookupIP(endpoint, 0) - if err != nil { - return err + if endpoint != "" { + _, err = conn.LookupIP(endpoint, 0) + if err != nil { + return err + } } pri, pub := device.RandomKeyPair() edge_infos[NodeID] = edge_info{ - Endpoint: endpoint, - PrivKey: pri.ToString(), - PubKey: pub.ToString(), - PersistentKeepalive: edgeinfo.PersistentKeepalive, - ConnectedEdge: make(map[mtypes.Vertex]bool), + Endpoint: endpoint, + PrivKey: pri.ToString(), + PubKey: pub.ToString(), + ConnectedEdge: make(map[mtypes.Vertex]bool), } all_verts[NodeID] = false if NodeID > MaxNodeID { @@ -118,7 +119,7 @@ func GenNMCfg(NMCinfigPath string, printExample bool) (err error) { s := edge.Src_nodeID d := edge.Dst_nodeID if len(edge_infos[s].Endpoint)+len(edge_infos[d].Endpoint) == 0 { - return fmt.Errorf("there are an edge between node %v and %v, but non of them have endpoint", s, d) + return fmt.Errorf("there are an edge between node [%v , %v], but non of them have endpoint", s, d) } edge_infos[s].ConnectedEdge[d] = true edge_infos[d].ConnectedEdge[s] = true @@ -132,7 +133,7 @@ func GenNMCfg(NMCinfigPath string, printExample bool) (err error) { pbyte := mtypes.RandomBytes(4, []byte{0xaa, 0xbb, 0xcc, 0xdd}) pbyte[0] &^= 0b00000001 pbyte[0] |= 0b00000010 - NMCfg.EdgeNode.MacPrefix = fmt.Sprintf("%X:%X:%X:%X", pbyte[0], pbyte[1], pbyte[2], pbyte[3]) + NMCfg.EdgeNode.MacPrefix = fmt.Sprintf("%02X:%02X:%02X:%02X", pbyte[0], pbyte[1], pbyte[2], pbyte[3]) } dist, next, err := g.FloydWarshall(false) @@ -177,6 +178,8 @@ func GenNMCfg(NMCinfigPath string, printExample bool) (err error) { econfig.NodeID = NodeID idstr := fmt.Sprintf("%0"+strconv.Itoa(len(MaxNodeID.ToString()))+"d", NodeID) econfig.NodeName = NMCfg.NetworkName + idstr + PersistentKeepalive := uint32(30) + econfig.ListenPort = 0 if Edge.Endpoint != "" { ps := strings.Split(Edge.Endpoint, ":") pss := ps[len(ps)-1] @@ -185,6 +188,7 @@ func GenNMCfg(NMCinfigPath string, printExample bool) (err error) { return err } econfig.ListenPort = int(port) + PersistentKeepalive = 0 } econfig.Peers = make([]mtypes.PeerInfo, 0) for CNodeID, _ := range Edge.ConnectedEdge { @@ -193,7 +197,7 @@ func GenNMCfg(NMCinfigPath string, printExample bool) (err error) { PubKey: edge_infos[CNodeID].PubKey, PSKey: pskdb.GetPSK(NodeID, CNodeID).ToString(), EndPoint: edge_infos[CNodeID].Endpoint, - PersistentKeepalive: Edge.PersistentKeepalive, + PersistentKeepalive: PersistentKeepalive, Static: true, }) } diff --git a/gencfg/gencfgSM.go b/gencfg/gencfgSM.go index f90ef39..7a19753 100644 --- a/gencfg/gencfgSM.go +++ b/gencfg/gencfgSM.go @@ -220,7 +220,7 @@ func GenSuperCfg(SMCinfigPath string, printExample bool) (err error) { pbyte := mtypes.RandomBytes(4, []byte{0xaa, 0xbb, 0xcc, 0xdd}) pbyte[0] &^= 0b00000001 pbyte[0] |= 0b00000010 - MacPrefix = fmt.Sprintf("%X:%X:%X:%X", pbyte[0], pbyte[1], pbyte[2], pbyte[3]) + MacPrefix = fmt.Sprintf("%02X:%02X:%02X:%02X", pbyte[0], pbyte[1], pbyte[2], pbyte[3]) } IPv4Block := SMCfg.EdgeNode.IPv4Range @@ -264,6 +264,7 @@ func GenSuperCfg(SMCinfigPath string, printExample bool) (err error) { peerceconf.DynamicRoute.SuperNode.EndpointV4 = EndpointV4 + ":" + ListenPort peerceconf.DynamicRoute.SuperNode.EndpointV6 = EndpointV6 + ":" + ListenPort peerceconf.DynamicRoute.SuperNode.EndpointEdgeAPIUrl = EndpointEdgeAPIUrl + peerceconf.DynamicRoute.P2P.GraphRecalculateSetting.DampingResistance = 0 peerceconf.Interface.MacAddrPrefix = MacPrefix peerceconf.Interface.IPv4CIDR = IPv4Block peerceconf.Interface.IPv6CIDR = IPv6Block diff --git a/gencfg/types.go b/gencfg/types.go index 46dd708..f315d56 100644 --- a/gencfg/types.go +++ b/gencfg/types.go @@ -68,5 +68,4 @@ type edge_info struct { ConnectedEdge map[mtypes.Vertex]bool PrivKey string PubKey string - PersistentKeepalive uint32 } diff --git a/main_edge.go b/main_edge.go index 011bbd9..1ece5de 100644 --- a/main_edge.go +++ b/main_edge.go @@ -51,6 +51,9 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( if len(NodeName) > 32 { return errors.New("Node name can't longer than 32 :" + NodeName) } + if econfig.DynamicRoute.P2P.GraphRecalculateSetting.DampingResistance < 0 || econfig.DynamicRoute.P2P.GraphRecalculateSetting.DampingResistance >= 1 { + return fmt.Errorf("DampingResistance must in range [0,1) : %v", econfig.DynamicRoute.P2P.GraphRecalculateSetting.DampingResistance) + } var logLevel int switch econfig.LogLevel.LogLevel { case "verbose", "debug": diff --git a/main_httpserver.go b/main_httpserver.go index 1e7c38a..9e8303e 100644 --- a/main_httpserver.go +++ b/main_httpserver.go @@ -684,7 +684,7 @@ func manage_peeradd(w http.ResponseWriter, r *http.Request) { func manage_peerupdate(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() - toUpdate := mtypes.NodeID_Boardcast + toUpdate := mtypes.NodeID_Broadcast var err error var NodeID mtypes.Vertex @@ -856,7 +856,7 @@ func manage_superupdate(w http.ResponseWriter, r *http.Request) { func manage_peerdel(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() - toDelete := mtypes.NodeID_Boardcast + toDelete := mtypes.NodeID_Broadcast var err error var NodeID mtypes.Vertex @@ -900,7 +900,7 @@ func manage_peerdel(w http.ResponseWriter, r *http.Request) { toDelete = peerinfo.NodeID } } - if toDelete == mtypes.NodeID_Boardcast { + if toDelete == mtypes.NodeID_Broadcast { w.WriteHeader(http.StatusNotFound) w.Write([]byte(fmt.Sprintf("Paramater PrivKey: \"%v\" not found", PubKey))) return diff --git a/main_super.go b/main_super.go index 8294f99..95214cb 100644 --- a/main_super.go +++ b/main_super.go @@ -100,6 +100,9 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) if sconfig.RePushConfigInterval <= 0 { return fmt.Errorf("RePushConfigInterval must > 0 : %v", sconfig.RePushConfigInterval) } + if sconfig.GraphRecalculateSetting.DampingResistance < 0 || sconfig.GraphRecalculateSetting.DampingResistance >= 1 { + return fmt.Errorf("DampingResistance must in range [0,1) : %v", sconfig.GraphRecalculateSetting.DampingResistance) + } var logLevel int switch sconfig.LogLevel.LogLevel { diff --git a/mtypes/config.go b/mtypes/config.go index 4fea539..d70092f 100644 --- a/mtypes/config.go +++ b/mtypes/config.go @@ -10,11 +10,11 @@ import ( type Vertex uint16 const ( - NodeID_Boardcast Vertex = math.MaxUint16 - iota // Normal boardcast, boardcast with route table + NodeID_Broadcast Vertex = math.MaxUint16 - iota // Normal boardcast, boardcast with route table NodeID_AllPeer Vertex = math.MaxUint16 - iota // p2p mode: boardcast to every know peer and prevent dup. super mode: send to supernode NodeID_SuperNode Vertex = math.MaxUint16 - iota - NodeID_Invalid Vertex = math.MaxUint16 - iota - NodeID_Special Vertex = NodeID_Invalid + NodeID_Invalid Vertex = math.MaxUint16 - iota + NodeID_Special Vertex = NodeID_Invalid ) type EdgeConfig struct { @@ -99,15 +99,15 @@ type SuperPeerInfo struct { type LoggerInfo struct { LogLevel string `yaml:"LogLevel"` LogTransit bool `yaml:"LogTransit"` - LogControl bool `yaml:"LogControl"` LogNormal bool `yaml:"LogNormal"` + LogControl bool `yaml:"LogControl"` LogInternal bool `yaml:"LogInternal"` LogNTP bool `yaml:"LogNTP"` } func (v *Vertex) ToString() string { switch *v { - case NodeID_Boardcast: + case NodeID_Broadcast: return "Boardcast" case NodeID_AllPeer: return "Control" diff --git a/path/header.go b/path/header.go index 63e50dc..926a54a 100644 --- a/path/header.go +++ b/path/header.go @@ -32,6 +32,64 @@ const ( BroadcastPeer ) +func (v Usage) IsNormal() bool { + return v == NormalPacket +} + +func (v Usage) IsControl() bool { + switch v { + case Register: + return true + case ServerUpdate: + return true + case PingPacket: + return true + case PongPacket: + return true + case QueryPeer: + return true + case BroadcastPeer: + return true + default: + return false + } +} + +func (v Usage) IsControl_Super2Edge() bool { + switch v { + case ServerUpdate: + return true + default: + return false + } +} + +func (v Usage) IsControl_Edge2Super() bool { + switch v { + case Register: + return true + case PongPacket: + return true + default: + return false + } +} + +func (v Usage) IsControl_Edge2Edge() bool { + switch v { + case PingPacket: + return true + case PongPacket: + return true + case QueryPeer: + return true + case BroadcastPeer: + return true + default: + return false + } +} + func NewEgHeader(pac []byte) (e EgHeader, err error) { if len(pac) != EgHeaderLen { err = errors.New("invalid packet size") diff --git a/path/path.go b/path/path.go index 19da8c0..c97d189 100644 --- a/path/path.go +++ b/path/path.go @@ -189,7 +189,7 @@ func (g *IG) UpdateLatencyMulti(pong_info []mtypes.PongMsg, recalculate bool, ch newval := pong_msg.Timediff if _, ok := g.gsetting.ManualLatency[u]; ok { if _, ok := g.gsetting.ManualLatency[u][v]; ok { - newval = g.gsetting.ManualLatency[u][v] + newval = g.gsetting.ManualLatency[u][v] / 1000 // s to ms } } w := newval @@ -206,7 +206,7 @@ func (g *IG) UpdateLatencyMulti(pong_info []mtypes.PongMsg, recalculate bool, ch g.edgelock.Unlock() oldval := g.OldWeight(u, v, false) g.edgelock.Lock() - if oldval != mtypes.Infinity { + if oldval != mtypes.Infinity && g.IsSuperMode && g.gsetting.DampingResistance > 0 { w = oldval*g.gsetting.DampingResistance + newval*(1-g.gsetting.DampingResistance) } should_update = should_update || g.ShouldUpdate(oldval, w, false) diff --git a/tap/tap_stdio.go b/tap/tap_stdio.go index 37fc722..02d35bd 100644 --- a/tap/tap_stdio.go +++ b/tap/tap_stdio.go @@ -100,10 +100,11 @@ func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) { } } // read a packet from the device (without any additional headers) func (tap *StdIOTap) Write(buf []byte, offset int) (size int, err error) { - packet := make([]byte, len(buf[offset:])) - copy(packet, buf[offset:]) + packet := buf[offset:] switch tap.L2mode { case KeyboardDebug: + packet = make([]byte, len(buf[offset:])) + copy(packet, buf[offset:]) src := Mac2charForm(packet[6:12]) dst := Mac2charForm(packet[0:6]) packet[10] = dst