This commit is contained in:
jdl 2025-08-26 15:33:27 +02:00
parent b7cb4e20f0
commit 69823d1d19
15 changed files with 508 additions and 0 deletions

BIN
cmd/hub/hub Executable file

Binary file not shown.

BIN
cmd/vppn/vppn Executable file

Binary file not shown.

1
peer/bufferset.go Normal file
View File

@ -0,0 +1 @@
package peer

1
peer/cipher.go Normal file
View File

@ -0,0 +1 @@
package peer

View File

@ -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
} }

View File

@ -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)
} }

View File

@ -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
View 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
View 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
View File

@ -0,0 +1 @@
package peer

1
peer/relay.go Normal file
View File

@ -0,0 +1 @@
package peer

View File

@ -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:

View File

@ -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
} }

View File

@ -0,0 +1 @@
package peer

138
peer/routingtable.go Normal file
View 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
}