mirror of
https://github.com/KusakabeShi/EtherGuard-VPN.git
synced 2025-02-16 15:29:15 +01:00
std bind, http api, hole punching, domain endpoint, faster reaction, psk
This commit is contained in:
parent
1fcc1bbfa1
commit
2ac7c0547d
@ -16,6 +16,9 @@ Here is the solution. This VPN `Etherguard` can collect all the single-way lenta
|
||||
|
||||
```bash
|
||||
Usage of ./etherguard-go:
|
||||
-bind string
|
||||
UDP socket bind mode. [linux|std]
|
||||
You may need this if tou want to run Etherguard under WSL. (default "linux")
|
||||
-config string
|
||||
Config path.
|
||||
-example
|
||||
@ -26,6 +29,7 @@ Usage of ./etherguard-go:
|
||||
Running mode. [super|edge|solve]
|
||||
-no-uapi
|
||||
Do not use UAPI
|
||||
With UAPI, you can check etherguard status by `wg` command
|
||||
-version
|
||||
Show version
|
||||
```
|
||||
|
@ -20,6 +20,9 @@ OSPF能夠根據cost自動選路
|
||||
|
||||
```bash
|
||||
Usage of ./etherguard-go-vpp:
|
||||
-bind string
|
||||
UDP socket bind mode. [linux|std]
|
||||
You may need this if tou want to run Etherguard under WSL. (default "linux")
|
||||
-config string
|
||||
設定檔路徑
|
||||
-example
|
||||
|
@ -99,8 +99,10 @@ func (v *Vertex) ToString() string {
|
||||
|
||||
type DynamicRouteInfo struct {
|
||||
SendPingInterval float64
|
||||
PeerAliveTimeout float64
|
||||
DupCheckTimeout float64
|
||||
ConnTimeOut float64
|
||||
ConnNextTry float64
|
||||
SaveNewPeers bool
|
||||
SuperNode SuperInfo
|
||||
P2P P2Pinfo
|
||||
@ -117,6 +119,7 @@ type NTPinfo struct {
|
||||
|
||||
type SuperInfo struct {
|
||||
UseSuperNode bool
|
||||
PSKey string
|
||||
ConnURLV4 string
|
||||
PubKeyV4 string
|
||||
ConnURLV6 string
|
||||
@ -128,7 +131,6 @@ type SuperInfo struct {
|
||||
type P2Pinfo struct {
|
||||
UseP2P bool
|
||||
SendPeerInterval float64
|
||||
PeerAliveTimeout float64
|
||||
GraphRecalculateSetting GraphRecalculateSetting
|
||||
}
|
||||
|
||||
@ -144,9 +146,8 @@ type NextHopTable map[Vertex]map[Vertex]*Vertex
|
||||
|
||||
type API_Peerinfo struct {
|
||||
NodeID Vertex
|
||||
PubKey string
|
||||
PSKey string
|
||||
Connurl map[string]bool
|
||||
Connurl map[string]int
|
||||
}
|
||||
|
||||
type API_Peers map[string]API_Peerinfo // map[PubKey]API_Peerinfo
|
||||
|
@ -65,11 +65,17 @@ type LinuxSocketBind struct {
|
||||
}
|
||||
|
||||
func NewLinuxSocketBind() Bind { return &LinuxSocketBind{sock4: -1, sock6: -1, use4: true, use6: true} }
|
||||
func NewDefaultBind() Bind { return NewLinuxSocketBind() }
|
||||
func NewCustomBind(use4 bool, use6 bool) Bind {
|
||||
func NewLinuxSocketBindAf(use4 bool, use6 bool) Bind {
|
||||
return &LinuxSocketBind{sock4: -1, sock6: -1, use4: use4, use6: use6}
|
||||
}
|
||||
|
||||
func NewDefaultBind(use4 bool, use6 bool, bindmode string) Bind {
|
||||
if bindmode == "std" {
|
||||
return NewStdNetBindAf(use4, use6)
|
||||
}
|
||||
return NewLinuxSocketBindAf(use4, use6)
|
||||
}
|
||||
|
||||
var _ Endpoint = (*LinuxSocketEndpoint)(nil)
|
||||
var _ Bind = (*LinuxSocketBind)(nil)
|
||||
|
||||
|
@ -22,9 +22,14 @@ type StdNetBind struct {
|
||||
ipv6 *net.UDPConn
|
||||
blackhole4 bool
|
||||
blackhole6 bool
|
||||
use4 bool
|
||||
use6 bool
|
||||
}
|
||||
|
||||
func NewStdNetBind() Bind { return &StdNetBind{} }
|
||||
func NewStdNetBind() Bind { return &StdNetBind{use4: true, use6: true} }
|
||||
func NewStdNetBindAf(use4 bool, use6 bool) Bind {
|
||||
return &StdNetBind{use4: use4, use6: use6}
|
||||
}
|
||||
|
||||
type StdNetEndpoint net.UDPAddr
|
||||
|
||||
@ -100,21 +105,31 @@ again:
|
||||
port := int(uport)
|
||||
var ipv4, ipv6 *net.UDPConn
|
||||
|
||||
ipv4, port, err = listenNet("udp4", port)
|
||||
if err != nil && !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
return nil, 0, err
|
||||
if bind.use4 {
|
||||
ipv4, port, err = listenNet("udp4", port)
|
||||
if uport == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 {
|
||||
ipv6.Close()
|
||||
tries++
|
||||
goto again
|
||||
}
|
||||
if err != nil && !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
ipv6.Close()
|
||||
return nil, 0, err
|
||||
}
|
||||
}
|
||||
|
||||
// Listen on the same port as we're using for ipv4.
|
||||
ipv6, port, err = listenNet("udp6", port)
|
||||
if uport == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 {
|
||||
ipv4.Close()
|
||||
tries++
|
||||
goto again
|
||||
}
|
||||
if err != nil && !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
ipv4.Close()
|
||||
return nil, 0, err
|
||||
if bind.use6 {
|
||||
// Listen on the same port as we're using for ipv4.
|
||||
ipv6, port, err = listenNet("udp6", port)
|
||||
if uport == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 {
|
||||
ipv4.Close()
|
||||
tries++
|
||||
goto again
|
||||
}
|
||||
if err != nil && !errors.Is(err, syscall.EAFNOSUPPORT) {
|
||||
ipv4.Close()
|
||||
return nil, 0, err
|
||||
}
|
||||
}
|
||||
var fns []ReceiveFunc
|
||||
if ipv4 != nil {
|
||||
|
25
conn/conn.go
25
conn/conn.go
@ -149,3 +149,28 @@ func parseEndpoint(s string) (*net.UDPAddr, error) {
|
||||
}
|
||||
return addr, err
|
||||
}
|
||||
|
||||
func LookupIP(host_port string, af int) (string, error) {
|
||||
network := "udp"
|
||||
if af == 4 {
|
||||
network = "udp4"
|
||||
} else if af == 6 {
|
||||
network = "udp6"
|
||||
}
|
||||
conn, err := net.Dial(network, host_port)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer conn.Close()
|
||||
return conn.RemoteAddr().String(), nil
|
||||
}
|
||||
|
||||
func ValidIP(ip net.IP) bool {
|
||||
for b := range ip {
|
||||
if b != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@ -69,6 +70,8 @@ type Device struct {
|
||||
IDMap map[config.Vertex]*Peer
|
||||
SuperPeer map[NoisePublicKey]*Peer
|
||||
Peer_state [32]byte
|
||||
LocalV4 net.IP
|
||||
LocalV6 net.IP
|
||||
}
|
||||
event_tryendpoint chan struct{}
|
||||
ResetConnInterval float64
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@ -36,6 +37,7 @@ type Peer struct {
|
||||
AskedForNeighbor bool
|
||||
StaticConn bool //if true, this peer will not write to config file when roaming, and the endpoint will be reset periodically
|
||||
ConnURL string
|
||||
ConnAF int //0: both, 4: ipv4 only, 6: ipv6 only
|
||||
|
||||
// These fields are accessed with atomic operations, which must be
|
||||
// 64-bit aligned even on 32-bit platforms. Go guarantees that an
|
||||
@ -76,20 +78,21 @@ type Peer struct {
|
||||
persistentKeepaliveInterval uint32 // accessed atomically
|
||||
}
|
||||
|
||||
func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex, isSpecial bool) (*Peer, error) {
|
||||
if isSpecial {
|
||||
if id >= config.Special_NodeID {
|
||||
//pass check
|
||||
} else {
|
||||
return nil, errors.New(fmt.Sprint("ID", uint32(id), "is not a special NodeID"))
|
||||
}
|
||||
} else {
|
||||
func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex, isSuper bool) (*Peer, error) {
|
||||
if isSuper == false {
|
||||
if id < config.Special_NodeID {
|
||||
//pass check
|
||||
} else {
|
||||
return nil, errors.New(fmt.Sprint("ID ", uint32(id), " is a special NodeID"))
|
||||
}
|
||||
} else {
|
||||
if id == config.SuperNodeMessage {
|
||||
//pass check
|
||||
} else {
|
||||
return nil, errors.New(fmt.Sprint("ID", uint32(id), "is not a supernode NodeID"))
|
||||
}
|
||||
}
|
||||
|
||||
if device.isClosed() {
|
||||
return nil, errors.New("device closed")
|
||||
}
|
||||
@ -311,16 +314,53 @@ func (peer *Peer) Stop() {
|
||||
}
|
||||
|
||||
func (peer *Peer) SetPSK(psk NoisePresharedKey) {
|
||||
if peer.device.IsSuperNode == false && peer.ID < config.Special_NodeID && peer.device.DRoute.P2P.UseP2P == true {
|
||||
peer.device.log.Verbosef("Preshared keys disabled in P2P mode.")
|
||||
return
|
||||
}
|
||||
peer.handshake.mutex.Lock()
|
||||
peer.handshake.presharedKey = psk
|
||||
peer.handshake.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (peer *Peer) SetEndpointFromConnURL(connurl string, af int, static bool) error {
|
||||
peer.StaticConn = static
|
||||
peer.ConnURL = connurl
|
||||
peer.ConnAF = af
|
||||
|
||||
var err error
|
||||
connurl, err = conn.LookupIP(connurl, af)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint, err := peer.device.net.bind.ParseEndpoint(connurl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
peer.StaticConn = static
|
||||
peer.ConnURL = connurl
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (peer *Peer) SetEndpointFromPacket(endpoint conn.Endpoint) {
|
||||
if peer.disableRoaming {
|
||||
return
|
||||
}
|
||||
peer.Lock()
|
||||
if peer.ID == config.SuperNodeMessage {
|
||||
conn, err := net.Dial("udp", endpoint.DstToString())
|
||||
defer conn.Close()
|
||||
if err == nil {
|
||||
IP := conn.LocalAddr().(*net.UDPAddr).IP
|
||||
if ip4 := IP.To4(); ip4 != nil {
|
||||
peer.device.peers.LocalV4 = ip4
|
||||
} else {
|
||||
peer.device.peers.LocalV6 = IP
|
||||
}
|
||||
}
|
||||
}
|
||||
peer.device.SaveToConfig(peer, endpoint)
|
||||
peer.endpoint = endpoint
|
||||
peer.Unlock()
|
||||
|
@ -7,12 +7,14 @@ import (
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
orderedmap "github.com/KusakabeSi/EtherGuardVPN/orderdmap"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
@ -253,6 +255,9 @@ func (device *Device) server_process_Pong(content path.PongMsg) error {
|
||||
|
||||
func (device *Device) process_ping(peer *Peer, content path.PingMsg) error {
|
||||
peer.LastPingReceived = time.Now()
|
||||
peer.Lock()
|
||||
//peer.endpoint_trylist.
|
||||
peer.Unlock()
|
||||
PongMSG := path.PongMsg{
|
||||
Src_nodeID: content.Src_nodeID,
|
||||
Dst_nodeID: device.ID,
|
||||
@ -279,9 +284,18 @@ func (device *Device) process_ping(peer *Peer, content path.PingMsg) error {
|
||||
header.SetDst(config.ControlMessage)
|
||||
device.SpreadPacket(make(map[config.Vertex]bool), path.PongPacket, buf, MessageTransportOffsetContent)
|
||||
}
|
||||
go device.SendPing(peer, content.RequestReply, 0, 3)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) SendPing(peer *Peer, times int, replies int, interval float32) {
|
||||
for i := 0; i < times; i++ {
|
||||
packet, usage, _ := device.GeneratePingPacket(device.ID, replies)
|
||||
device.SendPacket(peer, usage, packet, MessageTransportOffsetContent)
|
||||
time.Sleep(path.S2TD(float64(interval)))
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) process_pong(peer *Peer, content path.PongMsg) error {
|
||||
if device.DRoute.P2P.UseP2P {
|
||||
if time.Now().After(device.graph.NhTableExpire) {
|
||||
@ -324,7 +338,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
|
||||
return nil
|
||||
}
|
||||
|
||||
downloadurl := device.DRoute.SuperNode.APIUrl + "/peerinfo?PubKey=" + url.QueryEscape(device.staticIdentity.publicKey.ToString()) + "&State=" + url.QueryEscape(string(content.State_hash[:]))
|
||||
downloadurl := device.DRoute.SuperNode.APIUrl + "/peerinfo?NodeID=" + strconv.Itoa(int(device.ID)) + "&PubKey=" + url.QueryEscape(device.staticIdentity.publicKey.ToString()) + "&State=" + url.QueryEscape(string(content.State_hash[:]))
|
||||
if device.LogLevel.LogControl {
|
||||
fmt.Println("Control: Download peerinfo from :" + downloadurl)
|
||||
}
|
||||
@ -365,14 +379,13 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
|
||||
device.RemovePeer(pk)
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for PubKey, peerinfo := range peer_infos {
|
||||
if len(peerinfo.Connurl) == 0 {
|
||||
return nil
|
||||
}
|
||||
sk, err := Str2PubKey(peerinfo.PubKey)
|
||||
sk, err := Str2PubKey(PubKey)
|
||||
if err != nil {
|
||||
device.log.Errorf("Error decode base64:", err)
|
||||
return err
|
||||
@ -393,17 +406,17 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
|
||||
}
|
||||
device.NewPeer(sk, peerinfo.NodeID, false)
|
||||
thepeer = device.LookupPeer(sk)
|
||||
if peerinfo.PSKey != "" {
|
||||
pk, err := Str2PSKey(peerinfo.PSKey)
|
||||
if err != nil {
|
||||
device.log.Errorf("Error decode base64:", err)
|
||||
return err
|
||||
}
|
||||
thepeer.handshake.presharedKey = pk
|
||||
}
|
||||
if peerinfo.PSKey != "" {
|
||||
pk, err := Str2PSKey(peerinfo.PSKey)
|
||||
if err != nil {
|
||||
device.log.Errorf("Error decode base64:", err)
|
||||
return err
|
||||
}
|
||||
thepeer.SetPSK(pk)
|
||||
}
|
||||
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).Before(time.Now()) {
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.PeerAliveTimeout)).Before(time.Now()) {
|
||||
//Peer died, try to switch to this new endpoint
|
||||
for url, _ := range peerinfo.Connurl {
|
||||
thepeer.Lock()
|
||||
@ -440,7 +453,7 @@ func (device *Device) process_UpdateNhTableMsg(peer *Peer, content path.UpdateNh
|
||||
if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) {
|
||||
return nil
|
||||
}
|
||||
downloadurl := device.DRoute.SuperNode.APIUrl + "/nhtable?PubKey=" + url.QueryEscape(device.staticIdentity.publicKey.ToString()) + "&State=" + url.QueryEscape(string(content.State_hash[:]))
|
||||
downloadurl := device.DRoute.SuperNode.APIUrl + "/nhtable?NodeID=" + strconv.Itoa(int(device.ID)) + "&PubKey=" + url.QueryEscape(device.staticIdentity.publicKey.ToString()) + "&State=" + url.QueryEscape(string(content.State_hash[:]))
|
||||
if device.LogLevel.LogControl {
|
||||
fmt.Println("Control: Download NhTable from :" + downloadurl)
|
||||
}
|
||||
@ -477,7 +490,7 @@ func (device *Device) process_UpdateErrorMsg(peer *Peer, content path.UpdateErro
|
||||
}
|
||||
return nil
|
||||
}
|
||||
device.log.Errorf(content.ToString())
|
||||
device.log.Errorf(strconv.Itoa(content.ErrorCode) + ": " + content.ErrorMsg)
|
||||
if content.Action == path.Shutdown {
|
||||
device.closed <- struct{}{}
|
||||
} else if content.Action == path.Panic {
|
||||
@ -494,7 +507,7 @@ func (device *Device) RoutineSetEndpoint() {
|
||||
NextRun := false
|
||||
<-device.event_tryendpoint
|
||||
for _, thepeer := range device.peers.IDMap {
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).After(time.Now()) {
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.PeerAliveTimeout)).After(time.Now()) {
|
||||
//Peer alives
|
||||
thepeer.Lock()
|
||||
for _, key := range thepeer.endpoint_trylist.Keys() { // delete whole endpoint_trylist
|
||||
@ -503,6 +516,9 @@ func (device *Device) RoutineSetEndpoint() {
|
||||
thepeer.Unlock()
|
||||
} else {
|
||||
thepeer.RLock()
|
||||
thepeer.endpoint_trylist.Sort(func(a *orderedmap.Pair, b *orderedmap.Pair) bool {
|
||||
return a.Value().(time.Time).Before(b.Value().(time.Time))
|
||||
})
|
||||
trylist := thepeer.endpoint_trylist.Keys()
|
||||
thepeer.RUnlock()
|
||||
for _, key := range trylist { // try next endpoint
|
||||
@ -519,25 +535,23 @@ func (device *Device) RoutineSetEndpoint() {
|
||||
thepeer.endpoint_trylist.Delete(key)
|
||||
thepeer.Unlock()
|
||||
} else {
|
||||
endpoint, err := device.Bind().ParseEndpoint(connurl) //trying to bind first url in the list and wait device.DRoute.P2P.PeerAliveTimeout seconds
|
||||
if device.LogLevel.LogControl {
|
||||
fmt.Println("Control: Set endpoint to " + connurl + " for NodeID:" + thepeer.ID.ToString())
|
||||
}
|
||||
err := thepeer.SetEndpointFromConnURL(connurl, thepeer.ConnAF, thepeer.StaticConn) //trying to bind first url in the list and wait device.DRoute.P2P.PeerAliveTimeout seconds
|
||||
if err != nil {
|
||||
device.log.Errorf("Can't bind " + connurl)
|
||||
device.log.Errorf("Bind " + connurl + " failed!")
|
||||
thepeer.Lock()
|
||||
thepeer.endpoint_trylist.Delete(connurl)
|
||||
thepeer.Unlock()
|
||||
continue
|
||||
}
|
||||
if device.LogLevel.LogControl {
|
||||
fmt.Println("Control: Set endpoint to " + endpoint.DstToString() + " for NodeID:" + thepeer.ID.ToString())
|
||||
}
|
||||
thepeer.SetEndpointFromPacket(endpoint)
|
||||
NextRun = true
|
||||
thepeer.Lock()
|
||||
thepeer.endpoint_trylist.Set(key, time.Now())
|
||||
thepeer.Unlock()
|
||||
//Send Ping message to it
|
||||
packet, usage, err := device.GeneratePingPacket(device.ID)
|
||||
device.SendPacket(thepeer, usage, packet, MessageTransportOffsetContent)
|
||||
go device.SendPing(thepeer, int(device.DRoute.ConnNextTry+1), 1, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -551,7 +565,7 @@ func (device *Device) RoutineSetEndpoint() {
|
||||
break ClearChanLoop
|
||||
}
|
||||
}
|
||||
time.Sleep(path.S2TD(device.DRoute.P2P.PeerAliveTimeout))
|
||||
time.Sleep(path.S2TD(device.DRoute.ConnNextTry))
|
||||
if NextRun {
|
||||
device.event_tryendpoint <- struct{}{}
|
||||
}
|
||||
@ -563,7 +577,7 @@ func (device *Device) RoutineSendPing() {
|
||||
return
|
||||
}
|
||||
for {
|
||||
packet, usage, _ := device.GeneratePingPacket(device.ID)
|
||||
packet, usage, _ := device.GeneratePingPacket(device.ID, 0)
|
||||
device.SpreadPacket(make(map[config.Vertex]bool), usage, packet, MessageTransportOffsetContent)
|
||||
time.Sleep(path.S2TD(device.DRoute.SendPingInterval))
|
||||
}
|
||||
@ -575,11 +589,20 @@ func (device *Device) RoutineRegister() {
|
||||
}
|
||||
_ = <-device.Event_Supernode_OK
|
||||
for {
|
||||
|
||||
body, _ := path.GetByte(path.RegisterMsg{
|
||||
Node_id: device.ID,
|
||||
PeerStateHash: device.peers.Peer_state,
|
||||
NhStateHash: device.graph.NhTableHash,
|
||||
Version: device.Version,
|
||||
LocalV4: net.UDPAddr{
|
||||
IP: device.peers.LocalV4,
|
||||
Port: int(device.net.port),
|
||||
},
|
||||
LocalV6: net.UDPAddr{
|
||||
IP: device.peers.LocalV6,
|
||||
Port: int(device.net.port),
|
||||
},
|
||||
})
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
|
||||
@ -633,27 +656,27 @@ func (device *Device) RoutineResetConn() {
|
||||
}
|
||||
for {
|
||||
for _, peer := range device.peers.keyMap {
|
||||
if peer.StaticConn {
|
||||
if !peer.StaticConn { //Do not reset connecton for dynamic peer
|
||||
continue
|
||||
}
|
||||
if peer.ConnURL == "" {
|
||||
continue
|
||||
}
|
||||
endpoint, err := device.Bind().ParseEndpoint(peer.ConnURL)
|
||||
err := peer.SetEndpointFromConnURL(peer.ConnURL, peer.ConnAF, peer.StaticConn)
|
||||
if err != nil {
|
||||
device.log.Errorf("Failed to bind "+peer.ConnURL, err)
|
||||
continue
|
||||
}
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
}
|
||||
time.Sleep(time.Duration(device.ResetConnInterval))
|
||||
time.Sleep(path.S2TD(device.ResetConnInterval))
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) GeneratePingPacket(src_nodeID config.Vertex) ([]byte, path.Usage, error) {
|
||||
func (device *Device) GeneratePingPacket(src_nodeID config.Vertex, request_reply int) ([]byte, path.Usage, error) {
|
||||
body, err := path.GetByte(&path.PingMsg{
|
||||
Src_nodeID: src_nodeID,
|
||||
Time: device.graph.GetCurrentTime(),
|
||||
Src_nodeID: src_nodeID,
|
||||
Time: device.graph.GetCurrentTime(),
|
||||
RequestReply: request_reply,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, path.PingPacket, err
|
||||
@ -686,7 +709,6 @@ func (device *Device) process_RequestPeerMsg(content path.QueryPeerMsg) error {
|
||||
Request_ID: content.Request_ID,
|
||||
NodeID: peer.ID,
|
||||
PubKey: pubkey,
|
||||
PSKey: peer.handshake.presharedKey,
|
||||
ConnURL: peer.endpoint.DstToString(),
|
||||
}
|
||||
peer.handshake.mutex.RUnlock()
|
||||
@ -731,12 +753,8 @@ func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.Boardcas
|
||||
device.graph.UpdateLentancy(content.NodeID, device.ID, path.S2TD(path.Infinity), true, false)
|
||||
}
|
||||
device.NewPeer(pk, content.NodeID, false)
|
||||
thepeer = device.LookupPeer(pk)
|
||||
var pk NoisePresharedKey
|
||||
copy(pk[:], content.PSKey[:])
|
||||
thepeer.handshake.presharedKey = pk
|
||||
}
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).Before(time.Now()) {
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.PeerAliveTimeout)).Before(time.Now()) {
|
||||
//Peer died, try to switch to this new endpoint
|
||||
thepeer.Lock()
|
||||
thepeer.endpoint_trylist.Set(content.ConnURL, time.Time{}) //another gorouting will process it
|
||||
|
@ -68,4 +68,10 @@ P2P模式也有幾個參數
|
||||
1. nodereporttimeout: 收到的`Pong`封包的有效期限。太久沒收到就變回Infinity
|
||||
1. recalculatecooldown: Floyd-Warshal是O(n^3)時間複雜度,不能太常算。設個冷卻時間
|
||||
|
||||
## Note
|
||||
P2P模式下,PSK是禁用的。因為n個節點有n(n-1)/2的連線,每個連線都要使用不同PSK
|
||||
又不像static mode提前設好,peer數固定不再變動
|
||||
也不像super mode,有中心伺服器統一分發
|
||||
每對peer要協商出一個PSK有難度,因此我設定禁用PSK了,只用wireguard原本的加密系統
|
||||
|
||||
**最後,P2P模式我還沒有大規模測試過,穩定性不知如何。PR is welecome**
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: true
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: true
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: true
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: true
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: true
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: true
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
@ -21,8 +21,10 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 20
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: false
|
||||
supernode:
|
||||
usesupernode: false
|
||||
@ -35,7 +37,6 @@ dynamicroute:
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
|
BIN
example_config/super_mode/EGS06.png
Normal file
BIN
example_config/super_mode/EGS06.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
BIN
example_config/super_mode/EGS07.png
Normal file
BIN
example_config/super_mode/EGS07.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -14,8 +14,11 @@ Super Mode是受到[n2n](https://github.com/ntop/n2n)的啟發
|
||||
由supernode執行[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法),並把計算結果分發給全部edge node
|
||||
|
||||
在super mode模式下,設定檔裡面的`nexthoptable`以及`peers`是無效的。
|
||||
這些資訊都是從super node上面下載
|
||||
|
||||
這些資訊都是從super node上面下載
|
||||
同時,supernode會幫每個連線生成Preshared Key,分發給edge使用。
|
||||
```golang
|
||||
psk = shs256("PubkeyPeerA" + "PubkeyPeerB" + "主廚特調當季精選海鹽")[:32]
|
||||
```
|
||||
|
||||
### SuperMsg
|
||||
|
||||
@ -58,9 +61,11 @@ Super node收到Pong以後,就會更新它裡面的`Distance matrix`,並且
|
||||
這樣super node收到HTTP API看到`state hash`就知道這個edge node確實有收到`UpdateXXX`了。
|
||||
不然每隔一段時間就會重新發送`UpdateXXX`給該節點
|
||||
|
||||
### Guest API
|
||||
### peerstate
|
||||
HTTP還有一個API
|
||||
`http://127.0.0.1:3000/api/peerstate?Password=passwd`
|
||||
```
|
||||
http://127.0.0.1:3000/api/peerstate?Password=passwd
|
||||
```
|
||||
可以給前端看的,用來顯示現在各節點之間的單向延遲狀況
|
||||
之後可以用來畫力導向圖。
|
||||
|
||||
@ -69,12 +74,35 @@ HTTP還有一個API
|
||||
這個數值是編譯時決定的,一般不會動。但說不定你想改code,改成999呢?
|
||||
所以有這個欄位,前端顯示時看到數值大於這個,就視為不可達,不用畫線了
|
||||
|
||||
接下來你就能了解一下[P2P Mode的運作](../p2p_mode/README_zh.md)
|
||||
### peeradd
|
||||
新增peer
|
||||
|
||||
範例:
|
||||
```
|
||||
curl -X POST "http://127.0.0.1:3000/api/peer/add?Password=passwd_addpeer" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "nodeid=1&name=Node_01&pubkey=ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I=&pskey=iPM8FXfnHVzwjguZHRW9bLNY%2bh7%2bB1O2oTJtktptQkI="
|
||||
```
|
||||
參數:
|
||||
1. URL query: Password: 新增peer用的密碼
|
||||
1. Post body:
|
||||
1. nodeid: Node ID
|
||||
1. pubkey: Public Key
|
||||
1. pskey: Preshared Key
|
||||
|
||||
### peerdel
|
||||
刪除peer
|
||||
|
||||
範例:
|
||||
```
|
||||
curl "http://127.0.0.1:3000/api/peer/del?Password=passwd_delpeer&nodeid=1"
|
||||
```
|
||||
|
||||
## Config Paramaters
|
||||
|
||||
### Super mode的edge node有幾個參數
|
||||
1. `usesupernode`: 是否啟用Super mode
|
||||
1. `pskey`: 和supernode建立連線用的Preshared Key
|
||||
1. `connurlv4`: Super node的IPv4連線地址
|
||||
1. `pubkeyv4`: Super node的IPv4工鑰
|
||||
1. `connurlv6`: Super node的IPv6連線地址
|
||||
@ -91,17 +119,37 @@ HTTP還有一個API
|
||||
1. statepassword: Guest API 的密碼
|
||||
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:
|
||||
1. jittertolerance: 抖動容許誤差,收到Pong以後,一個37ms,一個39ms,不會觸發重新 計算
|
||||
1. jittertolerance: 抖動容許誤差,收到Pong以後,一個37ms,一個39ms,不會觸發重新計算
|
||||
1. jittertolerancemultiplier: 一樣是抖動容許誤差,但是高ping的話允許更多誤差
|
||||
https://www.desmos.com/calculator/raoti16r5n
|
||||
1. nodereporttimeout: 收到的`Pong`封包的有效期限。太久沒收到就變回Infinity
|
||||
1. recalculatecooldown: Floyd-Warshal是O(n^3)時間複雜度,不能太常算。設個冷卻時間
|
||||
1. recalculatecooldown: Floyd-Warshal是O(n^3)時間複雜度,不能太頻繁計算。設個冷卻時間
|
||||
1. edgetemplate: 給`addpeer`API用的。參考這個設定檔,顯示一個範例設定檔給edge
|
||||
1. peers: Peer列表,參考 [README_zh.md](../README_zh.md)
|
||||
1. nodeid: Peer的節點ID
|
||||
1. name: Peer名稱(顯示在前端)
|
||||
1. pubkey: peer 公鑰
|
||||
1. pskey: preshared key
|
||||
1. pskey: preshared key 該peer和本Supernode連線的PSK
|
||||
|
||||
##
|
||||
執行此範例設定檔(請開三個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
|
||||
```
|
||||
因為是stdio模式,stdin會讀入VPN網路
|
||||
請在其中一個edge視窗中鍵入
|
||||
```
|
||||
b1aaaaaaaaaa
|
||||
```
|
||||
b1會被轉換成 12byte 的layer 2 header,b是廣播地址`FF:FF:FF:FF:FF:FF`,1是普通地址`AA:BB:CC:DD:EE:01`,aaaaaaaaaa是後面的payload,然後再丟入VPN
|
||||
此時應該要能夠在另一個視窗上看見字串b1aaaaaaaaaa。前12byte被轉換回來了
|
||||
|
||||
## V4 V6 兩個公鑰
|
||||
為什麼要分開IPv4和IPv6呢?
|
||||
@ -113,4 +161,27 @@ HTTP還有一個API
|
||||
|
||||
![TwoChannel](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS05.png)
|
||||
|
||||
所以要像這樣,V4和V6都建立一條通道,才能讓V4和V6同時都被處理到
|
||||
所以要像這樣,V4和V6都建立一條通道,才能讓V4和V6同時都被處理到
|
||||
|
||||
## 打洞可行性
|
||||
對於不同的NAT type,打洞的可行性可以參考這張圖([出處](https://dh2i.com/kbs/kbs-2961448-understanding-different-nat-types-and-hole-punching/))
|
||||
|
||||
![EGS06](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS06.png)
|
||||
|
||||
還有,就算雙方都是ConeNAT,也不保證100%成功。
|
||||
還得看NAT設備的支援情況,詳見[此文](https://bford.info/pub/net/p2pnat/),裡面3.5章節描述的情況,也無法打洞成功
|
||||
|
||||
## Relay node
|
||||
因為Etherguard的Supernode單純只負責幫忙打洞+計算[Floyd-Warshall](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法),並分發運算結果
|
||||
而他本身並不參與資料轉發。因此如上章節描述打洞失敗,且沒有任何可達路徑的話,就需要搭建relay node
|
||||
基本上任意一個節點有公網ip,就不用擔心沒有路徑可達了。但是還是說明一下
|
||||
|
||||
Relay node其實也是一個edge node,只不過被設定成為interface=dummy,不串接任何真實接口
|
||||
![EGS07](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS07.png)
|
||||
只是在設定時要注意,Supernode地只要設定成Supernode的**外網ip**。
|
||||
因為如果用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`,就連不上了
|
||||
|
||||
|
||||
|
||||
看完本章捷,接下來你就能了解一下[P2P Mode的運作](../p2p_mode/README_zh.md)
|
||||
|
@ -21,21 +21,23 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 16
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: true
|
||||
supernode:
|
||||
usesupernode: true
|
||||
pskey: 'iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI='
|
||||
connurlv4: 127.0.0.1:3000
|
||||
pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
|
||||
connurlv6: '[::1]:3000'
|
||||
connurlv6: ''
|
||||
pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
|
||||
apiurl: http://127.0.0.1:3000/api
|
||||
supernodeinfotimeout: 50
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
@ -45,7 +47,7 @@ dynamicroute:
|
||||
usentp: true
|
||||
maxserveruse: 8
|
||||
synctimeinterval: 3600
|
||||
ntptimeout: 10
|
||||
ntptimeout: 3
|
||||
servers:
|
||||
- time.google.com
|
||||
- time1.google.com
|
||||
|
@ -21,21 +21,23 @@ loglevel:
|
||||
logntp: true
|
||||
dynamicroute:
|
||||
sendpinginterval: 16
|
||||
peeralivetimeout: 30
|
||||
dupchecktimeout: 40
|
||||
conntimeout: 30
|
||||
connnexttry: 5
|
||||
savenewpeers: true
|
||||
supernode:
|
||||
usesupernode: true
|
||||
pskey: 'juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs='
|
||||
connurlv4: 127.0.0.1:3000
|
||||
pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
|
||||
connurlv6: '[::1]:3000'
|
||||
connurlv6: ''
|
||||
pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
|
||||
apiurl: http://127.0.0.1:3000/api
|
||||
supernodeinfotimeout: 50
|
||||
p2p:
|
||||
usep2p: false
|
||||
sendpeerinterval: 20
|
||||
peeralivetimeout: 30
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 20
|
||||
jittertolerancemultiplier: 1.1
|
||||
@ -45,7 +47,7 @@ dynamicroute:
|
||||
usentp: true
|
||||
maxserveruse: 8
|
||||
synctimeinterval: 3600
|
||||
ntptimeout: 10
|
||||
ntptimeout: 3
|
||||
servers:
|
||||
- time.google.com
|
||||
- time1.google.com
|
||||
|
@ -2,28 +2,29 @@ nodename: NodeSuper
|
||||
privkeyv4: mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=
|
||||
privkeyv6: +EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=
|
||||
listenport: 3000
|
||||
passwords:
|
||||
showstate: passwd
|
||||
addpeer: passwd_addpeer
|
||||
delpeer: passwd_delpeer
|
||||
loglevel:
|
||||
loglevel: normal
|
||||
logtransit: true
|
||||
logcontrol: true
|
||||
lognormal: true
|
||||
logntp: false
|
||||
repushconfiginterval: 30
|
||||
passwords:
|
||||
showstate: passwd
|
||||
addpeer: passwd_addpeer
|
||||
delpeer: passwd_delpeer
|
||||
graphrecalculatesetting:
|
||||
jittertolerance: 5
|
||||
jittertolerancemultiplier: 1.01
|
||||
nodereporttimeout: 50
|
||||
recalculatecooldown: 5
|
||||
edgetemplate: "example_config/super_mode/s1.yaml"
|
||||
edgetemplate: example_config/super_mode/n1.yaml
|
||||
peers:
|
||||
- nodeid: 1
|
||||
name: "Node_01"
|
||||
pubkey: ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I=
|
||||
pskey: ""
|
||||
- nodeid: 2
|
||||
name: "Node_02"
|
||||
name: Node_02
|
||||
pubkey: dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=
|
||||
pskey: ""
|
||||
pskey: juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs=
|
||||
- nodeid: 1
|
||||
name: Node_01
|
||||
pubkey: ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I=
|
||||
pskey: iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=
|
||||
|
9
main.go
9
main.go
@ -47,7 +47,8 @@ var (
|
||||
tconfig = flag.String("config", "", "Config path for the interface.")
|
||||
mode = flag.String("mode", "", "Running mode. [super|edge|solve]")
|
||||
printExample = flag.Bool("example", false, "Print example config")
|
||||
nouapi = flag.Bool("no-uapi", false, "Do not use UAPI")
|
||||
bind = flag.String("bind", "linux", "UDP socket bind mode. [linux|std]\nYou may need this if tou want to run Etherguard under WSL.")
|
||||
nouapi = flag.Bool("no-uapi", false, "Disable UAPI\nWith UAPI, you can check etherguard status by \"wg\" command")
|
||||
version = flag.Bool("version", false, "Show version")
|
||||
help = flag.Bool("help", false, "Show this help")
|
||||
)
|
||||
@ -55,7 +56,7 @@ var (
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *version == true {
|
||||
fmt.Printf("etherguard-go %s\n%s-%s\n%s\n\nA full mesh layer 2 VPN powered by Floyd Warshall algorithm.\nInformation available at https://github.com/KusakabeSi/EtherGuardVPN.\nCopyright (C) Kusakabe Si <si@kskb.eu.org>.\n", Version,runtime.GOOS, runtime.GOARCH, tap.VPP_SUPPORT)
|
||||
fmt.Printf("etherguard-go %s\n%s-%s\n%s\n\nA full mesh layer 2 VPN powered by Floyd Warshall algorithm.\nInformation available at https://github.com/KusakabeSi/EtherGuardVPN.\nCopyright (C) Kusakabe Si <si@kskb.eu.org>.\n", Version, runtime.GOOS, runtime.GOARCH, tap.VPP_SUPPORT)
|
||||
return
|
||||
}
|
||||
if *help == true {
|
||||
@ -71,9 +72,9 @@ func main() {
|
||||
var err error
|
||||
switch *mode {
|
||||
case "edge":
|
||||
err = Edge(*tconfig, !*nouapi, *printExample)
|
||||
err = Edge(*tconfig, !*nouapi, *printExample, *bind)
|
||||
case "super":
|
||||
err = Super(*tconfig, !*nouapi, *printExample)
|
||||
err = Super(*tconfig, !*nouapi, *printExample, *bind)
|
||||
case "solve":
|
||||
err = path.Solve(*tconfig, *printExample)
|
||||
default:
|
||||
|
33
main_edge.go
33
main_edge.go
@ -49,6 +49,7 @@ func printExampleEdgeConf() {
|
||||
},
|
||||
DynamicRoute: config.DynamicRouteInfo{
|
||||
SendPingInterval: 20,
|
||||
PeerAliveTimeout: 30,
|
||||
DupCheckTimeout: 40,
|
||||
ConnTimeOut: 30,
|
||||
SaveNewPeers: true,
|
||||
@ -64,7 +65,6 @@ func printExampleEdgeConf() {
|
||||
P2P: config.P2Pinfo{
|
||||
UseP2P: true,
|
||||
SendPeerInterval: 20,
|
||||
PeerAliveTimeout: 30,
|
||||
GraphRecalculateSetting: config.GraphRecalculateSetting{
|
||||
JitterTolerance: 20,
|
||||
JitterToleranceMultiplier: 1.1,
|
||||
@ -132,7 +132,7 @@ func printExampleEdgeConf() {
|
||||
return
|
||||
}
|
||||
|
||||
func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (err error) {
|
||||
if printExample {
|
||||
printExampleEdgeConf()
|
||||
return nil
|
||||
@ -208,7 +208,7 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
graph := path.NewGraph(3, false, econfig.DynamicRoute.P2P.GraphRecalculateSetting, econfig.DynamicRoute.NTPconfig, econfig.LogLevel.LogNTP)
|
||||
graph.SetNHTable(econfig.NextHopTable, [32]byte{})
|
||||
|
||||
the_device := device.NewDevice(thetap, econfig.NodeID, conn.NewDefaultBind(), logger, graph, false, configPath, &econfig, nil, nil, Version)
|
||||
the_device := device.NewDevice(thetap, econfig.NodeID, conn.NewDefaultBind(true, true, bindmode), logger, graph, false, configPath, &econfig, nil, nil, Version)
|
||||
defer the_device.Close()
|
||||
pk, err := device.Str2PriKey(econfig.PrivKey)
|
||||
if err != nil {
|
||||
@ -228,14 +228,11 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
the_device.NewPeer(pk, peerconf.NodeID, false)
|
||||
if peerconf.EndPoint != "" {
|
||||
peer := the_device.LookupPeer(pk)
|
||||
endpoint, err := the_device.Bind().ParseEndpoint(peerconf.EndPoint)
|
||||
err = peer.SetEndpointFromConnURL(peerconf.EndPoint, 0, peerconf.Static)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to set endpoint %v: %w", peerconf.EndPoint, err)
|
||||
return err
|
||||
}
|
||||
peer.StaticConn = peerconf.Static
|
||||
peer.ConnURL = peerconf.EndPoint
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,34 +243,44 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
fmt.Println("Error decode base64 ", err)
|
||||
return err
|
||||
}
|
||||
endpoint, err := the_device.Bind().ParseEndpoint(econfig.DynamicRoute.SuperNode.ConnURLV4)
|
||||
psk, err := device.Str2PSKey(econfig.DynamicRoute.SuperNode.PSKey)
|
||||
if err != nil {
|
||||
fmt.Println("Error decode base64 ", err)
|
||||
return err
|
||||
}
|
||||
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
peer.StaticConn = false
|
||||
peer.ConnURL = econfig.DynamicRoute.SuperNode.ConnURLV4
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
peer.SetPSK(psk)
|
||||
err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.ConnURLV4, 4, false)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to set endpoint for supernode v4 %v: %v", econfig.DynamicRoute.SuperNode.ConnURLV4, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if econfig.DynamicRoute.SuperNode.ConnURLV6 != "" {
|
||||
pk, err := device.Str2PubKey(econfig.DynamicRoute.SuperNode.PubKeyV6)
|
||||
if err != nil {
|
||||
fmt.Println("Error decode base64 ", err)
|
||||
}
|
||||
endpoint, err := the_device.Bind().ParseEndpoint(econfig.DynamicRoute.SuperNode.ConnURLV6)
|
||||
psk, err := device.Str2PSKey(econfig.DynamicRoute.SuperNode.PSKey)
|
||||
if err != nil {
|
||||
fmt.Println("Error decode base64 ", err)
|
||||
return err
|
||||
}
|
||||
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
peer.SetPSK(psk)
|
||||
peer.StaticConn = false
|
||||
peer.ConnURL = econfig.DynamicRoute.SuperNode.ConnURLV6
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.ConnURLV6, 6, false)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to set endpoint for supernode v6 %v: %v", econfig.DynamicRoute.SuperNode.ConnURLV6, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
the_device.Event_Supernode_OK <- struct{}{}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@ -14,6 +15,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/device"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
@ -27,7 +29,7 @@ var (
|
||||
http_NhTable_Hash [32]byte
|
||||
http_PeerInfo_hash [32]byte
|
||||
http_NhTableStr []byte
|
||||
http_PeerInfoStr []byte
|
||||
http_PeerInfo config.API_Peers
|
||||
|
||||
http_PeerID2PubKey map[config.Vertex]string
|
||||
|
||||
@ -36,12 +38,18 @@ var (
|
||||
http_StateString_tmp []byte
|
||||
|
||||
http_PeerState map[string]*PeerState //the state hash reported by peer
|
||||
http_PeerIPs map[string]*HttpPeerLocalIP
|
||||
http_sconfig *config.SuperConfig
|
||||
|
||||
http_sconfig_path string
|
||||
http_econfig_tmp *config.EdgeConfig
|
||||
)
|
||||
|
||||
type HttpPeerLocalIP struct {
|
||||
IPv4 net.UDPAddr
|
||||
IPv6 net.UDPAddr
|
||||
}
|
||||
|
||||
type HttpState struct {
|
||||
PeerInfo map[config.Vertex]HttpPeerInfo
|
||||
Infinity float64
|
||||
@ -68,26 +76,38 @@ type client struct {
|
||||
notify6 string
|
||||
}
|
||||
|
||||
func get_api_peers() (api_peerinfo config.API_Peers, api_peerinfo_str_byte []byte, StateHash [32]byte, changed bool) {
|
||||
func get_api_peers(old_State_hash [32]byte) (api_peerinfo config.API_Peers, StateHash [32]byte, changed bool) {
|
||||
api_peerinfo = make(config.API_Peers)
|
||||
for _, peerinfo := range http_sconfig.Peers {
|
||||
api_peerinfo[peerinfo.PubKey] = config.API_Peerinfo{
|
||||
NodeID: peerinfo.NodeID,
|
||||
PubKey: peerinfo.PubKey,
|
||||
PSKey: peerinfo.PSKey,
|
||||
Connurl: make(map[string]bool),
|
||||
Connurl: make(map[string]int),
|
||||
}
|
||||
connV4 := http_device4.GetConnurl(peerinfo.NodeID)
|
||||
connV6 := http_device6.GetConnurl(peerinfo.NodeID)
|
||||
api_peerinfo[peerinfo.PubKey].Connurl[connV4] = true
|
||||
api_peerinfo[peerinfo.PubKey].Connurl[connV6] = true
|
||||
api_peerinfo[peerinfo.PubKey].Connurl[connV4] = 4
|
||||
api_peerinfo[peerinfo.PubKey].Connurl[connV6] = 6
|
||||
L4Addr := http_PeerIPs[peerinfo.PubKey].IPv4
|
||||
L4IP := L4Addr.IP
|
||||
L4str := L4Addr.String()
|
||||
if L4str != connV4 && conn.ValidIP(L4IP) {
|
||||
api_peerinfo[peerinfo.PubKey].Connurl[L4str] = 14
|
||||
}
|
||||
L6Addr := http_PeerIPs[peerinfo.PubKey].IPv6
|
||||
L6IP := L6Addr.IP
|
||||
L6str := L6Addr.String()
|
||||
if L6str != connV6 && conn.ValidIP(L6IP) {
|
||||
api_peerinfo[peerinfo.PubKey].Connurl[L6str] = 16
|
||||
}
|
||||
|
||||
delete(api_peerinfo[peerinfo.PubKey].Connurl, "")
|
||||
}
|
||||
api_peerinfo_str_byte, _ = json.Marshal(&api_peerinfo)
|
||||
api_peerinfo_str_byte, _ := json.Marshal(&api_peerinfo)
|
||||
hash_raw := md5.Sum(append(api_peerinfo_str_byte, http_HashSalt...))
|
||||
hash_str := hex.EncodeToString(hash_raw[:])
|
||||
copy(StateHash[:], []byte(hash_str))
|
||||
if bytes.Equal(http_PeerInfo_hash[:], StateHash[:]) == false {
|
||||
if bytes.Equal(old_State_hash[:], StateHash[:]) == false {
|
||||
changed = true
|
||||
}
|
||||
return
|
||||
@ -107,14 +127,55 @@ func get_peerinfo(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
NIDA, has := params["NodeID"]
|
||||
if !has {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
NID2, err := strconv.ParseUint(NIDA[0], 10, 16)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(fmt.Sprintf("%v", err)))
|
||||
return
|
||||
}
|
||||
PubKey := PubKeyA[0]
|
||||
State := StateA[0]
|
||||
NodeID := config.Vertex(NID2)
|
||||
if http_PeerID2PubKey[NodeID] != PubKey {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
|
||||
if bytes.Equal(http_PeerInfo_hash[:], []byte(State)) {
|
||||
if state := http_PeerState[PubKey]; state != nil {
|
||||
copy(http_PeerState[PubKey].PeerInfoState[:], State)
|
||||
http_PeerInfo_2peer := make(config.API_Peers)
|
||||
|
||||
for PeerPubKey, peerinfo := range http_PeerInfo {
|
||||
h := sha256.New()
|
||||
if NodeID > peerinfo.NodeID {
|
||||
h.Write([]byte(PubKey))
|
||||
h.Write([]byte(PeerPubKey))
|
||||
} else if NodeID < peerinfo.NodeID {
|
||||
h.Write([]byte(PeerPubKey))
|
||||
h.Write([]byte(PubKey))
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
h.Write(http_HashSalt)
|
||||
bs := h.Sum(nil)
|
||||
var psk device.NoisePresharedKey
|
||||
copy(psk[:], bs[:])
|
||||
peerinfo.PSKey = psk.ToString()
|
||||
http_PeerInfo_2peer[PeerPubKey] = peerinfo
|
||||
}
|
||||
api_peerinfo_str_byte, _ := json.Marshal(&http_PeerInfo_2peer)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(http_PeerInfoStr))
|
||||
w.Write(api_peerinfo_str_byte)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -136,8 +197,27 @@ func get_nhtable(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
NIDA, has := params["NodeID"]
|
||||
if !has {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
NID2, err := strconv.ParseUint(NIDA[0], 10, 16)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(fmt.Sprintf("%v", err)))
|
||||
return
|
||||
}
|
||||
PubKey := PubKeyA[0]
|
||||
State := StateA[0]
|
||||
NodeID := config.Vertex(NID2)
|
||||
if http_PeerID2PubKey[NodeID] != PubKey {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
|
||||
if bytes.Equal(http_NhTable_Hash[:], []byte(State)) {
|
||||
if state := http_PeerState[PubKey]; state != nil {
|
||||
copy(http_PeerState[PubKey].NhTableState[:], State)
|
||||
@ -252,8 +332,22 @@ func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test
|
||||
PubKey: PubKey,
|
||||
PSKey: PSKey,
|
||||
})
|
||||
http_sconfig.Peers = append(http_sconfig.Peers, config.SuperPeerInfo{
|
||||
NodeID: NodeID,
|
||||
Name: Name,
|
||||
PubKey: PubKey,
|
||||
PSKey: PSKey,
|
||||
})
|
||||
configbytes, _ := yaml.Marshal(http_sconfig)
|
||||
ioutil.WriteFile(http_sconfig_path, configbytes, 0644)
|
||||
http_econfig_tmp.NodeID = NodeID
|
||||
http_econfig_tmp.NodeName = Name
|
||||
http_econfig_tmp.PrivKey = "Your_Private_Key"
|
||||
http_econfig_tmp.DynamicRoute.SuperNode.PSKey = PSKey
|
||||
ret_str_byte, _ := yaml.Marshal(&http_econfig_tmp)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(ret_str_byte)
|
||||
return
|
||||
}
|
||||
|
||||
func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test
|
||||
@ -264,7 +358,7 @@ func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test
|
||||
PubKey := ""
|
||||
if has {
|
||||
password := PasswordA[0]
|
||||
if password == http_passwords.AddPeer {
|
||||
if password == http_passwords.DelPeer {
|
||||
NodeIDA, has := params["nodeid"]
|
||||
if !has {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
@ -8,6 +8,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@ -62,7 +63,7 @@ func printExampleSuperConf() {
|
||||
return
|
||||
}
|
||||
|
||||
func Super(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
func Super(configPath string, useUAPI bool, printExample bool, bindmode string) (err error) {
|
||||
if printExample {
|
||||
printExampleSuperConf()
|
||||
return nil
|
||||
@ -108,6 +109,7 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
|
||||
http_sconfig_path = configPath
|
||||
http_PeerState = make(map[string]*PeerState)
|
||||
http_PeerIPs = make(map[string]*HttpPeerLocalIP)
|
||||
http_PeerID2PubKey = make(map[config.Vertex]string)
|
||||
http_HashSalt = []byte(config.RandomStr(32, "Salt generate failed"))
|
||||
http_passwords = sconfig.Passwords
|
||||
@ -120,10 +122,10 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting, config.NTPinfo{}, sconfig.LogLevel.LogNTP)
|
||||
|
||||
thetap4, _ := tap.CreateDummyTAP()
|
||||
http_device4 = device.NewDevice(thetap4, config.SuperNodeMessage, conn.NewCustomBind(true, false), logger4, http_graph, true, configPath, nil, &sconfig, &super_chains, Version)
|
||||
http_device4 = device.NewDevice(thetap4, config.SuperNodeMessage, conn.NewDefaultBind(true, false, bindmode), logger4, http_graph, true, configPath, nil, &sconfig, &super_chains, Version)
|
||||
defer http_device4.Close()
|
||||
thetap6, _ := tap.CreateDummyTAP()
|
||||
http_device6 = device.NewDevice(thetap6, config.SuperNodeMessage, conn.NewCustomBind(false, true), logger6, http_graph, true, configPath, nil, &sconfig, &super_chains, Version)
|
||||
http_device6 = device.NewDevice(thetap6, config.SuperNodeMessage, conn.NewDefaultBind(false, true, bindmode), logger6, http_graph, true, configPath, nil, &sconfig, &super_chains, Version)
|
||||
defer http_device6.Close()
|
||||
if sconfig.PrivKeyV4 != "" {
|
||||
pk4, err := device.Str2PriKey(sconfig.PrivKeyV4)
|
||||
@ -199,7 +201,7 @@ func super_peeradd(peerconf config.SuperPeerInfo) error {
|
||||
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
|
||||
return err
|
||||
}
|
||||
peer4.StaticConn = true
|
||||
peer4.StaticConn = false
|
||||
if peerconf.PSKey != "" {
|
||||
psk, err := device.Str2PSKey(peerconf.PSKey)
|
||||
if err != nil {
|
||||
@ -215,7 +217,7 @@ func super_peeradd(peerconf config.SuperPeerInfo) error {
|
||||
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
|
||||
return err
|
||||
}
|
||||
peer6.StaticConn = true
|
||||
peer6.StaticConn = false
|
||||
if peerconf.PSKey != "" {
|
||||
psk, err := device.Str2PSKey(peerconf.PSKey)
|
||||
if err != nil {
|
||||
@ -227,15 +229,41 @@ func super_peeradd(peerconf config.SuperPeerInfo) error {
|
||||
}
|
||||
http_PeerID2PubKey[peerconf.NodeID] = peerconf.PubKey
|
||||
http_PeerState[peerconf.PubKey] = &PeerState{}
|
||||
http_PeerIPs[peerconf.PubKey] = &HttpPeerLocalIP{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func super_peerdel(toDelete config.Vertex) {
|
||||
PubKey := http_PeerID2PubKey[toDelete]
|
||||
UpdateErrorMsg := path.UpdateErrorMsg{
|
||||
Node_id: toDelete,
|
||||
Action: path.Shutdown,
|
||||
ErrorCode: 410,
|
||||
ErrorMsg: "You've been removed from supernode.",
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
body, _ := path.GetByte(&UpdateErrorMsg)
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, _ := path.NewEgHeader(buf[:path.EgHeaderLen])
|
||||
header.SetSrc(config.SuperNodeMessage)
|
||||
header.SetTTL(0)
|
||||
header.SetPacketLength(uint16(len(body)))
|
||||
copy(buf[path.EgHeaderLen:], body)
|
||||
header.SetDst(toDelete)
|
||||
|
||||
peer4 := http_device4.LookupPeerByStr(PubKey)
|
||||
http_device4.SendPacket(peer4, path.UpdateError, buf, device.MessageTransportOffsetContent)
|
||||
|
||||
peer6 := http_device6.LookupPeerByStr(PubKey)
|
||||
http_device6.SendPacket(peer6, path.UpdateError, buf, device.MessageTransportOffsetContent)
|
||||
time.Sleep(path.S2TD(0.1))
|
||||
}
|
||||
http_device4.RemovePeerByID(toDelete)
|
||||
http_device6.RemovePeerByID(toDelete)
|
||||
http_graph.RemoveVirt(toDelete, true, false)
|
||||
PubKey := http_PeerID2PubKey[toDelete]
|
||||
|
||||
delete(http_PeerState, PubKey)
|
||||
delete(http_PeerIPs, PubKey)
|
||||
delete(http_PeerID2PubKey, toDelete)
|
||||
}
|
||||
|
||||
@ -243,15 +271,30 @@ func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
|
||||
for {
|
||||
select {
|
||||
case reg_msg := <-events.Event_server_register:
|
||||
var should_push_peer bool
|
||||
var should_push_nh bool
|
||||
if reg_msg.Node_id < config.Special_NodeID {
|
||||
copy(http_PeerState[http_PeerID2PubKey[reg_msg.Node_id]].NhTableState[:], reg_msg.NhStateHash[:])
|
||||
copy(http_PeerState[http_PeerID2PubKey[reg_msg.Node_id]].PeerInfoState[:], reg_msg.PeerStateHash[:])
|
||||
PubKey := http_PeerID2PubKey[reg_msg.Node_id]
|
||||
if bytes.Equal(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) == false {
|
||||
copy(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:])
|
||||
should_push_nh = true
|
||||
}
|
||||
if bytes.Equal(http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) == false {
|
||||
copy(http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:])
|
||||
should_push_peer = true
|
||||
}
|
||||
|
||||
http_PeerIPs[PubKey].IPv4 = reg_msg.LocalV4
|
||||
http_PeerIPs[PubKey].IPv6 = reg_msg.LocalV6
|
||||
}
|
||||
var changed bool
|
||||
_, http_PeerInfoStr, http_PeerInfo_hash, changed = get_api_peers()
|
||||
if changed {
|
||||
var peer_state_changed bool
|
||||
http_PeerInfo, http_PeerInfo_hash, peer_state_changed = get_api_peers(http_PeerInfo_hash)
|
||||
if should_push_peer || peer_state_changed {
|
||||
PushPeerinfo()
|
||||
}
|
||||
if should_push_nh {
|
||||
PushNhTable()
|
||||
}
|
||||
case <-events.Event_server_NhTable_changed:
|
||||
NhTable := graph.GetNHTable()
|
||||
NhTablestr, _ := json.Marshal(NhTable)
|
||||
@ -307,7 +350,6 @@ func PushNhTable() {
|
||||
if peer := http_device6.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" {
|
||||
http_device6.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,12 @@ func (o *OrderedMap) Delete(key string) {
|
||||
delete(o.values, key)
|
||||
}
|
||||
|
||||
func (o *OrderedMap) Clear() { // delete whole orderdmap
|
||||
for _, key := range o.Keys() {
|
||||
o.Delete(key)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OrderedMap) Keys() []string {
|
||||
ret := make([]string, len(o.keys))
|
||||
for i, v := range o.keys {
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@ -22,13 +24,24 @@ func GetByte(structIn interface{}) (bb []byte, err error) {
|
||||
|
||||
type RegisterMsg struct {
|
||||
Node_id config.Vertex
|
||||
Version string
|
||||
PeerStateHash [32]byte
|
||||
NhStateHash [32]byte
|
||||
Version string
|
||||
LocalV4 net.UDPAddr
|
||||
LocalV6 net.UDPAddr
|
||||
}
|
||||
|
||||
func Hash2Str(h []byte) string {
|
||||
for _, v := range h {
|
||||
if v != 0 {
|
||||
return base64.StdEncoding.EncodeToString(h)[:10] + "..."
|
||||
}
|
||||
}
|
||||
return "\"\""
|
||||
}
|
||||
|
||||
func (c *RegisterMsg) ToString() string {
|
||||
return "RegisterMsg Node_id:" + c.Node_id.ToString() + " Version:" + c.Version + " PeerHash:" + base64.StdEncoding.EncodeToString(c.PeerStateHash[:]) + " NhHash:" + base64.StdEncoding.EncodeToString(c.NhStateHash[:])
|
||||
return fmt.Sprint("RegisterMsg Node_id:"+c.Node_id.ToString(), " Version:"+c.Version, " PeerHash:"+Hash2Str(c.PeerStateHash[:]), " NhHash:"+Hash2Str(c.NhStateHash[:]), " LocalV4:"+c.LocalV4.String(), " LocalV6:"+c.LocalV6.String())
|
||||
}
|
||||
|
||||
func ParseRegisterMsg(bin []byte) (StructPlace RegisterMsg, err error) {
|
||||
@ -108,9 +121,10 @@ func ParseUpdateNhTableMsg(bin []byte) (StructPlace UpdateNhTableMsg, err error)
|
||||
}
|
||||
|
||||
type PingMsg struct {
|
||||
RequestID uint32
|
||||
Src_nodeID config.Vertex
|
||||
Time time.Time
|
||||
RequestID uint32
|
||||
Src_nodeID config.Vertex
|
||||
Time time.Time
|
||||
RequestReply int
|
||||
}
|
||||
|
||||
func (c *PingMsg) ToString() string {
|
||||
@ -164,7 +178,6 @@ type BoardcastPeerMsg struct {
|
||||
Request_ID uint32
|
||||
NodeID config.Vertex
|
||||
PubKey [32]byte
|
||||
PSKey [32]byte
|
||||
ConnURL string
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user