WIP
This commit is contained in:
parent
b7cb4e20f0
commit
69823d1d19
BIN
cmd/hub/hub
Executable file
BIN
cmd/hub/hub
Executable file
Binary file not shown.
BIN
cmd/vppn/vppn
Executable file
BIN
cmd/vppn/vppn
Executable file
Binary file not shown.
1
peer/bufferset.go
Normal file
1
peer/bufferset.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package peer
|
1
peer/cipher.go
Normal file
1
peer/cipher.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package peer
|
@ -31,6 +31,7 @@ var multicastAddr = net.UDPAddrFromAddrPort(netip.AddrPortFrom(
|
|||||||
netip.AddrFrom4([4]byte{224, 0, 0, 157}),
|
netip.AddrFrom4([4]byte{224, 0, 0, 157}),
|
||||||
4560))
|
4560))
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Globals struct {
|
type Globals struct {
|
||||||
@ -105,5 +106,73 @@ func NewGlobals(
|
|||||||
g.RemotePeers[i].Store(newRemote(g, byte(i)))
|
g.RemotePeers[i].Store(newRemote(g, byte(i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return g
|
||||||
|
=======
|
||||||
|
type marshaller interface {
|
||||||
|
Marshal([]byte) []byte
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Globals struct {
|
||||||
|
LocalConfig // Embed, immutable.
|
||||||
|
|
||||||
|
// Local public address (if available). Immutable.
|
||||||
|
LocalAddr netip.AddrPort
|
||||||
|
|
||||||
|
// True if local public address is valid. Immutable.
|
||||||
|
LocalAddrValid bool
|
||||||
|
|
||||||
|
// All remote peers by VPN IP.
|
||||||
|
RemotePeers [256]*atomic.Pointer[Remote]
|
||||||
|
|
||||||
|
// Discovered public addresses.
|
||||||
|
PubAddrs *pubAddrStore
|
||||||
|
|
||||||
|
// Attempts to ensure that we have a relay available.
|
||||||
|
RelayHandler *relayHandler
|
||||||
|
|
||||||
|
// Send UDP - Global function to write UDP packets.
|
||||||
|
SendUDP func(b []byte, addr netip.AddrPort) (n int, err error)
|
||||||
|
|
||||||
|
// Global TUN interface.
|
||||||
|
IFace io.ReadWriteCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGlobals(
|
||||||
|
localConfig LocalConfig,
|
||||||
|
localAddr netip.AddrPort,
|
||||||
|
conn *net.UDPConn,
|
||||||
|
iface io.ReadWriteCloser,
|
||||||
|
) (g Globals) {
|
||||||
|
g.LocalConfig = localConfig
|
||||||
|
|
||||||
|
g.LocalAddr = localAddr
|
||||||
|
g.LocalAddrValid = localAddr.IsValid()
|
||||||
|
|
||||||
|
g.PubAddrs = newPubAddrStore(localAddr)
|
||||||
|
|
||||||
|
g.RelayHandler = newRelayHandler()
|
||||||
|
|
||||||
|
// Use a lock here avoids starvation, at least on my Linux machine.
|
||||||
|
sendLock := sync.Mutex{}
|
||||||
|
g.SendUDP = func(b []byte, addr netip.AddrPort) (int, error) {
|
||||||
|
sendLock.Lock()
|
||||||
|
n, err := conn.WriteToUDPAddrPort(b, addr)
|
||||||
|
sendLock.Unlock()
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.IFace = iface
|
||||||
|
|
||||||
|
for i := range g.RemotePeers {
|
||||||
|
g.RemotePeers[i] = &atomic.Pointer[Remote]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range g.RemotePeers {
|
||||||
|
g.RemotePeers[i].Store(newRemote(g, byte(i)))
|
||||||
|
}
|
||||||
|
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ func runMCReaderInner(g Globals) {
|
|||||||
logf("Failed to open discovery packet?")
|
logf("Failed to open discovery packet?")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
log.Printf("Got local discovery from %v: %v", remoteAddr, h)
|
||||||
|
|
||||||
g.RemotePeers[h.SourceIP].Load().HandleLocalDiscoveryPacket(h, remoteAddr, buf)
|
g.RemotePeers[h.SourceIP].Load().HandleLocalDiscoveryPacket(h, remoteAddr, buf)
|
||||||
}
|
}
|
||||||
|
11
peer/peer.go
11
peer/peer.go
@ -11,7 +11,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
<<<<<<< HEAD
|
||||||
"os"
|
"os"
|
||||||
|
=======
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
"vppn/m"
|
"vppn/m"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,6 +53,7 @@ func newPeerMain(args mainArgs) *peerMain {
|
|||||||
log.Fatalf("Failed to load network state: %v", err)
|
log.Fatalf("Failed to load network state: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
startupCount, err := loadStartupCount(args.NetName)
|
startupCount, err := loadStartupCount(args.NetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
@ -66,6 +70,8 @@ func newPeerMain(args mainArgs) *peerMain {
|
|||||||
log.Fatalf("Failed to write startup count: %v", err)
|
log.Fatalf("Failed to write startup count: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
iface, err := openInterface(config.Network, config.LocalPeerIP, args.NetName)
|
iface, err := openInterface(config.Network, config.LocalPeerIP, args.NetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to open interface: %v", err)
|
log.Fatalf("Failed to open interface: %v", err)
|
||||||
@ -73,6 +79,7 @@ func newPeerMain(args mainArgs) *peerMain {
|
|||||||
|
|
||||||
localPeer := state.Peers[config.LocalPeerIP]
|
localPeer := state.Peers[config.LocalPeerIP]
|
||||||
|
|
||||||
|
log.Printf("XXXXX %v %v", config.LocalPeerIP, localPeer)
|
||||||
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", localPeer.Port))
|
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", localPeer.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to resolve UDP address: %v", err)
|
log.Fatalf("Failed to resolve UDP address: %v", err)
|
||||||
@ -93,7 +100,11 @@ func newPeerMain(args mainArgs) *peerMain {
|
|||||||
localAddr = netip.AddrPortFrom(ip, localPeer.Port)
|
localAddr = netip.AddrPortFrom(ip, localPeer.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
g := NewGlobals(config, startupCount, localAddr, conn, iface)
|
g := NewGlobals(config, startupCount, localAddr, conn, iface)
|
||||||
|
=======
|
||||||
|
g := NewGlobals(config, localAddr, conn, iface)
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
|
|
||||||
hubPoller, err := NewHubPoller(g, args.NetName, args.HubAddress, args.APIKey)
|
hubPoller, err := NewHubPoller(g, args.NetName, args.HubAddress, args.APIKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
114
peer/peer_test.go
Normal file
114
peer/peer_test.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package peer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
mrand "math/rand"
|
||||||
|
"net/netip"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A test peer.
|
||||||
|
type P struct {
|
||||||
|
cryptoKeys
|
||||||
|
RT *atomic.Pointer[routingTable]
|
||||||
|
Conn *TestUDPConn
|
||||||
|
IFace *TestIFace
|
||||||
|
ConnReader *ConnReader
|
||||||
|
IFReader *IFReader
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPeerForTesting(n *TestNetwork, ip byte, addr netip.AddrPort) P {
|
||||||
|
p := P{
|
||||||
|
cryptoKeys: generateKeys(),
|
||||||
|
RT: &atomic.Pointer[routingTable]{},
|
||||||
|
IFace: NewTestIFace(),
|
||||||
|
}
|
||||||
|
|
||||||
|
rt := newRoutingTable(ip, addr)
|
||||||
|
p.RT.Store(&rt)
|
||||||
|
p.Conn = n.NewUDPConn(addr)
|
||||||
|
//p.ConnWriter = NewConnWriter(p.Conn.WriteToUDPAddrPort, p.RT)
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConnectPeers(p1, p2 *P) {
|
||||||
|
rt1 := p1.RT.Load()
|
||||||
|
rt2 := p2.RT.Load()
|
||||||
|
|
||||||
|
ip1 := rt1.LocalIP
|
||||||
|
ip2 := rt2.LocalIP
|
||||||
|
|
||||||
|
rt1.Peers[ip2].Up = true
|
||||||
|
rt1.Peers[ip2].Direct = true
|
||||||
|
rt1.Peers[ip2].Relay = true
|
||||||
|
rt1.Peers[ip2].DirectAddr = rt2.LocalAddr
|
||||||
|
rt1.Peers[ip2].PubSignKey = p2.PubSignKey
|
||||||
|
rt1.Peers[ip2].ControlCipher = newControlCipher(p1.PrivKey, p2.PubKey)
|
||||||
|
rt1.Peers[ip2].DataCipher = newDataCipher()
|
||||||
|
|
||||||
|
rt2.Peers[ip1].Up = true
|
||||||
|
rt2.Peers[ip1].Direct = true
|
||||||
|
rt2.Peers[ip1].Relay = true
|
||||||
|
rt2.Peers[ip1].DirectAddr = rt1.LocalAddr
|
||||||
|
rt2.Peers[ip1].PubSignKey = p1.PubSignKey
|
||||||
|
rt2.Peers[ip1].ControlCipher = newControlCipher(p2.PrivKey, p1.PubKey)
|
||||||
|
rt2.Peers[ip1].DataCipher = rt1.Peers[ip2].DataCipher
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPeersForTesting() (p1, p2, p3 P) {
|
||||||
|
n := NewTestNetwork()
|
||||||
|
|
||||||
|
p1 = NewPeerForTesting(
|
||||||
|
n,
|
||||||
|
1,
|
||||||
|
netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 1, 1, 1}), 100))
|
||||||
|
|
||||||
|
p2 = NewPeerForTesting(
|
||||||
|
n,
|
||||||
|
2,
|
||||||
|
netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 1, 1, 2}), 200))
|
||||||
|
|
||||||
|
p3 = NewPeerForTesting(
|
||||||
|
n,
|
||||||
|
3,
|
||||||
|
netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 1, 1, 3}), 300))
|
||||||
|
|
||||||
|
ConnectPeers(&p1, &p2)
|
||||||
|
ConnectPeers(&p1, &p3)
|
||||||
|
ConnectPeers(&p2, &p3)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandPacket() []byte {
|
||||||
|
n := mrand.Intn(1200)
|
||||||
|
b := make([]byte, n)
|
||||||
|
rand.Read(b)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func ModifyPacket(in []byte) []byte {
|
||||||
|
x := make([]byte, 1)
|
||||||
|
|
||||||
|
for {
|
||||||
|
rand.Read(x)
|
||||||
|
out := bytes.Clone(in)
|
||||||
|
idx := mrand.Intn(len(out))
|
||||||
|
if out[idx] != x[0] {
|
||||||
|
out[idx] = x[0]
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type UnknownControlPacket struct {
|
||||||
|
TraceID uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p UnknownControlPacket) Marshal(buf []byte) []byte {
|
||||||
|
return newBinWriter(buf).Byte(255).Uint64(p.TraceID).Build()
|
||||||
|
}
|
28
peer/peerfsm.dot
Normal file
28
peer/peerfsm.dot
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
digraph d {
|
||||||
|
disconnected -> peerUpdating;
|
||||||
|
peerUpdating -> disconnected;
|
||||||
|
peerUpdating -> server;
|
||||||
|
peerUpdating -> clientInit;
|
||||||
|
server -> peerUpdating;
|
||||||
|
clientInit -> peerUpdating;
|
||||||
|
clientInit -> clientInit;
|
||||||
|
clientInit -> client;
|
||||||
|
client -> clientInit;
|
||||||
|
client -> peerUpdating;
|
||||||
|
|
||||||
|
clientInitializing -> clientSyncing;
|
||||||
|
clientSyncing -> clientInitializing;
|
||||||
|
clientSyncing -> clientUpIndirect;
|
||||||
|
clientSyncing -> clientUpDirect;
|
||||||
|
clientUpIndirect -> clientUpDirect;
|
||||||
|
clientUpIndirect -> clientInitializing;
|
||||||
|
clientUpDirect -> clientInitializing;
|
||||||
|
|
||||||
|
serverInitializing -> serverSyncing;
|
||||||
|
serverSyncing -> serverInitializing;
|
||||||
|
serverSyncing -> serverUpIndirect;
|
||||||
|
serverSyncing -> serverUpDirect;
|
||||||
|
serverUpIndirect -> serverUpDirect;
|
||||||
|
serverUpIndirect -> serverInitializing;
|
||||||
|
serverUpDirect -> serverInitializing;
|
||||||
|
}
|
1
peer/peersuper.go
Normal file
1
peer/peersuper.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package peer
|
1
peer/relay.go
Normal file
1
peer/relay.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package peer
|
102
peer/remote.go
102
peer/remote.go
@ -6,7 +6,14 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
<<<<<<< HEAD
|
||||||
"vppn/m"
|
"vppn/m"
|
||||||
|
=======
|
||||||
|
"time"
|
||||||
|
"vppn/m"
|
||||||
|
|
||||||
|
"git.crumpington.com/lib/go/ratelimiter"
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -37,6 +44,10 @@ type Remote struct {
|
|||||||
Globals
|
Globals
|
||||||
RemotePeerIP byte // Immutable.
|
RemotePeerIP byte // Immutable.
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
limiter *ratelimiter.Limiter
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
dupCheck *dupCheck
|
dupCheck *dupCheck
|
||||||
sendCounter uint64 // init to startupCount << 48. Atomic access only.
|
sendCounter uint64 // init to startupCount << 48. Atomic access only.
|
||||||
|
|
||||||
@ -49,9 +60,19 @@ func newRemote(g Globals, remotePeerIP byte) *Remote {
|
|||||||
r := &Remote{
|
r := &Remote{
|
||||||
Globals: g,
|
Globals: g,
|
||||||
RemotePeerIP: remotePeerIP,
|
RemotePeerIP: remotePeerIP,
|
||||||
|
<<<<<<< HEAD
|
||||||
dupCheck: newDupCheck(0),
|
dupCheck: newDupCheck(0),
|
||||||
sendCounter: (uint64(g.StartupCount) << 48) + 1,
|
sendCounter: (uint64(g.StartupCount) << 48) + 1,
|
||||||
messages: make(chan any, 8),
|
messages: make(chan any, 8),
|
||||||
|
=======
|
||||||
|
limiter: ratelimiter.New(ratelimiter.Config{
|
||||||
|
FillPeriod: 20 * time.Millisecond,
|
||||||
|
MaxWaitCount: 1,
|
||||||
|
}),
|
||||||
|
dupCheck: newDupCheck(0),
|
||||||
|
sendCounter: uint64(time.Now().Unix()<<30) + 1,
|
||||||
|
messages: make(chan any, 8),
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
}
|
}
|
||||||
r.config.Store(&remoteConfig{})
|
r.config.Store(&remoteConfig{})
|
||||||
return r
|
return r
|
||||||
@ -79,19 +100,36 @@ func (r *Remote) updateConf(conf remoteConfig) {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
func (r *Remote) sendUDP(b []byte, addr netip.AddrPort) {
|
func (r *Remote) sendUDP(b []byte, addr netip.AddrPort) {
|
||||||
|
<<<<<<< HEAD
|
||||||
if _, err := r.SendUDP(b, addr); err != nil {
|
if _, err := r.SendUDP(b, addr); err != nil {
|
||||||
r.logf("Failed to send UDP packet: %v", err)
|
r.logf("Failed to send UDP packet: %v", err)
|
||||||
|
=======
|
||||||
|
if err := r.limiter.Limit(); err != nil {
|
||||||
|
r.logf("Rate limiter")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := r.SendUDP(b, addr); err != nil {
|
||||||
|
r.logf("Failed to send URP packet: %v", err)
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
func (r *Remote) encryptData(conf remoteConfig, destIP byte, packet []byte) []byte {
|
func (r *Remote) encryptData(conf remoteConfig, destIP byte, packet []byte) []byte {
|
||||||
|
=======
|
||||||
|
func (r *Remote) encryptData(conf remoteConfig, packet []byte) []byte {
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
h := Header{
|
h := Header{
|
||||||
StreamID: dataStreamID,
|
StreamID: dataStreamID,
|
||||||
Counter: atomic.AddUint64(&r.sendCounter, 1),
|
Counter: atomic.AddUint64(&r.sendCounter, 1),
|
||||||
SourceIP: r.Globals.LocalPeerIP,
|
SourceIP: r.Globals.LocalPeerIP,
|
||||||
|
<<<<<<< HEAD
|
||||||
DestIP: destIP,
|
DestIP: destIP,
|
||||||
|
=======
|
||||||
|
DestIP: r.RemotePeerIP,
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
}
|
}
|
||||||
return conf.DataCipher.Encrypt(h, packet, packet[len(packet):cap(packet)])
|
return conf.DataCipher.Encrypt(h, packet, packet[len(packet):cap(packet)])
|
||||||
}
|
}
|
||||||
@ -116,6 +154,7 @@ func (r *Remote) SendDataTo(data []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// Direct:
|
// Direct:
|
||||||
|
|
||||||
if conf.Direct {
|
if conf.Direct {
|
||||||
@ -124,6 +163,17 @@ func (r *Remote) SendDataTo(data []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Relayed:
|
// Relayed:
|
||||||
|
=======
|
||||||
|
if conf.Direct {
|
||||||
|
r.sendDataDirect(conf, data)
|
||||||
|
} else {
|
||||||
|
r.sendDataRelayed(conf, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendDataRelayed sends data to the remote via the relay.
|
||||||
|
func (r *Remote) sendDataRelayed(conf remoteConfig, data []byte) {
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
relay := r.RelayHandler.Load()
|
relay := r.RelayHandler.Load()
|
||||||
|
|
||||||
if relay == nil {
|
if relay == nil {
|
||||||
@ -131,15 +181,29 @@ func (r *Remote) SendDataTo(data []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
relay.relayData(conf.Peer.PeerIP, r.encryptData(conf, conf.Peer.PeerIP, data))
|
relay.relayData(conf.Peer.PeerIP, r.encryptData(conf, conf.Peer.PeerIP, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Remote) relayData(toIP byte, enc []byte) {
|
func (r *Remote) relayData(toIP byte, enc []byte) {
|
||||||
|
=======
|
||||||
|
relay.relayData(r.encryptData(conf, data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendDataDirect sends data to the remote directly.
|
||||||
|
func (r *Remote) sendDataDirect(conf remoteConfig, data []byte) {
|
||||||
|
r.logf("Sending data direct...")
|
||||||
|
r.sendUDP(r.encryptData(conf, data), conf.DirectAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Remote) relayData(enc []byte) {
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
conf := r.conf()
|
conf := r.conf()
|
||||||
if !conf.Up || !conf.Direct {
|
if !conf.Up || !conf.Direct {
|
||||||
r.logf("Cannot relay: not up or not a direct connection")
|
r.logf("Cannot relay: not up or not a direct connection")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
<<<<<<< HEAD
|
||||||
r.sendUDP(r.encryptData(conf, toIP, enc), conf.DirectAddr)
|
r.sendUDP(r.encryptData(conf, toIP, enc), conf.DirectAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +218,32 @@ func (r *Remote) sendControl(conf remoteConfig, data []byte) {
|
|||||||
|
|
||||||
// Relayed:
|
// Relayed:
|
||||||
|
|
||||||
|
=======
|
||||||
|
r.sendDataDirect(conf, enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Remote) sendControl(conf remoteConfig, data []byte) {
|
||||||
|
if conf.Direct {
|
||||||
|
r.sendControlDirect(conf, data)
|
||||||
|
} else {
|
||||||
|
r.sendControlRelayed(conf, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Remote) sendControlToAddr(buf []byte, addr netip.AddrPort) {
|
||||||
|
enc := r.encryptControl(r.conf(), buf)
|
||||||
|
r.sendUDP(enc, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Remote) sendControlDirect(conf remoteConfig, data []byte) {
|
||||||
|
r.logf("Sending control direct...")
|
||||||
|
enc := r.encryptControl(conf, data)
|
||||||
|
r.sendUDP(enc, conf.DirectAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Remote) sendControlRelayed(conf remoteConfig, data []byte) {
|
||||||
|
r.logf("Sending control relayed...")
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
relay := r.RelayHandler.Load()
|
relay := r.RelayHandler.Load()
|
||||||
|
|
||||||
if relay == nil {
|
if relay == nil {
|
||||||
@ -161,12 +251,16 @@ func (r *Remote) sendControl(conf remoteConfig, data []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
relay.relayData(conf.Peer.PeerIP, r.encryptControl(conf, data))
|
relay.relayData(conf.Peer.PeerIP, r.encryptControl(conf, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Remote) sendControlToAddr(buf []byte, addr netip.AddrPort) {
|
func (r *Remote) sendControlToAddr(buf []byte, addr netip.AddrPort) {
|
||||||
enc := r.encryptControl(r.conf(), buf)
|
enc := r.encryptControl(r.conf(), buf)
|
||||||
r.sendUDP(enc, addr)
|
r.sendUDP(enc, addr)
|
||||||
|
=======
|
||||||
|
relay.relayData(r.encryptControl(conf, data))
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Remote) forwardPacket(data []byte) {
|
func (r *Remote) forwardPacket(data []byte) {
|
||||||
@ -244,9 +338,13 @@ func (r *Remote) handleDataPacket(h Header, data []byte) {
|
|||||||
// For local.
|
// For local.
|
||||||
if h.DestIP == r.LocalPeerIP {
|
if h.DestIP == r.LocalPeerIP {
|
||||||
if _, err := r.IFace.Write(dec); err != nil {
|
if _, err := r.IFace.Write(dec); err != nil {
|
||||||
|
<<<<<<< HEAD
|
||||||
// This could be a malformed packet from a peer, so we don't crash if it
|
// This could be a malformed packet from a peer, so we don't crash if it
|
||||||
// happens.
|
// happens.
|
||||||
r.logf("Failed to write to interface: %v", err)
|
r.logf("Failed to write to interface: %v", err)
|
||||||
|
=======
|
||||||
|
log.Fatalf("Failed to write to interface: %v", err)
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -275,6 +373,10 @@ func (r *Remote) HandleLocalDiscoveryPacket(h Header, srcAddr netip.AddrPort, da
|
|||||||
SrcIP: h.SourceIP,
|
SrcIP: h.SourceIP,
|
||||||
SrcAddr: srcAddr,
|
SrcAddr: srcAddr,
|
||||||
}
|
}
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
r.logf("Got local discovery packet from %v.", srcAddr)
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case r.messages <- msg:
|
case r.messages <- msg:
|
||||||
|
@ -9,11 +9,14 @@ import (
|
|||||||
|
|
||||||
type stateFunc func(msg any) stateFunc
|
type stateFunc func(msg any) stateFunc
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
type sentProbe struct {
|
type sentProbe struct {
|
||||||
SentAt time.Time
|
SentAt time.Time
|
||||||
Addr netip.AddrPort
|
Addr netip.AddrPort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
type remoteFSM struct {
|
type remoteFSM struct {
|
||||||
*Remote
|
*Remote
|
||||||
|
|
||||||
@ -161,13 +164,23 @@ func (r *remoteFSM) stateServer_onInit(msg controlMsg[packetInit]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteFSM) stateServer_onSyn(msg controlMsg[packetSyn]) {
|
func (r *remoteFSM) stateServer_onSyn(msg controlMsg[packetSyn]) {
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
r.logf("Got SYN: %v", msg.Packet)
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
r.lastSeen = time.Now()
|
r.lastSeen = time.Now()
|
||||||
p := msg.Packet
|
p := msg.Packet
|
||||||
|
|
||||||
// Before we can respond to this packet, we need to make sure the
|
// Before we can respond to this packet, we need to make sure the
|
||||||
// route is setup properly.
|
// route is setup properly.
|
||||||
conf := r.conf()
|
conf := r.conf()
|
||||||
|
<<<<<<< HEAD
|
||||||
logSyn := !conf.Up || conf.Direct != p.Direct
|
logSyn := !conf.Up || conf.Direct != p.Direct
|
||||||
|
=======
|
||||||
|
if !conf.Up || conf.Direct != p.Direct {
|
||||||
|
r.logf("Got SYN.")
|
||||||
|
}
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
|
|
||||||
conf.Up = true
|
conf.Up = true
|
||||||
conf.Direct = p.Direct
|
conf.Direct = p.Direct
|
||||||
@ -181,10 +194,13 @@ func (r *remoteFSM) stateServer_onSyn(msg controlMsg[packetSyn]) {
|
|||||||
|
|
||||||
r.updateConf(conf)
|
r.updateConf(conf)
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
if logSyn {
|
if logSyn {
|
||||||
r.logf("Got SYN.")
|
r.logf("Got SYN.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
r.sendControl(conf, packetAck{
|
r.sendControl(conf, packetAck{
|
||||||
TraceID: p.TraceID,
|
TraceID: p.TraceID,
|
||||||
ToAddr: conf.DirectAddr,
|
ToAddr: conf.DirectAddr,
|
||||||
@ -201,7 +217,11 @@ func (r *remoteFSM) stateServer_onSyn(msg controlMsg[packetSyn]) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
r.logf("Probing %v...", addr)
|
r.logf("Probing %v...", addr)
|
||||||
|
<<<<<<< HEAD
|
||||||
r.sendControlToAddr(packetProbe{TraceID: r.NewTraceID()}.Marshal(r.buf), addr)
|
r.sendControlToAddr(packetProbe{TraceID: r.NewTraceID()}.Marshal(r.buf), addr)
|
||||||
|
=======
|
||||||
|
r.sendControlToAddr(packetProbe{TraceID: newTraceID()}.Marshal(r.buf), addr)
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +289,11 @@ func (r *remoteFSM) stateClientInit(iMsg any) stateFunc {
|
|||||||
|
|
||||||
func (r *remoteFSM) stateClientInit_sendInit() {
|
func (r *remoteFSM) stateClientInit_sendInit() {
|
||||||
conf := r.conf()
|
conf := r.conf()
|
||||||
|
<<<<<<< HEAD
|
||||||
r.traceID = r.NewTraceID()
|
r.traceID = r.NewTraceID()
|
||||||
|
=======
|
||||||
|
r.traceID = newTraceID()
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
init := packetInit{
|
init := packetInit{
|
||||||
TraceID: r.traceID,
|
TraceID: r.traceID,
|
||||||
Direct: conf.Direct,
|
Direct: conf.Direct,
|
||||||
@ -316,7 +340,11 @@ func (r *remoteFSM) enterClient() stateFunc {
|
|||||||
conf := r.conf()
|
conf := r.conf()
|
||||||
r.probes = make(map[uint64]sentProbe, 8)
|
r.probes = make(map[uint64]sentProbe, 8)
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
r.traceID = r.NewTraceID()
|
r.traceID = r.NewTraceID()
|
||||||
|
=======
|
||||||
|
r.traceID = newTraceID()
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
r.stateClient_sendSyn(conf)
|
r.stateClient_sendSyn(conf)
|
||||||
|
|
||||||
r.pingTimer.Reset(pingInterval)
|
r.pingTimer.Reset(pingInterval)
|
||||||
@ -382,7 +410,11 @@ func (r *remoteFSM) stateClient_cleanProbes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteFSM) stateClient_sendProbeTo(addr netip.AddrPort) {
|
func (r *remoteFSM) stateClient_sendProbeTo(addr netip.AddrPort) {
|
||||||
|
<<<<<<< HEAD
|
||||||
probe := packetProbe{TraceID: r.NewTraceID()}
|
probe := packetProbe{TraceID: r.NewTraceID()}
|
||||||
|
=======
|
||||||
|
probe := packetProbe{TraceID: newTraceID()}
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
r.probes[probe.TraceID] = sentProbe{
|
r.probes[probe.TraceID] = sentProbe{
|
||||||
SentAt: time.Now(),
|
SentAt: time.Now(),
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
@ -408,7 +440,11 @@ func (r *remoteFSM) stateClient_onProbe(msg controlMsg[packetProbe]) {
|
|||||||
conf.DirectAddr = sent.Addr
|
conf.DirectAddr = sent.Addr
|
||||||
r.updateConf(conf)
|
r.updateConf(conf)
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
r.traceID = r.NewTraceID()
|
r.traceID = r.NewTraceID()
|
||||||
|
=======
|
||||||
|
r.traceID = newTraceID()
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
r.stateClient_sendSyn(conf)
|
r.stateClient_sendSyn(conf)
|
||||||
r.logf("Successful probe to %v.", sent.Addr)
|
r.logf("Successful probe to %v.", sent.Addr)
|
||||||
}
|
}
|
||||||
@ -435,6 +471,10 @@ func (r *remoteFSM) stateClient_onPingTimer() stateFunc {
|
|||||||
return r.enterClientInit()
|
return r.enterClientInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
r.traceID = newTraceID()
|
||||||
|
>>>>>>> 69f2536 (WIP)
|
||||||
r.stateClient_sendSyn(conf)
|
r.stateClient_sendSyn(conf)
|
||||||
return r.stateClient
|
return r.stateClient
|
||||||
}
|
}
|
||||||
|
1
peer/remotestate-disconnected.go
Normal file
1
peer/remotestate-disconnected.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package peer
|
138
peer/routingtable.go
Normal file
138
peer/routingtable.go
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package peer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: Remove
|
||||||
|
func newRemotePeer(ip byte) *remotePeer {
|
||||||
|
counter := uint64(time.Now().Unix()<<30 + 1)
|
||||||
|
return &remotePeer{
|
||||||
|
IP: ip,
|
||||||
|
counter: &counter,
|
||||||
|
dupCheck: newDupCheck(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type remotePeer struct {
|
||||||
|
localIP byte
|
||||||
|
IP byte // VPN IP of peer (last byte).
|
||||||
|
Up bool // True if data can be sent on the peer.
|
||||||
|
Relay bool // True if the peer is a relay.
|
||||||
|
Direct bool // True if this is a direct connection.
|
||||||
|
DirectAddr netip.AddrPort // Remote address if directly connected.
|
||||||
|
PubSignKey []byte
|
||||||
|
ControlCipher *controlCipher
|
||||||
|
DataCipher *dataCipher
|
||||||
|
|
||||||
|
counter *uint64 // For sending to. Atomic access only.
|
||||||
|
dupCheck *dupCheck // For receiving from. Not safe for concurrent use.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p remotePeer) EncryptDataPacket(destIP byte, data, out []byte) []byte {
|
||||||
|
h := Header{
|
||||||
|
StreamID: dataStreamID,
|
||||||
|
Counter: atomic.AddUint64(p.counter, 1),
|
||||||
|
SourceIP: p.localIP,
|
||||||
|
DestIP: destIP,
|
||||||
|
}
|
||||||
|
return p.DataCipher.Encrypt(h, data, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypts and de-dups incoming data packets.
|
||||||
|
func (p remotePeer) DecryptDataPacket(h Header, enc, out []byte) ([]byte, error) {
|
||||||
|
dec, ok := p.DataCipher.Decrypt(enc, out)
|
||||||
|
if !ok {
|
||||||
|
return nil, errDecryptionFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.dupCheck.IsDup(h.Counter) {
|
||||||
|
return nil, errDuplicateSeqNum
|
||||||
|
}
|
||||||
|
|
||||||
|
return dec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peer must have a ControlCipher.
|
||||||
|
func (p remotePeer) EncryptControlPacket(pkt marshaller, tmp, out []byte) []byte {
|
||||||
|
tmp = pkt.Marshal(tmp)
|
||||||
|
h := Header{
|
||||||
|
StreamID: controlStreamID,
|
||||||
|
Counter: atomic.AddUint64(p.counter, 1),
|
||||||
|
SourceIP: p.localIP,
|
||||||
|
DestIP: p.IP,
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.ControlCipher.Encrypt(h, tmp, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a controlMsg[PacketType]. Peer must have a non-nil ControlCipher.
|
||||||
|
//
|
||||||
|
// This function also drops packets with duplicate sequence numbers.
|
||||||
|
func (p remotePeer) DecryptControlPacket(fromAddr netip.AddrPort, h Header, enc, tmp []byte) (any, error) {
|
||||||
|
out, ok := p.ControlCipher.Decrypt(enc, tmp)
|
||||||
|
if !ok {
|
||||||
|
return nil, errDecryptionFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.dupCheck.IsDup(h.Counter) {
|
||||||
|
return nil, errDuplicateSeqNum
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := parseControlMsg(h.SourceIP, fromAddr, out)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type routingTable struct {
|
||||||
|
// The LocalIP is the configured IP address of the local peer on the VPN.
|
||||||
|
//
|
||||||
|
// This value is constant.
|
||||||
|
LocalIP byte
|
||||||
|
|
||||||
|
// The LocalAddr is the configured local public address of the peer on the
|
||||||
|
// internet. If LocalAddr.IsValid(), then the local peer has a public
|
||||||
|
// address.
|
||||||
|
//
|
||||||
|
// This value is constant.
|
||||||
|
LocalAddr netip.AddrPort
|
||||||
|
|
||||||
|
// The remote peer configurations. These are updated by
|
||||||
|
Peers [256]remotePeer
|
||||||
|
|
||||||
|
// The current relay's VPN IP address, or zero if no relay is available.
|
||||||
|
RelayIP byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRoutingTable(localIP byte, localAddr netip.AddrPort) routingTable {
|
||||||
|
rt := routingTable{
|
||||||
|
LocalIP: localIP,
|
||||||
|
LocalAddr: localAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range rt.Peers {
|
||||||
|
counter := uint64(time.Now().Unix()<<30 + 1)
|
||||||
|
rt.Peers[i] = remotePeer{
|
||||||
|
localIP: localIP,
|
||||||
|
IP: byte(i),
|
||||||
|
counter: &counter,
|
||||||
|
dupCheck: newDupCheck(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rt *routingTable) GetRelay() (remotePeer, bool) {
|
||||||
|
relay := rt.Peers[rt.RelayIP]
|
||||||
|
return relay, relay.Up && relay.Direct
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user