WIP
This commit is contained in:
		
							
								
								
									
										
											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 | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user