Refactor - now wireguard based. (#7)
This commit is contained in:
114
peer/on_hub.go
Normal file
114
peer/on_hub.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package peer
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"vppn/m"
|
||||
"vppn/peer/control"
|
||||
)
|
||||
|
||||
func (a *App) onAddPeer(p m.Peer) {
|
||||
a.onRemovePeer(p.WGPubKey)
|
||||
|
||||
octets := a.vpnNet.Addr().As4()
|
||||
octets[3] = p.PeerIP
|
||||
vpnIP := netip.AddrFrom4(octets)
|
||||
|
||||
peer := &Peer{
|
||||
wgPeer: wgtypes.Peer{PublicKey: p.WGPubKey},
|
||||
VPNIP: vpnIP,
|
||||
Name: p.Name,
|
||||
IsRelay: p.Relay,
|
||||
IsPublic: p.IsPublic(),
|
||||
EndpointV4: p.Endpoint4(),
|
||||
EndpointV6: p.Endpoint6(),
|
||||
RTT: time.Duration(math.MaxInt64) * time.Nanosecond,
|
||||
Role: roleFor(a.isPublic, a.vpnIP, p.IsPublic(), vpnIP),
|
||||
SignPubKey: p.SignPubKey,
|
||||
}
|
||||
|
||||
a.peersByKey[p.WGPubKey] = peer
|
||||
a.peersByIP[peer.VPNIP] = peer
|
||||
defer a.updateHosts()
|
||||
|
||||
if !peer.IsPublic {
|
||||
if a.isPublic {
|
||||
// Public nodes accept traffic from non-public peers as soon as they
|
||||
// initiate a handshake. Set /32 AllowedIPs now; WireGuard learns the
|
||||
// endpoint from the incoming handshake automatically.
|
||||
a.devPromote(peer)
|
||||
} else {
|
||||
a.devAddPeer(peer)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
a.devAddDirect(peer, peer.PreferredEndpoint())
|
||||
}
|
||||
|
||||
func (a *App) onRemovePeer(key wgtypes.Key) {
|
||||
peer, exists := a.peersByKey[key]
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
a.devRemove(peer)
|
||||
delete(a.peersByKey, key)
|
||||
delete(a.peersByIP, peer.VPNIP)
|
||||
a.updateHosts()
|
||||
|
||||
if peer == a.relay {
|
||||
a.relay = nil
|
||||
a.switchActiveRelay()
|
||||
}
|
||||
}
|
||||
|
||||
// switchActiveRelay promotes the lowest-latency relay peer to active.
|
||||
func (a *App) switchActiveRelay() {
|
||||
if a.relay != nil {
|
||||
// If we have a relay, it's public, so should go back to being a direct
|
||||
// peer - this will convert it's /24 to a /32.
|
||||
a.devAddDirect(a.relay, a.relay.PreferredEndpoint())
|
||||
a.relay = nil
|
||||
}
|
||||
|
||||
var best *Peer
|
||||
for _, p := range a.peersByKey {
|
||||
if !p.CanRelay() {
|
||||
continue
|
||||
}
|
||||
|
||||
if best == nil || p.RTT < best.RTT {
|
||||
best = p
|
||||
}
|
||||
}
|
||||
if best == nil {
|
||||
log.Printf("no relay available")
|
||||
return
|
||||
}
|
||||
|
||||
a.devSetRelay(best, best.PreferredEndpoint())
|
||||
a.relay = best
|
||||
}
|
||||
|
||||
func preferredEndpoint(v4, v6 netip.AddrPort) netip.AddrPort {
|
||||
// We always prefer v4 since all peers can connect to IPv4 addresses.
|
||||
if v4.IsValid() {
|
||||
return v4
|
||||
}
|
||||
return v6
|
||||
}
|
||||
|
||||
func roleFor(selfIsPublic bool, selfIP netip.Addr, peerIsPublic bool, peerVPNIP netip.Addr) control.Role {
|
||||
if !selfIsPublic && peerIsPublic {
|
||||
return control.Client
|
||||
}
|
||||
if selfIsPublic && !peerIsPublic {
|
||||
return control.Server
|
||||
}
|
||||
return control.RoleFor(selfIP, peerVPNIP)
|
||||
}
|
||||
Reference in New Issue
Block a user