mirror of
https://github.com/KusakabeShi/EtherGuard-VPN.git
synced 2024-11-07 16:04:00 +01:00
Not test yet
This commit is contained in:
parent
87a62f873b
commit
4939f9f0c4
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
go.sum
|
||||
etherguard-go
|
||||
etherguard-go
|
||||
.ipynb_checkpoints
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -10,7 +10,7 @@
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "${workspaceFolder}",
|
||||
"args":["-config","example_config/n1.yaml","-mode","edge"],
|
||||
"args":["-config","example_config/n1.yaml","-mode","super", "--example"],
|
||||
}
|
||||
]
|
||||
}
|
103
config/config.go
Normal file
103
config/config.go
Normal file
@ -0,0 +1,103 @@
|
||||
package config
|
||||
|
||||
type EdgeConfig struct {
|
||||
Interface InterfaceConf
|
||||
NodeID Vertex
|
||||
NodeName string
|
||||
PrivKey string
|
||||
ListenPort int
|
||||
LogLevel LoggerInfo
|
||||
DynamicRoute DynamicRouteInfo
|
||||
NextHopTable NextHopTable
|
||||
Peers []PeerInfo
|
||||
}
|
||||
|
||||
type SuperConfig struct {
|
||||
NodeName string
|
||||
PrivKeyV4 string
|
||||
PrivKeyV6 string
|
||||
ListenPort int
|
||||
LogLevel LoggerInfo
|
||||
GraphRecalculateSetting GraphRecalculateSetting
|
||||
Peers []PeerInfo
|
||||
}
|
||||
|
||||
type InterfaceConf struct {
|
||||
Itype string
|
||||
IfaceID int
|
||||
Name string
|
||||
MacAddr string
|
||||
MTU int
|
||||
RecvAddr string
|
||||
SendAddr string
|
||||
HumanFriendly bool
|
||||
}
|
||||
|
||||
type PeerInfo struct {
|
||||
NodeID Vertex
|
||||
PubKey string
|
||||
EndPoint string
|
||||
Static bool
|
||||
}
|
||||
|
||||
type LoggerInfo struct {
|
||||
LogLevel string
|
||||
LogTransit bool
|
||||
}
|
||||
|
||||
// Nonnegative integer ID of vertex
|
||||
type Vertex uint32
|
||||
|
||||
type DynamicRouteInfo struct {
|
||||
SendPingInterval float64
|
||||
DupCheckTimeout float64
|
||||
ConnTimeOut float64
|
||||
SaveNewPeers bool
|
||||
SuperNode SuperInfo
|
||||
P2P P2Pinfo
|
||||
NTPconfig NTPinfo
|
||||
}
|
||||
|
||||
type NTPinfo struct {
|
||||
UseNTP bool
|
||||
MaxServerUse int
|
||||
Servers []string
|
||||
}
|
||||
|
||||
type SuperInfo struct {
|
||||
UseSuperNode bool
|
||||
ConnURLV4 string
|
||||
PubKeyV4 string
|
||||
ConnURLV6 string
|
||||
PubKeyV6 string
|
||||
APIUrl string
|
||||
SuperNodeInfoTimeout float64
|
||||
}
|
||||
|
||||
type P2Pinfo struct {
|
||||
UseP2P bool
|
||||
SendPeerInterval float64
|
||||
PeerAliveTimeout float64
|
||||
GraphRecalculateSetting GraphRecalculateSetting
|
||||
}
|
||||
|
||||
type GraphRecalculateSetting struct {
|
||||
JitterTolerance float64
|
||||
JitterToleranceMultiplier float64
|
||||
NodeReportTimeout float64
|
||||
RecalculateCoolDown float64
|
||||
}
|
||||
|
||||
type DistTable map[Vertex]map[Vertex]float64
|
||||
type NextHopTable map[Vertex]map[Vertex]*Vertex
|
||||
|
||||
type HTTP_Peerinfo struct {
|
||||
NodeID Vertex
|
||||
PubKey string
|
||||
PSKey string
|
||||
Connurl map[string]bool
|
||||
}
|
||||
type HTTP_Peers struct {
|
||||
Peers map[string]HTTP_Peerinfo
|
||||
}
|
||||
|
105
device/device.go
105
device/device.go
@ -6,16 +6,19 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ratelimiter"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/rwcancel"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
fixed_time_cache "github.com/KusakabeSi/go-cache"
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
@ -61,16 +64,30 @@ type Device struct {
|
||||
peers struct {
|
||||
sync.RWMutex // protects keyMap
|
||||
keyMap map[NoisePublicKey]*Peer
|
||||
IDMap map[path.Vertex]*Peer
|
||||
IDMap map[config.Vertex]*Peer
|
||||
SuperPeer map[NoisePublicKey]*Peer
|
||||
Peer_state [32]byte
|
||||
}
|
||||
event_tryendpoint chan struct{}
|
||||
|
||||
EdgeConfigPath string
|
||||
EdgeConfig *config.EdgeConfig
|
||||
|
||||
Event_server_register chan path.RegisterMsg
|
||||
Event_server_pong chan path.PongMsg
|
||||
Event_server_NhTable_changed chan struct{}
|
||||
Event_save_config chan struct{}
|
||||
|
||||
indexTable IndexTable
|
||||
cookieChecker CookieChecker
|
||||
|
||||
ID path.Vertex
|
||||
NhTable path.NextHopTable
|
||||
l2fib map[tap.MacAddress]path.Vertex
|
||||
LogTransit bool
|
||||
IsSuperNode bool
|
||||
ID config.Vertex
|
||||
graph *path.IG
|
||||
l2fib map[tap.MacAddress]config.Vertex
|
||||
LogTransit bool
|
||||
DRoute config.DynamicRouteInfo
|
||||
DupData fixed_time_cache.Cache
|
||||
|
||||
pool struct {
|
||||
messageBuffers *WaitPool
|
||||
@ -135,7 +152,13 @@ func removePeerLocked(device *Device, peer *Peer, key NoisePublicKey) {
|
||||
peer.Stop()
|
||||
|
||||
// remove from peer map
|
||||
id := peer.ID
|
||||
delete(device.peers.keyMap, key)
|
||||
if id == path.SuperNodeMessage {
|
||||
delete(device.peers.SuperPeer, key)
|
||||
} else {
|
||||
delete(device.peers.IDMap, id)
|
||||
}
|
||||
}
|
||||
|
||||
// changeState attempts to change the device state to match want.
|
||||
@ -279,7 +302,7 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewDevice(tapDevice tap.Device, id path.Vertex, bind conn.Bind, logger *Logger) *Device {
|
||||
func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *Logger, graph *path.IG, IsSuperNode bool, theconfigpath string, theconfig *config.EdgeConfig, superevents *path.SUPER_Events) *Device {
|
||||
device := new(Device)
|
||||
device.state.state = uint32(deviceStateDown)
|
||||
device.closed = make(chan struct{})
|
||||
@ -293,13 +316,32 @@ func NewDevice(tapDevice tap.Device, id path.Vertex, bind conn.Bind, logger *Log
|
||||
}
|
||||
device.tap.mtu = int32(mtu)
|
||||
device.peers.keyMap = make(map[NoisePublicKey]*Peer)
|
||||
device.peers.IDMap = make(map[path.Vertex]*Peer)
|
||||
device.peers.IDMap = make(map[config.Vertex]*Peer)
|
||||
device.IsSuperNode = IsSuperNode
|
||||
device.ID = id
|
||||
device.l2fib = make(map[tap.MacAddress]path.Vertex)
|
||||
device.graph = graph
|
||||
device.l2fib = make(map[tap.MacAddress]config.Vertex)
|
||||
|
||||
device.rate.limiter.Init()
|
||||
device.indexTable.Init()
|
||||
device.PopulatePools()
|
||||
|
||||
if IsSuperNode {
|
||||
device.Event_server_pong = superevents.Event_server_pong
|
||||
device.Event_server_register = superevents.Event_server_register
|
||||
device.Event_server_NhTable_changed = superevents.Event_server_NhTable_changed
|
||||
go device.RoutineRecalculateNhTable()
|
||||
} else {
|
||||
device.EdgeConfigPath = theconfigpath
|
||||
device.EdgeConfig = theconfig
|
||||
device.DRoute = theconfig.DynamicRoute
|
||||
device.DupData = *fixed_time_cache.NewCache(path.S2TD(theconfig.DynamicRoute.DupCheckTimeout))
|
||||
device.event_tryendpoint = make(chan struct{}, 1<<6)
|
||||
device.Event_save_config = make(chan struct{}, 1<<5)
|
||||
go device.RoutineSetEndpoint()
|
||||
go device.RoutineRegister()
|
||||
go device.RoutineSendPing()
|
||||
go device.RoutineRecalculateNhTable()
|
||||
}
|
||||
// create queues
|
||||
|
||||
device.queue.handshake = newHandshakeQueue()
|
||||
@ -332,6 +374,49 @@ func (device *Device) LookupPeer(pk NoisePublicKey) *Peer {
|
||||
return device.peers.keyMap[pk]
|
||||
}
|
||||
|
||||
func (device *Device) LookupPeerByStr(pks string) *Peer {
|
||||
var pk NoisePublicKey
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(pks)
|
||||
copy(pk[:], sk_slice)
|
||||
return device.LookupPeer(pk)
|
||||
}
|
||||
|
||||
func PubKey2Str(pk NoisePublicKey) (result string) {
|
||||
result = string(base64.StdEncoding.EncodeToString(pk[:]))
|
||||
return
|
||||
}
|
||||
|
||||
func PriKey2Str(pk NoisePrivateKey) (result string) {
|
||||
result = string(base64.StdEncoding.EncodeToString(pk[:]))
|
||||
return
|
||||
}
|
||||
func PSKeyStr(pk NoisePresharedKey) (result string) {
|
||||
result = string(base64.StdEncoding.EncodeToString(pk[:]))
|
||||
return
|
||||
}
|
||||
|
||||
func Str2PubKey(k string) (pk NoisePublicKey) {
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(k)
|
||||
copy(pk[:], sk_slice)
|
||||
return
|
||||
}
|
||||
|
||||
func Str2PriKey(k string) (pk NoisePrivateKey) {
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(k)
|
||||
copy(pk[:], sk_slice)
|
||||
return
|
||||
}
|
||||
|
||||
func Str2PSKey(k string) (pk NoisePresharedKey) {
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(k)
|
||||
copy(pk[:], sk_slice)
|
||||
return
|
||||
}
|
||||
|
||||
func (device *Device) GetIPMap() map[config.Vertex]*Peer {
|
||||
return device.peers.IDMap
|
||||
}
|
||||
|
||||
func (device *Device) RemovePeer(key NoisePublicKey) {
|
||||
device.peers.Lock()
|
||||
defer device.peers.Unlock()
|
||||
@ -352,7 +437,7 @@ func (device *Device) RemoveAllPeers() {
|
||||
}
|
||||
|
||||
device.peers.keyMap = make(map[NoisePublicKey]*Peer)
|
||||
device.peers.IDMap = make(map[path.Vertex]*Peer)
|
||||
device.peers.IDMap = make(map[config.Vertex]*Peer)
|
||||
}
|
||||
|
||||
func (device *Device) Close() {
|
||||
|
@ -13,20 +13,23 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
type Peer struct {
|
||||
isRunning AtomicBool
|
||||
sync.RWMutex // Mostly protects endpoint, but is generally taken whenever we modify peer
|
||||
keypairs Keypairs
|
||||
handshake Handshake
|
||||
device *Device
|
||||
endpoint conn.Endpoint
|
||||
stopping sync.WaitGroup // routines pending stop
|
||||
isRunning AtomicBool
|
||||
sync.RWMutex // Mostly protects endpoint, but is generally taken whenever we modify peer
|
||||
keypairs Keypairs
|
||||
handshake Handshake
|
||||
device *Device
|
||||
endpoint conn.Endpoint
|
||||
endpoint_trylist map[string]time.Time
|
||||
LastPingReceived time.Time
|
||||
stopping sync.WaitGroup // routines pending stop
|
||||
|
||||
ID path.Vertex
|
||||
ID config.Vertex
|
||||
|
||||
// These fields are accessed with atomic operations, which must be
|
||||
// 64-bit aligned even on 32-bit platforms. Go guarantees that an
|
||||
@ -67,7 +70,7 @@ type Peer struct {
|
||||
persistentKeepaliveInterval uint32 // accessed atomically
|
||||
}
|
||||
|
||||
func (device *Device) NewPeer(pk NoisePublicKey, id path.Vertex) (*Peer, error) {
|
||||
func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex) (*Peer, error) {
|
||||
if device.isClosed() {
|
||||
return nil, errors.New("device closed")
|
||||
}
|
||||
@ -117,8 +120,13 @@ func (device *Device) NewPeer(pk NoisePublicKey, id path.Vertex) (*Peer, error)
|
||||
peer.endpoint = nil
|
||||
|
||||
// add
|
||||
device.peers.keyMap[pk] = peer
|
||||
device.peers.IDMap[id] = peer
|
||||
if id == path.SuperNodeMessage { // To communicate with supernode
|
||||
device.peers.SuperPeer[pk] = peer
|
||||
} else { // Regular peer, other edgenodes
|
||||
_, ok = device.peers.IDMap[id]
|
||||
device.peers.keyMap[pk] = peer
|
||||
device.peers.IDMap[id] = peer
|
||||
}
|
||||
|
||||
// start peer
|
||||
peer.timersInit()
|
||||
@ -288,3 +296,11 @@ func (peer *Peer) SetEndpointFromPacket(endpoint conn.Endpoint) {
|
||||
peer.endpoint = endpoint
|
||||
peer.Unlock()
|
||||
}
|
||||
|
||||
func (peer *Peer) GetEndpointSrcStr() string {
|
||||
return peer.endpoint.SrcToString()
|
||||
}
|
||||
|
||||
func (peer *Peer) GetEndpointDstStr() string {
|
||||
return peer.endpoint.DstToString()
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
@ -411,8 +412,10 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
}
|
||||
var EgBody path.EgHeader
|
||||
var err error
|
||||
var src_nodeID path.Vertex
|
||||
var dst_nodeID path.Vertex
|
||||
var src_nodeID config.Vertex
|
||||
var dst_nodeID config.Vertex
|
||||
var packet_type path.Usage
|
||||
should_process := false
|
||||
should_receive := false
|
||||
should_transfer := false
|
||||
elem.Lock()
|
||||
@ -445,57 +448,99 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
EgBody, err = path.NewEgHeader(elem.packet[0:path.EgHeaderLen])
|
||||
src_nodeID = EgBody.GetSrc()
|
||||
dst_nodeID = EgBody.GetDst()
|
||||
//elem.packet = elem.packet[:EgBody.GetPacketLength()]
|
||||
elem.packet = elem.packet[:EgBody.GetPacketLength()]
|
||||
packet_type = EgBody.GetUsage()
|
||||
|
||||
if dst_nodeID == device.ID {
|
||||
should_receive = true
|
||||
} else if dst_nodeID == path.Boardcast {
|
||||
should_receive = true
|
||||
should_transfer = true
|
||||
} else if device.NhTable[device.ID][dst_nodeID] != nil {
|
||||
should_transfer = true
|
||||
if device.IsSuperNode {
|
||||
peer.LastPingReceived = time.Now()
|
||||
switch dst_nodeID {
|
||||
case path.ControlMessage:
|
||||
should_process = true
|
||||
case path.SuperNodeMessage:
|
||||
should_process = true
|
||||
default:
|
||||
device.log.Errorf("Invalid dst_nodeID received. Check your code for bug")
|
||||
}
|
||||
} else {
|
||||
device.log.Verbosef("No route to peer ID %v", dst_nodeID)
|
||||
goto skip
|
||||
switch dst_nodeID {
|
||||
case path.Boardcast:
|
||||
should_receive = true
|
||||
should_transfer = true
|
||||
case path.PingMessage:
|
||||
peer.LastPingReceived = time.Now()
|
||||
should_process = true
|
||||
case path.SuperNodeMessage:
|
||||
should_process = true
|
||||
case path.ControlMessage:
|
||||
packet := elem.packet[path.EgHeaderLen:]
|
||||
if device.CheckNoDup(packet) {
|
||||
should_process = true
|
||||
should_transfer = true
|
||||
} else {
|
||||
should_process = false
|
||||
should_transfer = false
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Duplicate packet received from %d through %d , src_nodeID = %d . Dropeed.\n", peer.ID, device.ID, src_nodeID)
|
||||
}
|
||||
}
|
||||
case device.ID:
|
||||
if packet_type == path.NornalPacket {
|
||||
should_receive = true
|
||||
} else {
|
||||
should_process = true
|
||||
}
|
||||
default:
|
||||
if _, ok := device.graph.NhTable[device.ID][dst_nodeID]; ok {
|
||||
should_transfer = true
|
||||
} else {
|
||||
device.log.Verbosef("No route to peer ID %v", dst_nodeID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if should_transfer { //Send to another peer
|
||||
if should_transfer {
|
||||
l2ttl := EgBody.GetTTL()
|
||||
if l2ttl == 0 {
|
||||
device.log.Verbosef("TTL is 0 %v", dst_nodeID)
|
||||
} else {
|
||||
EgBody.SetTTL(l2ttl - 1)
|
||||
if dst_nodeID != path.Boardcast {
|
||||
next_id := *device.NhTable[device.ID][dst_nodeID]
|
||||
if dst_nodeID == path.Boardcast { //Regular transfer algorithm
|
||||
device.TransitBoardcastPacket(src_nodeID, peer.ID, elem.packet, MessageTransportOffsetContent)
|
||||
} else if dst_nodeID == path.ControlMessage { // Control Message will try send to every know node regardless the connectivity
|
||||
skip_list := make(map[config.Vertex]bool)
|
||||
skip_list[src_nodeID] = true //Don't send to conimg peer and source peer
|
||||
skip_list[peer.ID] = true
|
||||
device.SpreadPacket(skip_list, elem.packet, MessageTransportOffsetContent)
|
||||
|
||||
} else {
|
||||
next_id := *device.graph.NhTable[device.ID][dst_nodeID]
|
||||
peer_out = device.peers.IDMap[next_id]
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Transfer packet from %d through %d to %d\n", peer.ID, device.ID, peer_out.ID)
|
||||
}
|
||||
device.SendPacket(peer_out, elem.packet, MessageTransportOffsetContent)
|
||||
} else {
|
||||
node_boardcast_list := path.GetBoardcastThroughList(device.ID, src_nodeID, device.NhTable)
|
||||
for peer_id := range node_boardcast_list {
|
||||
peer_out = device.peers.IDMap[peer_id]
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Transfer packet from %d through %d to %d\n", peer.ID, device.ID, peer_out.ID)
|
||||
}
|
||||
device.SendPacket(peer_out, elem.packet, MessageTransportOffsetContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if should_receive {
|
||||
src_macaddr := tap.GetSrcMacAddr(elem.packet[path.EgHeaderLen:])
|
||||
device.l2fib[src_macaddr] = src_nodeID // Write to l2fib table
|
||||
_, err = device.tap.device.Write(elem.buffer[:MessageTransportOffsetContent+len(elem.packet)], MessageTransportOffsetContent+path.EgHeaderLen)
|
||||
if err != nil && !device.isClosed() {
|
||||
device.log.Errorf("Failed to write packet to TUN device: %v", err)
|
||||
if should_process {
|
||||
if packet_type != path.NornalPacket {
|
||||
device.process_received(packet_type, elem.packet[path.EgHeaderLen:])
|
||||
}
|
||||
if len(peer.queue.inbound.c) == 0 {
|
||||
err = device.tap.device.Flush()
|
||||
if err != nil {
|
||||
peer.device.log.Errorf("Unable to flush packets: %v", err)
|
||||
}
|
||||
|
||||
if should_receive { // Write message to tap device
|
||||
if packet_type == path.NornalPacket {
|
||||
src_macaddr := tap.GetSrcMacAddr(elem.packet[path.EgHeaderLen:])
|
||||
device.l2fib[src_macaddr] = src_nodeID // Write to l2fib table
|
||||
_, err = device.tap.device.Write(elem.buffer[:MessageTransportOffsetContent+len(elem.packet)], MessageTransportOffsetContent+path.EgHeaderLen)
|
||||
if err != nil && !device.isClosed() {
|
||||
device.log.Errorf("Failed to write packet to TUN device: %v", err)
|
||||
}
|
||||
if len(peer.queue.inbound.c) == 0 {
|
||||
err = device.tap.device.Flush()
|
||||
if err != nil {
|
||||
peer.device.log.Errorf("Unable to flush packets: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
460
device/receivesendproc.go
Normal file
460
device/receivesendproc.go
Normal file
@ -0,0 +1,460 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func (device *Device) SendPacket(peer *Peer, packet []byte, offset int) {
|
||||
if peer == nil {
|
||||
return
|
||||
}
|
||||
var elem *QueueOutboundElement
|
||||
elem = device.NewOutboundElement()
|
||||
copy(elem.buffer[offset:offset+len(packet)], packet)
|
||||
elem.packet = elem.buffer[offset : offset+len(packet)]
|
||||
if peer.isRunning.Get() {
|
||||
peer.StagePacket(elem)
|
||||
elem = nil
|
||||
peer.SendStagedPackets()
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) BoardcastPacket(skip_list map[config.Vertex]bool, packet []byte, offset int) { // Send packet to all connected peers
|
||||
send_list := device.graph.GetBoardcastList(device.ID)
|
||||
for node_id, _ := range skip_list {
|
||||
send_list[node_id] = false
|
||||
}
|
||||
for node_id, should_send := range send_list {
|
||||
if should_send {
|
||||
device.SendPacket(device.peers.IDMap[node_id], packet, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) SpreadPacket(skip_list map[config.Vertex]bool, packet []byte, offset int) { // Send packet to all peers no matter it is alive
|
||||
for peer_id, peer_out := range device.peers.IDMap {
|
||||
if _, ok := skip_list[peer_id]; ok {
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Skipped Spread Packet packet through %d to %d\n", device.ID, peer_out.ID)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Spread Packet packet through %d to %d\n", device.ID, peer_out.ID)
|
||||
}
|
||||
device.SendPacket(peer_out, packet, MessageTransportOffsetContent)
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) TransitBoardcastPacket(src_nodeID config.Vertex, in_id config.Vertex, packet []byte, offset int) {
|
||||
node_boardcast_list := device.graph.GetBoardcastThroughList(device.ID, in_id, src_nodeID)
|
||||
for peer_id := range node_boardcast_list {
|
||||
peer_out := device.peers.IDMap[peer_id]
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Transfer packet from %d through %d to %d\n", in_id, device.ID, peer_out.ID)
|
||||
}
|
||||
device.SendPacket(peer_out, packet, offset)
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) Send2Super(packet []byte, offset int) {
|
||||
if device.DRoute.SuperNode.UseSuperNode {
|
||||
for _, peer_out := range device.peers.SuperPeer {
|
||||
if device.LogTransit {
|
||||
fmt.Printf("Send to supernode %s\n", peer_out.endpoint.DstToString())
|
||||
}
|
||||
device.SendPacket(peer_out, packet, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) CheckNoDup(packet []byte) bool {
|
||||
hasher := crc32.New(crc32.MakeTable(crc32.Castagnoli))
|
||||
hasher.Write(packet)
|
||||
crc32result := hasher.Sum32()
|
||||
_, ok := device.DupData.Get(crc32result)
|
||||
device.DupData.Set(crc32result, true)
|
||||
return !ok
|
||||
}
|
||||
|
||||
func (device *Device) process_received(msg_type path.Usage, body []byte) (err error) {
|
||||
if device.IsSuperNode {
|
||||
switch msg_type {
|
||||
case path.Register:
|
||||
if content, err := path.ParseRegisterMsg(body); err == nil {
|
||||
return device.server_process_RegisterMsg(content)
|
||||
}
|
||||
case path.PongPacket:
|
||||
if content, err := path.ParsePongMsg(body); err == nil {
|
||||
return device.server_process_Pong(content)
|
||||
}
|
||||
default:
|
||||
err = errors.New("Not a valid msg_type")
|
||||
}
|
||||
} else {
|
||||
switch msg_type {
|
||||
case path.UpdatePeer:
|
||||
if content, err := path.ParseUpdatePeerMsg(body); err == nil {
|
||||
go device.process_UpdatePeerMsg(content)
|
||||
}
|
||||
case path.UpdateNhTable:
|
||||
if content, err := path.ParseUpdateNhTableMsg(body); err == nil {
|
||||
go device.process_UpdateNhTableMsg(content)
|
||||
}
|
||||
case path.PingPacket:
|
||||
if content, err := path.ParsePingMsg(body); err == nil {
|
||||
return device.process_ping(content)
|
||||
}
|
||||
case path.PongPacket:
|
||||
if content, err := path.ParsePongMsg(body); err == nil {
|
||||
return device.process_pong(content)
|
||||
}
|
||||
case path.RequestPeer:
|
||||
if content, err := path.ParseRequestPeerMsg(body); err == nil {
|
||||
return device.process_RequestPeerMsg(content)
|
||||
}
|
||||
case path.BoardcastPeer:
|
||||
if content, err := path.ParseBoardcastPeerMsg(body); err == nil {
|
||||
return device.process_BoardcastPeerMsg(content)
|
||||
}
|
||||
default:
|
||||
err = errors.New("Not a valid msg_type")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (device *Device) server_process_RegisterMsg(content path.RegisterMsg) error {
|
||||
device.Event_server_register <- content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) server_process_Pong(content path.PongMsg) error {
|
||||
device.Event_server_pong <- content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) process_ping(content path.PingMsg) error {
|
||||
PongMSG := path.PongMsg{
|
||||
Src_nodeID: content.Src_nodeID,
|
||||
Dst_nodeID: device.ID,
|
||||
Timediff: device.graph.GetCurrentTime().Sub(content.Time),
|
||||
}
|
||||
body, err := path.GetByte(&PongMSG)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, err := path.NewEgHeader(buf[:path.EgHeaderLen])
|
||||
header.SetSrc(device.ID)
|
||||
header.SetTTL(200)
|
||||
header.SetUsage(path.PongPacket)
|
||||
header.SetPacketLength(uint16(len(body)))
|
||||
if device.DRoute.SuperNode.UseSuperNode {
|
||||
header.SetDst(path.SuperNodeMessage)
|
||||
device.Send2Super(buf, MessageTransportOffsetContent)
|
||||
}
|
||||
if device.DRoute.P2P.UseP2P {
|
||||
header.SetDst(path.ControlMessage)
|
||||
device.SpreadPacket(make(map[config.Vertex]bool), buf, MessageTransportOffsetContent)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) process_pong(content path.PongMsg) error {
|
||||
if device.DRoute.P2P.UseP2P {
|
||||
device.graph.UpdateLentancy(content.Src_nodeID, content.Dst_nodeID, content.Timediff, false)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) process_UpdatePeerMsg(content path.UpdatePeerMsg) error {
|
||||
var send_signal bool
|
||||
if device.DRoute.SuperNode.UseSuperNode {
|
||||
var peer_infos config.HTTP_Peers
|
||||
if bytes.Equal(device.peers.Peer_state[:], content.State_hash[:]) {
|
||||
return nil
|
||||
}
|
||||
resp, err := http.Get(device.DRoute.SuperNode.APIUrl + "/peerinfo?PubKey=" + PubKey2Str(device.staticIdentity.publicKey) + "?State=" + string(content.State_hash[:]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
allbytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(allbytes, &peer_infos); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for pubkey, peerinfo := range peer_infos.Peers {
|
||||
if len(peerinfo.Connurl) == 0 {
|
||||
return nil
|
||||
}
|
||||
sk := Str2PubKey(pubkey)
|
||||
if bytes.Equal(sk[:], device.staticIdentity.publicKey[:]) {
|
||||
continue
|
||||
}
|
||||
thepeer := device.LookupPeer(sk)
|
||||
if thepeer == nil { //not exist in local
|
||||
if device.graph.Weight(device.ID, peerinfo.NodeID) == path.Infinity { // add node to graph
|
||||
device.graph.UpdateLentancy(device.ID, peerinfo.NodeID, path.S2TD(path.Infinity), false)
|
||||
}
|
||||
if device.graph.Weight(peerinfo.NodeID, device.ID) == path.Infinity { // add node to graph
|
||||
device.graph.UpdateLentancy(peerinfo.NodeID, device.ID, path.S2TD(path.Infinity), false)
|
||||
}
|
||||
device.NewPeer(sk, peerinfo.NodeID)
|
||||
thepeer = device.LookupPeer(sk)
|
||||
if peerinfo.PSKey != "" {
|
||||
pk := Str2PSKey(peerinfo.PSKey)
|
||||
thepeer.handshake.presharedKey = pk
|
||||
}
|
||||
}
|
||||
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).Before(time.Now()) {
|
||||
//Peer died, try to switch to this new endpoint
|
||||
for url, _ := range peerinfo.Connurl {
|
||||
thepeer.endpoint_trylist[url] = time.Time{} //another gorouting will process it
|
||||
send_signal = true
|
||||
}
|
||||
}
|
||||
}
|
||||
device.peers.Peer_state = content.State_hash
|
||||
if send_signal {
|
||||
device.event_tryendpoint <- struct{}{}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) RoutineSetEndpoint() {
|
||||
if !(device.DRoute.P2P.UseP2P || device.DRoute.SuperNode.UseSuperNode) {
|
||||
return
|
||||
}
|
||||
for {
|
||||
NextRun := false
|
||||
<-device.event_tryendpoint
|
||||
for _, thepeer := range device.peers.IDMap {
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).After(time.Now()) {
|
||||
//Peer alives
|
||||
for url := range thepeer.endpoint_trylist {
|
||||
delete(thepeer.endpoint_trylist, url)
|
||||
}
|
||||
} else {
|
||||
//Peer died, try to switch to this new endpoint
|
||||
for url, trytime := range thepeer.endpoint_trylist {
|
||||
if trytime.Sub(time.Time{}) != time.Duration(0) && time.Now().Sub(trytime) > path.S2TD(device.DRoute.ConnTimeOut) {
|
||||
delete(thepeer.endpoint_trylist, url)
|
||||
} else {
|
||||
endpoint, err := device.Bind().ParseEndpoint(url) //trying to bind first url in the list and wait device.DRoute.P2P.PeerAliveTimeout seconds
|
||||
if err != nil {
|
||||
device.log.Errorf("Can't bind " + url)
|
||||
delete(thepeer.endpoint_trylist, url)
|
||||
}
|
||||
thepeer.SetEndpointFromPacket(endpoint)
|
||||
NextRun = true
|
||||
thepeer.endpoint_trylist[url] = time.Now()
|
||||
//Send Ping message to it
|
||||
packet, err := device.GeneratePingPacket(device.ID)
|
||||
device.SendPacket(thepeer, packet, MessageTransportOffsetContent)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClearChanLoop:
|
||||
for {
|
||||
select {
|
||||
case <-device.event_tryendpoint:
|
||||
default:
|
||||
break ClearChanLoop
|
||||
}
|
||||
}
|
||||
time.Sleep(path.S2TD(device.DRoute.P2P.PeerAliveTimeout))
|
||||
if NextRun {
|
||||
go device.SaveConfig()
|
||||
device.event_tryendpoint <- struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) SaveConfig() {
|
||||
if device.DRoute.SaveNewPeers {
|
||||
configbytes, _ := yaml.Marshal(device.EdgeConfig)
|
||||
ioutil.WriteFile(device.EdgeConfigPath, configbytes, 0666)
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) RoutineSendPing() {
|
||||
if !(device.DRoute.P2P.UseP2P || device.DRoute.SuperNode.UseSuperNode) {
|
||||
return
|
||||
}
|
||||
for {
|
||||
packet, _ := device.GeneratePingPacket(device.ID)
|
||||
device.SpreadPacket(make(map[config.Vertex]bool), packet, MessageTransportOffsetContent)
|
||||
time.Sleep(path.S2TD(device.DRoute.SendPingInterval))
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) RoutineRegister() {
|
||||
if !(device.DRoute.SuperNode.UseSuperNode) {
|
||||
return
|
||||
}
|
||||
for {
|
||||
body, _ := path.GetByte(path.RegisterMsg{
|
||||
Node_id: device.ID,
|
||||
})
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
|
||||
header.SetDst(path.SuperNodeMessage)
|
||||
header.SetTTL(0)
|
||||
header.SetSrc(device.ID)
|
||||
header.SetUsage(path.Register)
|
||||
header.SetPacketLength(uint16(len(body)))
|
||||
copy(buf[path.EgHeaderLen:], body)
|
||||
device.Send2Super(buf, MessageTransportOffsetContent)
|
||||
time.Sleep(path.S2TD(device.DRoute.SendPingInterval))
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) RoutineRecalculateNhTable() {
|
||||
if device.IsSuperNode {
|
||||
for {
|
||||
changed := device.graph.RecalculateNhTable(true)
|
||||
if changed {
|
||||
device.Event_server_NhTable_changed <- struct{}{}
|
||||
}
|
||||
time.Sleep(device.graph.NodeReportTimeout)
|
||||
}
|
||||
} else {
|
||||
if !device.DRoute.P2P.UseP2P {
|
||||
return
|
||||
}
|
||||
for {
|
||||
|
||||
device.graph.RecalculateNhTable(false)
|
||||
time.Sleep(device.graph.NodeReportTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (device *Device) GeneratePingPacket(src_nodeID config.Vertex) ([]byte, error) {
|
||||
body, err := path.GetByte(&path.PingMsg{
|
||||
Src_nodeID: src_nodeID,
|
||||
Time: device.graph.GetCurrentTime(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
header.SetDst(path.PingMessage)
|
||||
header.SetTTL(0)
|
||||
header.SetSrc(device.ID)
|
||||
header.SetUsage(path.PingPacket)
|
||||
header.SetPacketLength(uint16(len(body)))
|
||||
copy(buf[path.EgHeaderLen:], body)
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (device *Device) process_UpdateNhTableMsg(content path.UpdateNhTableMsg) error {
|
||||
if device.DRoute.SuperNode.UseSuperNode {
|
||||
if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) {
|
||||
return nil
|
||||
}
|
||||
var NhTable config.NextHopTable
|
||||
if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) {
|
||||
return nil
|
||||
}
|
||||
resp, err := http.Get(device.DRoute.SuperNode.APIUrl + "/nhtable?PubKey=" + PubKey2Str(device.staticIdentity.publicKey) + "?State=" + string(content.State_hash[:]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
allbytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(allbytes, &NhTable); err != nil {
|
||||
return err
|
||||
}
|
||||
device.graph.SetNHTable(NhTable, content.State_hash)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) process_RequestPeerMsg(content path.RequestPeerMsg) error {
|
||||
if device.DRoute.P2P.UseP2P {
|
||||
for pubkey, peer := range device.peers.keyMap {
|
||||
if peer.ID >= path.Special_NodeID {
|
||||
continue
|
||||
}
|
||||
|
||||
response := path.BoardcastPeerMsg{
|
||||
RequestID: content.Request_ID,
|
||||
NodeID: peer.ID,
|
||||
PubKey: pubkey,
|
||||
PSKey: peer.handshake.presharedKey,
|
||||
ConnURL: peer.endpoint.DstToString(),
|
||||
}
|
||||
body, err := path.GetByte(response)
|
||||
if err != nil {
|
||||
device.log.Errorf("Error at receivesendproc.go line221: ", err)
|
||||
continue
|
||||
}
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
|
||||
header.SetDst(path.ControlMessage)
|
||||
header.SetTTL(200)
|
||||
header.SetSrc(device.ID)
|
||||
header.SetUsage(path.BoardcastPeer)
|
||||
header.SetPacketLength(uint16(len(body)))
|
||||
copy(buf[path.EgHeaderLen:], body)
|
||||
device.SpreadPacket(make(map[config.Vertex]bool), buf, MessageTransportOffsetContent)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) process_BoardcastPeerMsg(content path.BoardcastPeerMsg) error {
|
||||
if device.DRoute.P2P.UseP2P {
|
||||
var sk NoisePublicKey
|
||||
copy(sk[:], content.PubKey[:])
|
||||
thepeer := device.LookupPeer(sk)
|
||||
if thepeer == nil { //not exist in local
|
||||
if device.graph.Weight(device.ID, content.NodeID) == path.Infinity { // add node to graph
|
||||
device.graph.UpdateLentancy(device.ID, content.NodeID, path.S2TD(path.Infinity), false)
|
||||
}
|
||||
if device.graph.Weight(content.NodeID, device.ID) == path.Infinity { // add node to graph
|
||||
device.graph.UpdateLentancy(content.NodeID, device.ID, path.S2TD(path.Infinity), false)
|
||||
}
|
||||
device.NewPeer(sk, content.NodeID)
|
||||
thepeer = device.LookupPeer(sk)
|
||||
var pk NoisePresharedKey
|
||||
copy(pk[:], content.PSKey[:])
|
||||
thepeer.handshake.presharedKey = pk
|
||||
}
|
||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).Before(time.Now()) {
|
||||
//Peer died, try to switch to this new endpoint
|
||||
thepeer.endpoint_trylist[content.ConnURL] = time.Time{} //another gorouting will process it
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
@ -14,6 +14,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
@ -258,12 +259,13 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
}
|
||||
EgBody.SetSrc(device.ID)
|
||||
EgBody.SetDst(dst_nodeID)
|
||||
//EgBody.SetPacketLength(uint16(len(elem.packet)))
|
||||
EgBody.SetPacketLength(uint16(len(elem.packet)))
|
||||
EgBody.SetTTL(200)
|
||||
EgBody.SetUsage(path.NornalPacket)
|
||||
|
||||
if dst_nodeID != path.Boardcast {
|
||||
var peer_out *Peer
|
||||
next_id := *device.NhTable[device.ID][dst_nodeID]
|
||||
next_id := *device.graph.NhTable[device.ID][dst_nodeID]
|
||||
peer_out = device.peers.IDMap[next_id]
|
||||
if peer_out == nil {
|
||||
continue
|
||||
@ -274,29 +276,12 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
peer_out.SendStagedPackets()
|
||||
}
|
||||
} else {
|
||||
for key, _ := range path.GetBoardcastList(device.ID, device.NhTable) {
|
||||
device.SendPacket(device.peers.IDMap[key], elem.packet, offset)
|
||||
}
|
||||
device.BoardcastPacket(make(map[config.Vertex]bool, 0), elem.packet, offset)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) SendPacket(peer *Peer, packet []byte, offset int) {
|
||||
if peer == nil {
|
||||
return
|
||||
}
|
||||
var elem *QueueOutboundElement
|
||||
elem = device.NewOutboundElement()
|
||||
copy(elem.buffer[offset:offset+len(packet)], packet)
|
||||
elem.packet = elem.buffer[offset : offset+len(packet)]
|
||||
if peer.isRunning.Get() {
|
||||
peer.StagePacket(elem)
|
||||
elem = nil
|
||||
peer.SendStagedPackets()
|
||||
}
|
||||
}
|
||||
|
||||
func (peer *Peer) StagePacket(elem *QueueOutboundElement) {
|
||||
for {
|
||||
select {
|
||||
|
@ -19,8 +19,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ipc"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
type IPCError struct {
|
||||
@ -284,7 +284,7 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error
|
||||
|
||||
peer.created = peer.Peer == nil
|
||||
if peer.created {
|
||||
peer.Peer, err = device.NewPeer(publicKey, path.Vertex(h.Sum32()))
|
||||
peer.Peer, err = device.NewPeer(publicKey, config.Vertex(h.Sum32()))
|
||||
if err != nil {
|
||||
return ipcErrorf(ipc.IpcErrorInvalid, "failed to create new peer: %w", err)
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -3,6 +3,7 @@ module github.com/KusakabeSi/EtherGuardVPN
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/KusakabeSi/go-cache v0.0.0-20210817164551-57817be43e28
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
|
20
main.go
20
main.go
@ -43,18 +43,14 @@ func readYaml(filePath string, out interface{}) (err error) {
|
||||
}
|
||||
|
||||
var (
|
||||
config = flag.String("config", "", "Config path for the interface.")
|
||||
mode = flag.String("mode", "edge", "Running mode. [super|edge]")
|
||||
version = flag.Bool("version", false, "Show version")
|
||||
help = flag.Bool("help", false, "Show this help")
|
||||
nouapi = flag.Bool("no-uapi", false, "Do not use UAPI")
|
||||
tconfig = flag.String("config", "", "Config path for the interface.")
|
||||
mode = flag.String("mode", "edge", "Running mode. [super|edge]")
|
||||
printExample = flag.Bool("example", false, "Print example config")
|
||||
nouapi = flag.Bool("no-uapi", false, "Do not use UAPI")
|
||||
version = flag.Bool("version", false, "Show version")
|
||||
help = flag.Bool("help", false, "Show this help")
|
||||
)
|
||||
|
||||
type LoggerInfo struct {
|
||||
LogLevel string
|
||||
LogTransit bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *version == true {
|
||||
@ -73,9 +69,9 @@ func main() {
|
||||
|
||||
switch *mode {
|
||||
case "edge":
|
||||
Edge(*config, !*nouapi)
|
||||
Edge(*tconfig, !*nouapi, *printExample)
|
||||
case "super":
|
||||
Super(*config, !*nouapi)
|
||||
Super(*tconfig, !*nouapi, *printExample)
|
||||
case "path":
|
||||
path.Solve()
|
||||
default:
|
||||
|
262
main_edge.go
262
main_edge.go
@ -9,6 +9,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
@ -16,93 +17,130 @@ import (
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/device"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ipc"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type edgeConfig struct {
|
||||
Interface InterfaceConf
|
||||
NodeID path.Vertex
|
||||
NodeName string
|
||||
PrivKey string
|
||||
ListenPort int
|
||||
LogLevel LoggerInfo
|
||||
SuperNode SuperInfo
|
||||
NextHopTable path.NextHopTable
|
||||
Peers []PeerInfo
|
||||
}
|
||||
func printExampleEdgeConf() {
|
||||
tconfig := config.EdgeConfig{
|
||||
Interface: config.InterfaceConf{
|
||||
Itype: "stdio",
|
||||
IfaceID: 5,
|
||||
Name: "tap1",
|
||||
MacAddr: "AA:BB:CC:DD:EE:FF",
|
||||
MTU: 1400,
|
||||
RecvAddr: "127.0.0.1:4001",
|
||||
SendAddr: "127.0.0.1:5001",
|
||||
HumanFriendly: true,
|
||||
},
|
||||
NodeID: 1,
|
||||
NodeName: "Node01",
|
||||
PrivKey: "SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng=",
|
||||
ListenPort: 3001,
|
||||
LogLevel: config.LoggerInfo{
|
||||
LogLevel: "normal",
|
||||
LogTransit: true,
|
||||
},
|
||||
DynamicRoute: config.DynamicRouteInfo{
|
||||
SendPingInterval: 20,
|
||||
DupCheckTimeout: 40,
|
||||
ConnTimeOut: 30,
|
||||
SaveNewPeers: true,
|
||||
SuperNode: config.SuperInfo{
|
||||
UseSuperNode: true,
|
||||
ConnURLV4: "127.0.0.1:3000",
|
||||
PubKeyV4: "j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y=",
|
||||
ConnURLV6: "[::1]:3000",
|
||||
PubKeyV6: "cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw=",
|
||||
APIUrl: "http://127.0.0.1:3000/api",
|
||||
SuperNodeInfoTimeout: 40,
|
||||
},
|
||||
P2P: config.P2Pinfo{
|
||||
UseP2P: true,
|
||||
SendPeerInterval: 20,
|
||||
PeerAliveTimeout: 30,
|
||||
GraphRecalculateSetting: config.GraphRecalculateSetting{
|
||||
JitterTolerance: 20,
|
||||
JitterToleranceMultiplier: 1.1,
|
||||
NodeReportTimeout: 40,
|
||||
RecalculateCoolDown: 5,
|
||||
},
|
||||
},
|
||||
NTPconfig: config.NTPinfo{
|
||||
UseNTP: true,
|
||||
MaxServerUse: 5,
|
||||
Servers: []string{"time.google.com",
|
||||
"time1.google.com",
|
||||
"time2.google.com",
|
||||
"time3.google.com",
|
||||
"time4.google.com",
|
||||
"time1.facebook.com",
|
||||
"time2.facebook.com",
|
||||
"time3.facebook.com",
|
||||
"time4.facebook.com",
|
||||
"time5.facebook.com",
|
||||
"time.cloudflare.com",
|
||||
"time.apple.com",
|
||||
"time.asia.apple.com",
|
||||
"time.euro.apple.com",
|
||||
"time.windows.com"},
|
||||
},
|
||||
},
|
||||
NextHopTable: config.NextHopTable{},
|
||||
Peers: []config.PeerInfo{
|
||||
{
|
||||
NodeID: 2,
|
||||
PubKey: "NuYJ/3Ght+C4HovFq5Te/BrIazo6zwDJ8Bdu4rQCz0o=",
|
||||
EndPoint: "127.0.0.1:3002",
|
||||
Static: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
g := path.NewGraph(3, false, tconfig.DynamicRoute.P2P.GraphRecalculateSetting)
|
||||
|
||||
type InterfaceConf struct {
|
||||
Itype string
|
||||
IfaceID int
|
||||
Name string
|
||||
MacAddr string
|
||||
MTU int
|
||||
RecvAddr string
|
||||
SendAddr string
|
||||
HumanFriendly bool
|
||||
}
|
||||
|
||||
type SuperInfo struct {
|
||||
Enable bool
|
||||
PubKeyV4 string
|
||||
PubKeyV6 string
|
||||
RegURLV4 string
|
||||
RegURLV6 string
|
||||
APIUrl string
|
||||
}
|
||||
|
||||
type PeerInfo struct {
|
||||
NodeID path.Vertex
|
||||
PubKey string
|
||||
EndPoint string
|
||||
}
|
||||
|
||||
func printExampleConf() {
|
||||
var config edgeConfig
|
||||
config.Peers = make([]PeerInfo, 3)
|
||||
var g path.IG
|
||||
g.Init(4)
|
||||
g.Edge(1, 2, 0.5)
|
||||
g.Edge(2, 1, 0.5)
|
||||
g.Edge(2, 3, 0.5)
|
||||
g.Edge(3, 2, 0.5)
|
||||
g.Edge(2, 4, 0.5)
|
||||
g.Edge(4, 2, 0.5)
|
||||
g.Edge(3, 4, 0.5)
|
||||
g.Edge(4, 3, 0.5)
|
||||
g.Edge(5, 3, 0.5)
|
||||
g.Edge(3, 5, 0.5)
|
||||
g.Edge(6, 4, 0.5)
|
||||
g.Edge(4, 6, 0.5)
|
||||
g.UpdateLentancy(1, 2, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(2, 1, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(2, 3, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(3, 2, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(2, 4, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(4, 2, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(3, 4, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(4, 3, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(5, 3, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(3, 5, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(6, 4, path.S2TD(0.5), false)
|
||||
g.UpdateLentancy(4, 6, path.S2TD(0.5), false)
|
||||
_, next := path.FloydWarshall(g)
|
||||
config.NextHopTable = next
|
||||
test, _ := yaml.Marshal(config)
|
||||
fmt.Print(string(test))
|
||||
tconfig.NextHopTable = next
|
||||
toprint, _ := yaml.Marshal(tconfig)
|
||||
fmt.Print(string(toprint))
|
||||
return
|
||||
}
|
||||
|
||||
func Edge(configPath string, useUAPI bool) (err error) {
|
||||
|
||||
var config edgeConfig
|
||||
func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
if printExample {
|
||||
printExampleEdgeConf()
|
||||
return nil
|
||||
}
|
||||
var tconfig config.EdgeConfig
|
||||
//printExampleConf()
|
||||
//return
|
||||
|
||||
err = readYaml(configPath, &config)
|
||||
err = readYaml(configPath, &tconfig)
|
||||
if err != nil {
|
||||
fmt.Printf("Error read config: %s :", configPath)
|
||||
fmt.Print(err)
|
||||
return err
|
||||
}
|
||||
|
||||
interfaceName := config.NodeName
|
||||
interfaceName := tconfig.NodeName
|
||||
|
||||
var logLevel int
|
||||
switch config.LogLevel.LogLevel {
|
||||
switch tconfig.LogLevel.LogLevel {
|
||||
case "verbose", "debug":
|
||||
logLevel = device.LogLevelVerbose
|
||||
case "error":
|
||||
@ -110,14 +148,11 @@ func Edge(configPath string, useUAPI bool) (err error) {
|
||||
case "silent":
|
||||
logLevel = device.LogLevelSilent
|
||||
}
|
||||
|
||||
logger := device.NewLogger(
|
||||
logLevel,
|
||||
fmt.Sprintf("(%s) ", interfaceName),
|
||||
)
|
||||
|
||||
logger.Verbosef("Starting wireguard-go version %s", Version)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("UAPI listen error: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
@ -126,40 +161,44 @@ func Edge(configPath string, useUAPI bool) (err error) {
|
||||
|
||||
var thetap tap.Device
|
||||
// open TUN device (or use supplied fd)
|
||||
switch config.Interface.Itype {
|
||||
switch tconfig.Interface.Itype {
|
||||
case "dummy":
|
||||
thetap, err = tap.CreateDummyTAP()
|
||||
case "stdio":
|
||||
thetap, err = tap.CreateStdIOTAP(config.Interface.Name, config.Interface.HumanFriendly)
|
||||
thetap, err = tap.CreateStdIOTAP(tconfig.Interface.Name, tconfig.Interface.HumanFriendly)
|
||||
case "udpsock":
|
||||
{
|
||||
lis, _ := net.ResolveUDPAddr("udp", config.Interface.RecvAddr)
|
||||
sen, _ := net.ResolveUDPAddr("udp", config.Interface.SendAddr)
|
||||
thetap, err = tap.CreateUDPSockTAP(config.Interface.Name, lis, sen, config.Interface.HumanFriendly)
|
||||
lis, _ := net.ResolveUDPAddr("udp", tconfig.Interface.RecvAddr)
|
||||
sen, _ := net.ResolveUDPAddr("udp", tconfig.Interface.SendAddr)
|
||||
thetap, err = tap.CreateUDPSockTAP(tconfig.Interface.Name, lis, sen, tconfig.Interface.HumanFriendly)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to create TUN device: %v", err)
|
||||
logger.Errorf("Failed to create TAP device: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Config
|
||||
the_device := device.NewDevice(thetap, config.NodeID, conn.NewDefaultBind(), logger)
|
||||
the_device.LogTransit = config.LogLevel.LogTransit
|
||||
the_device.NhTable = config.NextHopTable
|
||||
graph := path.NewGraph(3, false, tconfig.DynamicRoute.P2P.GraphRecalculateSetting)
|
||||
graph.SetNHTable(tconfig.NextHopTable, [32]byte{})
|
||||
|
||||
the_device := device.NewDevice(thetap, tconfig.NodeID, conn.NewDefaultBind(), logger, &graph, false, configPath, &tconfig, nil)
|
||||
the_device.LogTransit = tconfig.LogLevel.LogTransit
|
||||
defer the_device.Close()
|
||||
var sk [32]byte
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(config.PrivKey)
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(tconfig.PrivKey)
|
||||
copy(sk[:], sk_slice)
|
||||
the_device.SetPrivateKey(sk)
|
||||
the_device.IpcSet("fwmark=0\n")
|
||||
the_device.IpcSet("listen_port=" + strconv.Itoa(config.ListenPort) + "\n")
|
||||
the_device.IpcSet("listen_port=" + strconv.Itoa(tconfig.ListenPort) + "\n")
|
||||
the_device.IpcSet("replace_peers=true\n")
|
||||
for _, peerconf := range config.Peers {
|
||||
for _, peerconf := range tconfig.Peers {
|
||||
sk_slice, _ = base64.StdEncoding.DecodeString(peerconf.PubKey)
|
||||
copy(sk[:], sk_slice)
|
||||
if peerconf.NodeID >= path.SuperNodeMessage {
|
||||
return errors.New(fmt.Sprintf("Invalid Node_id at peer %s\n", peerconf.PubKey))
|
||||
}
|
||||
the_device.NewPeer(sk, peerconf.NodeID)
|
||||
if peerconf.EndPoint != "" {
|
||||
peer := the_device.LookupPeer(sk)
|
||||
@ -172,45 +211,42 @@ func Edge(configPath string, useUAPI bool) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if tconfig.DynamicRoute.SuperNode.UseSuperNode {
|
||||
if tconfig.DynamicRoute.SuperNode.ConnURLV4 != "" {
|
||||
sk_slice, _ = base64.StdEncoding.DecodeString(tconfig.DynamicRoute.SuperNode.PubKeyV4)
|
||||
copy(sk[:], sk_slice)
|
||||
endpoint, err := the_device.Bind().ParseEndpoint(tconfig.DynamicRoute.SuperNode.ConnURLV4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
peer, err := the_device.NewPeer(sk, path.SuperNodeMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
}
|
||||
if tconfig.DynamicRoute.SuperNode.ConnURLV6 != "" {
|
||||
sk_slice, _ = base64.StdEncoding.DecodeString(tconfig.DynamicRoute.SuperNode.PubKeyV6)
|
||||
copy(sk[:], sk_slice)
|
||||
endpoint, err := the_device.Bind().ParseEndpoint(tconfig.DynamicRoute.SuperNode.ConnURLV6)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
peer, err := the_device.NewPeer(sk, path.SuperNodeMessage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
peer.SetEndpointFromPacket(endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Verbosef("Device started")
|
||||
|
||||
errs := make(chan error)
|
||||
term := make(chan os.Signal, 1)
|
||||
|
||||
if useUAPI {
|
||||
|
||||
fileUAPI, err := func() (*os.File, error) {
|
||||
uapiFdStr := os.Getenv(ENV_WP_UAPI_FD)
|
||||
if uapiFdStr == "" {
|
||||
return ipc.UAPIOpen(interfaceName)
|
||||
}
|
||||
|
||||
// use supplied fd
|
||||
|
||||
fd, err := strconv.ParseUint(uapiFdStr, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.NewFile(uintptr(fd), ""), nil
|
||||
}()
|
||||
uapi, err := ipc.UAPIListen(interfaceName, fileUAPI)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to listen on uapi socket: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := uapi.Accept()
|
||||
if err != nil {
|
||||
errs <- err
|
||||
return
|
||||
}
|
||||
go the_device.IpcHandle(conn)
|
||||
}
|
||||
}()
|
||||
defer uapi.Close()
|
||||
logger.Verbosef("UAPI listener started")
|
||||
startUAPI(interfaceName, logger, the_device, errs)
|
||||
}
|
||||
|
||||
// wait for program to terminate
|
||||
|
72
main_httpserver.go
Normal file
72
main_httpserver.go
Normal file
@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/device"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
var (
|
||||
http_graph *path.IG
|
||||
http_device4 *device.Device
|
||||
http_device6 *device.Device
|
||||
http_NhTable_Hash string
|
||||
http_PeerInfo_hash string
|
||||
http_NhTableStr []byte
|
||||
http_PeerInfoStr []byte
|
||||
http_PeerState map[string]*PeerState
|
||||
http_PeerID2Map map[config.Vertex]string
|
||||
http_PeerInfos config.HTTP_Peers
|
||||
)
|
||||
|
||||
type PeerState struct {
|
||||
NhTableState string
|
||||
PeerInfoState string
|
||||
}
|
||||
|
||||
type client struct {
|
||||
ConnV4 net.Addr
|
||||
ConnV6 net.Addr
|
||||
InterV4 []net.Addr
|
||||
InterV6 []net.Addr
|
||||
notify4 string
|
||||
notify6 string
|
||||
}
|
||||
|
||||
func get_peerinfo(w http.ResponseWriter, r *http.Request) {
|
||||
params := r.URL.Query()
|
||||
PubKey, _ := params["PubKey"]
|
||||
State, _ := params["State"]
|
||||
if state := http_PeerState[PubKey[0]]; state != nil {
|
||||
http_PeerState[PubKey[0]].PeerInfoState = State[0]
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(http_PeerInfoStr))
|
||||
}
|
||||
|
||||
func get_nhtable(w http.ResponseWriter, r *http.Request) {
|
||||
params := r.URL.Query()
|
||||
PubKey, _ := params["PubKey"]
|
||||
State, _ := params["State"]
|
||||
if state := http_PeerState[PubKey[0]]; state != nil {
|
||||
http_PeerState[PubKey[0]].NhTableState = State[0]
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(http_NhTableStr))
|
||||
}
|
||||
|
||||
func HttpServer(http_port int, apiprefix string, graph *path.IG, device4 *device.Device, device6 *device.Device) {
|
||||
http_graph = graph
|
||||
http_device4 = device4
|
||||
http_device6 = device6
|
||||
http_PeerState = make(map[string]*PeerState)
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/"+apiprefix+"/peerinfo", get_peerinfo)
|
||||
mux.HandleFunc("/"+apiprefix+"/nhtable", get_nhtable)
|
||||
go http.ListenAndServe(":"+strconv.Itoa(http_port), mux)
|
||||
}
|
274
main_super.go
274
main_super.go
@ -7,6 +7,278 @@
|
||||
|
||||
package main
|
||||
|
||||
func Super(configPath string, useUAPI bool) {
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/conn"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/device"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/ipc"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
"github.com/KusakabeSi/EtherGuardVPN/tap"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func printExampleSuperConf() {
|
||||
sconfig := config.SuperConfig{
|
||||
NodeName: "NodeSuper",
|
||||
PrivKeyV4: "SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng=",
|
||||
PrivKeyV6: "SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng=",
|
||||
ListenPort: 3000,
|
||||
LogLevel: config.LoggerInfo{
|
||||
LogLevel: "normal",
|
||||
LogTransit: true,
|
||||
},
|
||||
Peers: []config.PeerInfo{
|
||||
{
|
||||
NodeID: 2,
|
||||
PubKey: "NuYJ/3Ght+C4HovFq5Te/BrIazo6zwDJ8Bdu4rQCz0o=",
|
||||
EndPoint: "127.0.0.1:3002",
|
||||
Static: true,
|
||||
},
|
||||
},
|
||||
GraphRecalculateSetting: config.GraphRecalculateSetting{
|
||||
JitterTolerance: 20,
|
||||
JitterToleranceMultiplier: 1.1,
|
||||
NodeReportTimeout: 40,
|
||||
RecalculateCoolDown: 5,
|
||||
},
|
||||
}
|
||||
|
||||
soprint, _ := yaml.Marshal(sconfig)
|
||||
fmt.Print(string(soprint))
|
||||
return
|
||||
}
|
||||
|
||||
func Super(configPath string, useUAPI bool, printExample bool) (err error) {
|
||||
if printExample {
|
||||
printExampleSuperConf()
|
||||
return nil
|
||||
}
|
||||
var sconfig config.SuperConfig
|
||||
err = readYaml(configPath, &sconfig)
|
||||
if err != nil {
|
||||
fmt.Printf("Error read config: %s :", configPath)
|
||||
fmt.Print(err)
|
||||
return err
|
||||
}
|
||||
interfaceName := sconfig.NodeName
|
||||
var logLevel int
|
||||
switch sconfig.LogLevel.LogLevel {
|
||||
case "verbose", "debug":
|
||||
logLevel = device.LogLevelVerbose
|
||||
case "error":
|
||||
logLevel = device.LogLevelError
|
||||
case "silent":
|
||||
logLevel = device.LogLevelSilent
|
||||
}
|
||||
|
||||
logger4 := device.NewLogger(
|
||||
logLevel,
|
||||
fmt.Sprintf("(%s) ", interfaceName+"_v4"),
|
||||
)
|
||||
logger6 := device.NewLogger(
|
||||
logLevel,
|
||||
fmt.Sprintf("(%s) ", interfaceName+"_v6"),
|
||||
)
|
||||
|
||||
super_chains := path.SUPER_Events{
|
||||
Event_server_pong: make(chan path.PongMsg, 1<<5),
|
||||
Event_server_register: make(chan path.RegisterMsg, 1<<5),
|
||||
Event_server_NhTable_changed: make(chan struct{}, 1<<4),
|
||||
}
|
||||
|
||||
thetap, _ := tap.CreateDummyTAP()
|
||||
graph := path.NewGraph(3, true, sconfig.GraphRecalculateSetting)
|
||||
device_v4 := device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(true, false), logger4, &graph, true, "", nil, &super_chains)
|
||||
device_v6 := device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(false, true), logger6, &graph, true, "", nil, &super_chains)
|
||||
defer device_v4.Close()
|
||||
defer device_v6.Close()
|
||||
var sk [32]byte
|
||||
sk_slice, _ := base64.StdEncoding.DecodeString(sconfig.PrivKeyV4)
|
||||
copy(sk[:], sk_slice)
|
||||
device_v4.SetPrivateKey(sk)
|
||||
sk_slice, _ = base64.StdEncoding.DecodeString(sconfig.PrivKeyV6)
|
||||
copy(sk[:], sk_slice)
|
||||
device_v6.SetPrivateKey(sk)
|
||||
device_v4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n")
|
||||
device_v6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n")
|
||||
device_v4.IpcSet("replace_peers=true\n")
|
||||
device_v6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n")
|
||||
|
||||
for _, peerconf := range sconfig.Peers {
|
||||
sk_slice, _ = base64.StdEncoding.DecodeString(peerconf.PubKey)
|
||||
copy(sk[:], sk_slice)
|
||||
if peerconf.NodeID >= path.SuperNodeMessage {
|
||||
return errors.New(fmt.Sprintf("Invalid Node_id at peer %s\n", peerconf.PubKey))
|
||||
}
|
||||
device_v4.NewPeer(sk, peerconf.NodeID)
|
||||
device_v6.NewPeer(sk, peerconf.NodeID)
|
||||
http_PeerState[peerconf.PubKey] = &PeerState{}
|
||||
}
|
||||
logger4.Verbosef("Device started")
|
||||
|
||||
errs := make(chan error, 1<<3)
|
||||
term := make(chan os.Signal, 1)
|
||||
if useUAPI {
|
||||
uapi4, err := startUAPI(interfaceName+"_v4", logger4, device_v4, errs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer uapi4.Close()
|
||||
uapi6, err := startUAPI(interfaceName+"_v6", logger6, device_v6, errs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer uapi6.Close()
|
||||
}
|
||||
signal.Notify(term, syscall.SIGTERM)
|
||||
signal.Notify(term, os.Interrupt)
|
||||
|
||||
select {
|
||||
case <-term:
|
||||
case <-errs:
|
||||
case <-device_v4.Wait():
|
||||
case <-device_v6.Wait():
|
||||
}
|
||||
logger4.Verbosef("Shutting down")
|
||||
return
|
||||
}
|
||||
|
||||
func Event_server_pong_hendler(graph path.IG, events path.SUPER_Events) {
|
||||
for {
|
||||
pongmsg := <-events.Event_server_pong
|
||||
changed := graph.UpdateLentancy(pongmsg.Src_nodeID, pongmsg.Dst_nodeID, pongmsg.Timediff, true)
|
||||
if changed {
|
||||
NhTable := graph.GetNHTable(false)
|
||||
NhTablestr, _ := json.Marshal(NhTable)
|
||||
md5_hash_raw := md5.Sum(http_NhTableStr)
|
||||
new_hash := hex.EncodeToString(md5_hash_raw[:])
|
||||
if http_NhTable_Hash != new_hash {
|
||||
http_NhTable_Hash = new_hash
|
||||
http_NhTableStr = NhTablestr
|
||||
NhTable_Hash_fixbyte := [32]byte{}
|
||||
copy(NhTable_Hash_fixbyte[:], []byte(http_NhTable_Hash))
|
||||
body, err := path.GetByte(path.UpdateNhTableMsg{
|
||||
State_hash: NhTable_Hash_fixbyte,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("Error get byte")
|
||||
continue
|
||||
}
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, _ := path.NewEgHeader(buf[:path.EgHeaderLen])
|
||||
header.SetDst(path.SuperNodeMessage)
|
||||
header.SetPacketLength(uint16(len(body)))
|
||||
header.SetSrc(path.SuperNodeMessage)
|
||||
header.SetTTL(0)
|
||||
header.SetUsage(path.UpdateNhTable)
|
||||
copy(buf[path.EgHeaderLen:], body)
|
||||
for pkstr, peerstate := range http_PeerState {
|
||||
if peerstate.NhTableState != http_NhTable_Hash {
|
||||
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil {
|
||||
http_device4.SendPacket(peer, buf, device.MessageTransportOffsetContent)
|
||||
}
|
||||
if peer := http_device6.LookupPeerByStr(pkstr); peer != nil {
|
||||
http_device6.SendPacket(peer, buf, device.MessageTransportOffsetContent)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Event_server_register_hendler(raph path.IG, events path.SUPER_Events) {
|
||||
for {
|
||||
reg_msg := <-events.Event_server_register
|
||||
PubKey := http_PeerID2Map[reg_msg.Node_id]
|
||||
if peer := http_device4.LookupPeerByStr(PubKey); peer != nil {
|
||||
if connstr := peer.GetEndpointDstStr(); connstr != "" {
|
||||
http_PeerInfos.Peers[PubKey].Connurl[connstr] = true
|
||||
}
|
||||
}
|
||||
if peer := http_device6.LookupPeerByStr(PubKey); peer != nil {
|
||||
if connstr := peer.GetEndpointDstStr(); connstr != "" {
|
||||
http_PeerInfos.Peers[PubKey].Connurl[connstr] = true
|
||||
}
|
||||
}
|
||||
http_PeerInfoStr, _ = json.Marshal(&http_PeerInfos)
|
||||
PeerInfo_hash_raw := md5.Sum(http_PeerInfoStr)
|
||||
PeerInfo_hash := hex.EncodeToString(PeerInfo_hash_raw[:])
|
||||
http_PeerInfo_hash_fixbyte := [32]byte{}
|
||||
copy(http_PeerInfo_hash_fixbyte[:], []byte(PeerInfo_hash))
|
||||
if http_PeerInfo_hash != PeerInfo_hash {
|
||||
http_PeerInfo_hash = PeerInfo_hash
|
||||
body, err := path.GetByte(path.UpdatePeerMsg{
|
||||
State_hash: http_PeerInfo_hash_fixbyte,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("Error get byte")
|
||||
continue
|
||||
}
|
||||
buf := make([]byte, path.EgHeaderLen+len(body))
|
||||
header, _ := path.NewEgHeader(buf[:path.EgHeaderLen])
|
||||
header.SetDst(path.SuperNodeMessage)
|
||||
header.SetPacketLength(uint16(len(body)))
|
||||
header.SetSrc(path.SuperNodeMessage)
|
||||
header.SetTTL(0)
|
||||
header.SetUsage(path.UpdatePeer)
|
||||
copy(buf[path.EgHeaderLen:], body)
|
||||
for pkstr, peerstate := range http_PeerState {
|
||||
if peerstate.PeerInfoState != PeerInfo_hash {
|
||||
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil {
|
||||
http_device4.SendPacket(peer, buf, device.MessageTransportOffsetContent)
|
||||
}
|
||||
if peer := http_device6.LookupPeerByStr(pkstr); peer != nil {
|
||||
http_device6.SendPacket(peer, buf, device.MessageTransportOffsetContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) {
|
||||
fileUAPI, err := func() (*os.File, error) {
|
||||
uapiFdStr := os.Getenv(ENV_WP_UAPI_FD)
|
||||
if uapiFdStr == "" {
|
||||
return ipc.UAPIOpen(interfaceName)
|
||||
}
|
||||
// use supplied fd
|
||||
fd, err := strconv.ParseUint(uapiFdStr, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.NewFile(uintptr(fd), ""), nil
|
||||
}()
|
||||
uapi, err := ipc.UAPIListen(interfaceName, fileUAPI)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to listen on uapi socket: %v", err)
|
||||
os.Exit(ExitSetupFailed)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := uapi.Accept()
|
||||
if err != nil {
|
||||
errs <- err
|
||||
return
|
||||
}
|
||||
go the_device.IpcHandle(conn)
|
||||
}
|
||||
}()
|
||||
logger.Verbosef("UAPI listener started")
|
||||
return uapi, err
|
||||
}
|
||||
|
@ -3,9 +3,11 @@ package path
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
)
|
||||
|
||||
const EgHeaderLen = 10
|
||||
const EgHeaderLen = 12
|
||||
|
||||
type EgHeader struct {
|
||||
buf []byte
|
||||
@ -15,8 +17,15 @@ type Usage uint8
|
||||
|
||||
const (
|
||||
NornalPacket Usage = iota
|
||||
PingSingleWay
|
||||
PingDualWay
|
||||
Register //Register to server
|
||||
|
||||
UpdatePeer //Comes from server
|
||||
UpdateNhTable
|
||||
|
||||
PingPacket //Comes from other peer
|
||||
PongPacket //Send to everyone, include server
|
||||
RequestPeer
|
||||
BoardcastPeer
|
||||
)
|
||||
|
||||
func NewEgHeader(pac []byte) (e EgHeader, err error) {
|
||||
@ -28,17 +37,17 @@ func NewEgHeader(pac []byte) (e EgHeader, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (e EgHeader) GetDst() Vertex {
|
||||
return Vertex(binary.BigEndian.Uint32(e.buf[0:4]))
|
||||
func (e EgHeader) GetDst() config.Vertex {
|
||||
return config.Vertex(binary.BigEndian.Uint32(e.buf[0:4]))
|
||||
}
|
||||
func (e EgHeader) SetDst(node_ID Vertex) {
|
||||
func (e EgHeader) SetDst(node_ID config.Vertex) {
|
||||
binary.BigEndian.PutUint32(e.buf[0:4], uint32(node_ID))
|
||||
}
|
||||
|
||||
func (e EgHeader) GetSrc() Vertex {
|
||||
return Vertex(binary.BigEndian.Uint32(e.buf[4:8]))
|
||||
func (e EgHeader) GetSrc() config.Vertex {
|
||||
return config.Vertex(binary.BigEndian.Uint32(e.buf[4:8]))
|
||||
}
|
||||
func (e EgHeader) SetSrc(node_ID Vertex) {
|
||||
func (e EgHeader) SetSrc(node_ID config.Vertex) {
|
||||
binary.BigEndian.PutUint32(e.buf[4:8], uint32(node_ID))
|
||||
}
|
||||
|
||||
@ -50,18 +59,16 @@ func (e EgHeader) SetTTL(ttl uint8) {
|
||||
e.buf[8] = ttl
|
||||
}
|
||||
|
||||
func (e EgHeader) GetUsage() uint8 {
|
||||
return e.buf[9]
|
||||
func (e EgHeader) GetUsage() Usage {
|
||||
return Usage(e.buf[9])
|
||||
}
|
||||
func (e EgHeader) SetUsage(usage uint8) {
|
||||
e.buf[9] = usage
|
||||
func (e EgHeader) SetUsage(usage Usage) {
|
||||
e.buf[9] = uint8(usage)
|
||||
}
|
||||
|
||||
/*
|
||||
func (e EgHeader) GetPacketLength() uint16 {
|
||||
return binary.BigEndian.Uint16(e.buf[10:12])
|
||||
}
|
||||
func (e EgHeader) SetPacketLength(length uint16) {
|
||||
binary.BigEndian.PutUint16(e.buf[10:12], length)
|
||||
}
|
||||
*/
|
||||
|
116
path/metamessage.go
Normal file
116
path/metamessage.go
Normal file
@ -0,0 +1,116 @@
|
||||
package path
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
)
|
||||
|
||||
func GetByte(structIn interface{}) (bb []byte, err error) {
|
||||
var b bytes.Buffer
|
||||
e := gob.NewEncoder(&b)
|
||||
if err := e.Encode(structIn); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bb = b.Bytes()
|
||||
return
|
||||
}
|
||||
|
||||
type RegisterMsg struct {
|
||||
Node_id config.Vertex
|
||||
}
|
||||
|
||||
func ParseRegisterMsg(bin []byte) (RegisterMsg, error) {
|
||||
var StructPlace RegisterMsg
|
||||
var b bytes.Buffer
|
||||
d := gob.NewDecoder(&b)
|
||||
err := d.Decode(&StructPlace)
|
||||
return StructPlace, err
|
||||
}
|
||||
|
||||
type UpdatePeerMsg struct {
|
||||
State_hash [32]byte
|
||||
}
|
||||
|
||||
func ParseUpdatePeerMsg(bin []byte) (UpdatePeerMsg, error) {
|
||||
var StructPlace UpdatePeerMsg
|
||||
var b bytes.Buffer
|
||||
d := gob.NewDecoder(&b)
|
||||
err := d.Decode(&StructPlace)
|
||||
return StructPlace, err
|
||||
}
|
||||
|
||||
type UpdateNhTableMsg struct {
|
||||
State_hash [32]byte
|
||||
}
|
||||
|
||||
func ParseUpdateNhTableMsg(bin []byte) (UpdateNhTableMsg, error) {
|
||||
var StructPlace UpdateNhTableMsg
|
||||
var b bytes.Buffer
|
||||
d := gob.NewDecoder(&b)
|
||||
err := d.Decode(&StructPlace)
|
||||
return StructPlace, err
|
||||
}
|
||||
|
||||
type PingMsg struct {
|
||||
Src_nodeID config.Vertex
|
||||
Time time.Time
|
||||
}
|
||||
|
||||
func ParsePingMsg(bin []byte) (PingMsg, error) {
|
||||
var StructPlace PingMsg
|
||||
var b bytes.Buffer
|
||||
d := gob.NewDecoder(&b)
|
||||
err := d.Decode(&StructPlace)
|
||||
return StructPlace, err
|
||||
}
|
||||
|
||||
type PongMsg struct {
|
||||
Src_nodeID config.Vertex
|
||||
Dst_nodeID config.Vertex
|
||||
Timediff time.Duration
|
||||
}
|
||||
|
||||
func ParsePongMsg(bin []byte) (PongMsg, error) {
|
||||
var StructPlace PongMsg
|
||||
var b bytes.Buffer
|
||||
d := gob.NewDecoder(&b)
|
||||
err := d.Decode(&StructPlace)
|
||||
return StructPlace, err
|
||||
}
|
||||
|
||||
type RequestPeerMsg struct {
|
||||
Request_ID uint32
|
||||
}
|
||||
|
||||
func ParseRequestPeerMsg(bin []byte) (RequestPeerMsg, error) {
|
||||
var StructPlace RequestPeerMsg
|
||||
var b bytes.Buffer
|
||||
d := gob.NewDecoder(&b)
|
||||
err := d.Decode(&StructPlace)
|
||||
return StructPlace, err
|
||||
}
|
||||
|
||||
type BoardcastPeerMsg struct {
|
||||
RequestID uint32
|
||||
NodeID config.Vertex
|
||||
PubKey [32]byte
|
||||
PSKey [32]byte
|
||||
ConnURL string
|
||||
}
|
||||
|
||||
func ParseBoardcastPeerMsg(bin []byte) (BoardcastPeerMsg, error) {
|
||||
var StructPlace BoardcastPeerMsg
|
||||
var b bytes.Buffer
|
||||
d := gob.NewDecoder(&b)
|
||||
err := d.Decode(&StructPlace)
|
||||
return StructPlace, err
|
||||
}
|
||||
|
||||
type SUPER_Events struct {
|
||||
Event_server_pong chan PongMsg
|
||||
Event_server_register chan RegisterMsg
|
||||
Event_server_NhTable_changed chan struct{}
|
||||
}
|
215
path/path.go
215
path/path.go
@ -5,85 +5,179 @@ import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
timeout = time.Second * 3
|
||||
const Infinity = float64(99999)
|
||||
|
||||
const (
|
||||
Boardcast config.Vertex = math.MaxUint32 - iota // Normal boardcast, boardcast with route table
|
||||
ControlMessage config.Vertex = math.MaxUint32 - iota // p2p mode: boardcast to every know keer and prevent dup/ super mode: send to supernode
|
||||
PingMessage config.Vertex = math.MaxUint32 - iota // boardsact to every know peer but don't transit
|
||||
SuperNodeMessage config.Vertex = math.MaxUint32 - iota
|
||||
Special_NodeID config.Vertex = SuperNodeMessage
|
||||
)
|
||||
|
||||
func (g *IG) GetCurrentTime() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// A Graph is the interface implemented by graphs that
|
||||
// this algorithm can run on.
|
||||
type Graph interface {
|
||||
Vertices() map[Vertex]bool
|
||||
Neighbors(v Vertex) []Vertex
|
||||
Weight(u, v Vertex) float64
|
||||
Vertices() map[config.Vertex]bool
|
||||
Neighbors(v config.Vertex) []config.Vertex
|
||||
Weight(u, v config.Vertex) float64
|
||||
}
|
||||
|
||||
// Nonnegative integer ID of vertex
|
||||
type Vertex uint32
|
||||
|
||||
const Infinity = 99999
|
||||
|
||||
var Boardcast = Vertex(math.MaxUint32)
|
||||
|
||||
type Latency struct {
|
||||
ping float64
|
||||
time time.Time
|
||||
}
|
||||
|
||||
type DistTable map[Vertex]map[Vertex]float64
|
||||
type NextHopTable map[Vertex]map[Vertex]*Vertex
|
||||
|
||||
type Fullroute struct {
|
||||
Dist DistTable `json:"total distance"`
|
||||
Next NextHopTable `json:"next hop"`
|
||||
Dist config.DistTable `json:"total distance"`
|
||||
Next config.NextHopTable `json:"next hop"`
|
||||
}
|
||||
|
||||
// IG is a graph of integers that satisfies the Graph interface.
|
||||
type IG struct {
|
||||
Vert map[Vertex]bool
|
||||
Edges map[Vertex]map[Vertex]Latency
|
||||
Vert map[config.Vertex]bool
|
||||
Edges map[config.Vertex]map[config.Vertex]Latency
|
||||
JitterTolerance float64
|
||||
JitterToleranceMultiplier float64
|
||||
NodeReportTimeout time.Duration
|
||||
SuperNodeInfoTimeout time.Duration
|
||||
RecalculateCoolDown time.Duration
|
||||
RecalculateTime time.Time
|
||||
dlTable config.DistTable
|
||||
NhTable config.NextHopTable
|
||||
NhTableHash [32]byte
|
||||
nhTableExpire time.Time
|
||||
IsSuperMode bool
|
||||
}
|
||||
|
||||
func (g *IG) Init(num_node int) error {
|
||||
g.Vert = make(map[Vertex]bool, num_node)
|
||||
g.Edges = make(map[Vertex]map[Vertex]Latency, num_node)
|
||||
return nil
|
||||
func S2TD(secs float64) time.Duration {
|
||||
return time.Duration(secs * float64(time.Second))
|
||||
}
|
||||
|
||||
func (g *IG) Edge(u, v Vertex, w float64) {
|
||||
func NewGraph(num_node int, IsSuperMode bool, theconfig config.GraphRecalculateSetting) IG {
|
||||
g := IG{
|
||||
JitterTolerance: theconfig.JitterTolerance,
|
||||
JitterToleranceMultiplier: theconfig.JitterToleranceMultiplier,
|
||||
NodeReportTimeout: S2TD(theconfig.NodeReportTimeout),
|
||||
RecalculateCoolDown: S2TD(theconfig.RecalculateCoolDown),
|
||||
}
|
||||
g.Vert = make(map[config.Vertex]bool, num_node)
|
||||
g.Edges = make(map[config.Vertex]map[config.Vertex]Latency, num_node)
|
||||
g.IsSuperMode = IsSuperMode
|
||||
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *IG) GetWeightType(x float64) float64 {
|
||||
x = math.Abs(x)
|
||||
y := x
|
||||
if g.JitterTolerance > 1 && g.JitterToleranceMultiplier > 0.001 {
|
||||
r := g.JitterTolerance
|
||||
m := g.JitterToleranceMultiplier
|
||||
y = math.Pow(math.Ceil(math.Pow(x/m, 1/r)), r) * m
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func (g *IG) ShouldUpdate(u config.Vertex, v config.Vertex, newval float64) bool {
|
||||
oldval := g.Weight(u, v) * 1000
|
||||
newval *= 1000
|
||||
if g.IsSuperMode {
|
||||
return (oldval-newval)*(oldval*g.JitterToleranceMultiplier) <= g.JitterTolerance
|
||||
} else {
|
||||
return g.GetWeightType(oldval) == g.GetWeightType(newval)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *IG) RecalculateNhTable(checkchange bool) (changed bool) {
|
||||
if g.RecalculateTime.Add(g.RecalculateCoolDown).Before(time.Now()) {
|
||||
dist, next := FloydWarshall(g)
|
||||
if checkchange {
|
||||
CheckLoop:
|
||||
for src, dsts := range next {
|
||||
for dst, cost := range dsts {
|
||||
nexthop := g.Next(src, dst)
|
||||
if nexthop != nil {
|
||||
changed = cost == nexthop
|
||||
if changed {
|
||||
break CheckLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g.dlTable, g.NhTable = dist, next
|
||||
g.nhTableExpire = time.Now().Add(g.NodeReportTimeout)
|
||||
g.RecalculateTime = time.Now()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (g *IG) UpdateLentancy(u, v config.Vertex, dt time.Duration, checkchange bool) (changed bool) {
|
||||
g.Vert[u] = true
|
||||
g.Vert[v] = true
|
||||
w := float64(dt) / float64(time.Second)
|
||||
if _, ok := g.Edges[u]; !ok {
|
||||
g.Edges[u] = make(map[Vertex]Latency)
|
||||
g.Edges[u] = make(map[config.Vertex]Latency)
|
||||
}
|
||||
if g.ShouldUpdate(u, v, w) {
|
||||
changed = g.RecalculateNhTable(checkchange)
|
||||
}
|
||||
g.Edges[u][v] = Latency{
|
||||
ping: w,
|
||||
time: time.Now(),
|
||||
}
|
||||
return
|
||||
}
|
||||
func (g IG) Vertices() map[Vertex]bool { return g.Vert }
|
||||
func (g IG) Neighbors(v Vertex) (vs []Vertex) {
|
||||
func (g IG) Vertices() map[config.Vertex]bool {
|
||||
return g.Vert
|
||||
}
|
||||
func (g IG) Neighbors(v config.Vertex) (vs []config.Vertex) {
|
||||
for k := range g.Edges[v] {
|
||||
vs = append(vs, k)
|
||||
}
|
||||
return vs
|
||||
}
|
||||
func (g IG) Weight(u, v Vertex) float64 {
|
||||
if time.Now().Sub(g.Edges[u][v].time) < timeout {
|
||||
return g.Edges[u][v].ping
|
||||
|
||||
func (g IG) Next(u, v config.Vertex) *config.Vertex {
|
||||
if _, ok := g.NhTable[u]; !ok {
|
||||
return nil
|
||||
}
|
||||
return Infinity
|
||||
if _, ok := g.NhTable[u][v]; !ok {
|
||||
return nil
|
||||
}
|
||||
return g.NhTable[u][v]
|
||||
}
|
||||
|
||||
func FloydWarshall(g Graph) (dist DistTable, next NextHopTable) {
|
||||
func (g IG) Weight(u, v config.Vertex) float64 {
|
||||
if _, ok := g.Edges[u]; !ok {
|
||||
g.Edges[u] = make(map[config.Vertex]Latency)
|
||||
return Infinity
|
||||
}
|
||||
if _, ok := g.Edges[u][v]; !ok {
|
||||
return Infinity
|
||||
}
|
||||
if time.Now().After(g.Edges[u][v].time.Add(g.NodeReportTimeout)) {
|
||||
return Infinity
|
||||
}
|
||||
return g.Edges[u][v].ping
|
||||
}
|
||||
|
||||
func FloydWarshall(g Graph) (dist config.DistTable, next config.NextHopTable) {
|
||||
vert := g.Vertices()
|
||||
dist = make(DistTable)
|
||||
next = make(NextHopTable)
|
||||
dist = make(config.DistTable)
|
||||
next = make(config.NextHopTable)
|
||||
for u, _ := range vert {
|
||||
dist[u] = make(map[Vertex]float64)
|
||||
next[u] = make(map[Vertex]*Vertex)
|
||||
dist[u] = make(map[config.Vertex]float64)
|
||||
next[u] = make(map[config.Vertex]*config.Vertex)
|
||||
for v, _ := range vert {
|
||||
dist[u][v] = Infinity
|
||||
}
|
||||
@ -112,11 +206,11 @@ func FloydWarshall(g Graph) (dist DistTable, next NextHopTable) {
|
||||
return dist, next
|
||||
}
|
||||
|
||||
func Path(u, v Vertex, next NextHopTable) (path []Vertex) {
|
||||
func Path(u, v config.Vertex, next config.NextHopTable) (path []config.Vertex) {
|
||||
if next[u][v] == nil {
|
||||
return []Vertex{}
|
||||
return []config.Vertex{}
|
||||
}
|
||||
path = []Vertex{u}
|
||||
path = []config.Vertex{u}
|
||||
for u != v {
|
||||
u = *next[u][v]
|
||||
path = append(path, u)
|
||||
@ -124,19 +218,32 @@ func Path(u, v Vertex, next NextHopTable) (path []Vertex) {
|
||||
return path
|
||||
}
|
||||
|
||||
func GetBoardcastList(id Vertex, nh NextHopTable) (tosend map[Vertex]bool) {
|
||||
tosend = make(map[Vertex]bool)
|
||||
for _, element := range nh[id] {
|
||||
func (g *IG) SetNHTable(nh config.NextHopTable, table_hash [32]byte) { // set nhTable from supernode
|
||||
g.NhTable = nh
|
||||
g.NhTableHash = table_hash
|
||||
g.nhTableExpire = time.Now().Add(g.SuperNodeInfoTimeout)
|
||||
}
|
||||
|
||||
func (g *IG) GetNHTable(checkChange bool) config.NextHopTable {
|
||||
if time.Now().After(g.nhTableExpire) {
|
||||
g.RecalculateNhTable(checkChange)
|
||||
}
|
||||
return g.NhTable
|
||||
}
|
||||
|
||||
func (g *IG) GetBoardcastList(id config.Vertex) (tosend map[config.Vertex]bool) {
|
||||
tosend = make(map[config.Vertex]bool)
|
||||
for _, element := range g.NhTable[id] {
|
||||
tosend[*element] = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetBoardcastThroughList(id Vertex, src Vertex, nh NextHopTable) (tosend map[Vertex]bool) {
|
||||
tosend = make(map[Vertex]bool)
|
||||
for check_id, _ := range GetBoardcastList(id, nh) {
|
||||
for _, path_node := range Path(src, check_id, nh) {
|
||||
if path_node == id {
|
||||
func (g *IG) GetBoardcastThroughList(self_id config.Vertex, in_id config.Vertex, src_id config.Vertex) (tosend map[config.Vertex]bool) {
|
||||
tosend = make(map[config.Vertex]bool)
|
||||
for check_id, _ := range g.GetBoardcastList(self_id) {
|
||||
for _, path_node := range Path(src_id, check_id, g.NhTable) {
|
||||
if path_node == self_id && check_id != in_id {
|
||||
tosend[check_id] = true
|
||||
continue
|
||||
}
|
||||
@ -147,13 +254,13 @@ func GetBoardcastThroughList(id Vertex, src Vertex, nh NextHopTable) (tosend map
|
||||
|
||||
func Solve() {
|
||||
var g IG
|
||||
g.Init(4)
|
||||
g.Edge(1, 2, 0.5)
|
||||
g.Edge(2, 1, 0.5)
|
||||
g.Edge(2, 3, 2)
|
||||
g.Edge(3, 2, 2)
|
||||
g.Edge(2, 4, 0.7)
|
||||
g.Edge(4, 2, 2)
|
||||
//g.Init()
|
||||
g.UpdateLentancy(1, 2, S2TD(0.5), false)
|
||||
g.UpdateLentancy(2, 1, S2TD(0.5), false)
|
||||
g.UpdateLentancy(2, 3, S2TD(2), false)
|
||||
g.UpdateLentancy(3, 2, S2TD(2), false)
|
||||
g.UpdateLentancy(2, 4, S2TD(0.7), false)
|
||||
g.UpdateLentancy(4, 2, S2TD(2), false)
|
||||
dist, next := FloydWarshall(g)
|
||||
fmt.Println("pair\tdist\tpath")
|
||||
for u, m := range dist {
|
||||
|
190
server.go
190
server.go
@ -1,190 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/KusakabeSi/EtherGuardVPN/path"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
ConnV4 net.Addr
|
||||
ConnV6 net.Addr
|
||||
InterV4 []net.Addr
|
||||
InterV6 []net.Addr
|
||||
notify4 string
|
||||
notify6 string
|
||||
}
|
||||
|
||||
type action struct {
|
||||
Action string `json:"a"`
|
||||
Node_ID int `json:"id"`
|
||||
Name string `json:"n"`
|
||||
}
|
||||
|
||||
type serverConf struct {
|
||||
UDP_port int `json:"port"`
|
||||
CONN_url string `json:"url"`
|
||||
USE_Oneway bool `json:"use_oneway"`
|
||||
}
|
||||
|
||||
type pathLentancy struct {
|
||||
NodeID_S int `json:"src"`
|
||||
NodeID_E int `json:"dst"`
|
||||
Latency float64 `json:"ping"`
|
||||
Is_Oneway bool `json:"oneway"`
|
||||
}
|
||||
|
||||
var (
|
||||
clients = []client{}
|
||||
graph = path.IG{}
|
||||
node_num = 10
|
||||
udp_port = 9595
|
||||
http_port = 9595
|
||||
)
|
||||
|
||||
func (c *client) hasV4() bool {
|
||||
return c.ConnV4.String() == ""
|
||||
}
|
||||
func (c *client) hasV6() bool {
|
||||
return c.ConnV6.String() == ""
|
||||
}
|
||||
func (c *client) online() bool {
|
||||
return c.hasV4() || c.hasV6()
|
||||
}
|
||||
|
||||
func serv(conn net.Conn, version int) {
|
||||
buffer := make([]byte, 1024)
|
||||
|
||||
_, err := conn.Read(buffer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
incoming := string(buffer)
|
||||
fmt.Println("[INCOMING]", conn.RemoteAddr(), incoming)
|
||||
theaction := action{}
|
||||
err = json.Unmarshal(buffer, &theaction)
|
||||
if err != nil {
|
||||
fmt.Println("[Error]", err)
|
||||
return
|
||||
}
|
||||
|
||||
if theaction.Action != "register" {
|
||||
fmt.Println("[Error]", "Unknow action", theaction.Action)
|
||||
return
|
||||
}
|
||||
if version == 4 {
|
||||
clients[theaction.Node_ID].ConnV4 = conn.RemoteAddr()
|
||||
} else if version == 6 {
|
||||
clients[theaction.Node_ID].ConnV6 = conn.RemoteAddr()
|
||||
}
|
||||
conn.Write([]byte("OK"))
|
||||
err = conn.Close()
|
||||
if err != nil {
|
||||
fmt.Println("[Error]", err)
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func accept(listener net.Listener, version int) {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
serv(conn, version)
|
||||
}
|
||||
}
|
||||
|
||||
// Server --
|
||||
func RegisterServer() {
|
||||
/*
|
||||
graph.Init(node_num)
|
||||
clients = make([]client, node_num)
|
||||
|
||||
addr4 := &net.UDPAddr{
|
||||
IP: net.IPv4zero,
|
||||
Port: udp_port,
|
||||
}
|
||||
addr6 := &net.UDPAddr{
|
||||
IP: net.IPv6zero,
|
||||
Port: udp_port,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Connect to a DTLS server
|
||||
listener4, err4 := dtls.Listen("udp4", addr4)
|
||||
if err4 != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer listener4.Close()
|
||||
listener6, err6 := dtls.Listen("udp6", addr6)
|
||||
if err6 != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer listener6.Close()
|
||||
if err4 != nil && err6 != nil {
|
||||
fmt.Println("udp4 and udp6 both failed!")
|
||||
return
|
||||
}
|
||||
go accept(listener4, 4)
|
||||
go accept(listener6, 6)*/
|
||||
}
|
||||
|
||||
func get_config(w http.ResponseWriter, r *http.Request) {
|
||||
rr, _ := json.Marshal(serverConf{
|
||||
UDP_port: udp_port,
|
||||
CONN_url: "https://example.com",
|
||||
})
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(rr)
|
||||
}
|
||||
|
||||
func get_neighbor(w http.ResponseWriter, r *http.Request) {
|
||||
rr, _ := json.Marshal(clients)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(rr)
|
||||
}
|
||||
|
||||
func get_route(w http.ResponseWriter, r *http.Request) {
|
||||
dist, next := path.FloydWarshall(graph)
|
||||
rr, _ := json.Marshal(path.Fullroute{
|
||||
Dist: dist,
|
||||
Next: next,
|
||||
})
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(rr)
|
||||
}
|
||||
|
||||
func post_latency(w http.ResponseWriter, r *http.Request) {
|
||||
body := make([]byte, r.ContentLength)
|
||||
info := pathLentancy{}
|
||||
err := json.Unmarshal(body, &info)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(fmt.Sprint(err)))
|
||||
return
|
||||
}
|
||||
if info.Is_Oneway {
|
||||
graph.Edge(path.Vertex(info.NodeID_S), path.Vertex(info.NodeID_E), info.Latency)
|
||||
} else {
|
||||
graph.Edge(path.Vertex(info.NodeID_S), path.Vertex(info.NodeID_E), info.Latency/2)
|
||||
graph.Edge(path.Vertex(info.NodeID_E), path.Vertex(info.NodeID_S), info.Latency/2)
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("OK"))
|
||||
}
|
||||
|
||||
func HttpServer() {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/api/neighbor/", get_neighbor)
|
||||
mux.HandleFunc("/api/route/", get_route)
|
||||
mux.HandleFunc("/api/latency/", post_latency)
|
||||
go http.ListenAndServe(":"+strconv.Itoa(http_port), mux)
|
||||
}
|
Loading…
Reference in New Issue
Block a user