52 lines
1.1 KiB
Go
52 lines
1.1 KiB
Go
package peer
|
|
|
|
import (
|
|
"net/netip"
|
|
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
|
|
"vppn/peer/multicast"
|
|
)
|
|
|
|
func (a *App) onMulticastDiscovery(pkt multicast.Packet) {
|
|
if a.isPublic {
|
|
return
|
|
}
|
|
|
|
// Locate the sender peer by its VPN IP (final octet carried in the beacon).
|
|
octets := a.vpnNet.Addr().As4()
|
|
octets[3] = pkt.PeerIP
|
|
vpnIP := netip.AddrFrom4(octets)
|
|
|
|
peer, ok := a.peersByIP[vpnIP]
|
|
if !ok || peer.IsPublic || peer.State == StateDirect {
|
|
return
|
|
}
|
|
|
|
// Authenticate the beacon against the peer's known sign key. scratch[:0]
|
|
// gives sign.Open an empty-but-capacity buffer to decode into.
|
|
if !pkt.Verify(a.scratch[:0], &peer.SignPubKey) {
|
|
return
|
|
}
|
|
|
|
// The beacon is authentic but must also advertise the WG key the hub gave
|
|
// us for this peer; otherwise it's inconsistent — drop it.
|
|
if wgtypes.Key(pkt.WGPubKey) != peer.PubKey() {
|
|
return
|
|
}
|
|
|
|
endpoint := netip.AddrPortFrom(pkt.Src, pkt.WGPort)
|
|
if !endpoint.IsValid() {
|
|
return
|
|
}
|
|
|
|
var v4, v6 netip.AddrPort
|
|
if pkt.Src.Is4() {
|
|
v4 = endpoint
|
|
} else {
|
|
v6 = endpoint
|
|
}
|
|
|
|
a.addProbe(peer, v4, v6)
|
|
}
|