WIP
This commit is contained in:
@@ -8,11 +8,13 @@ import (
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/nacl/sign"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
const (
|
||||
mcBeaconLen = 35 // 1 VPN IP byte + 32 WG pubkey + 2 WG listen port
|
||||
mcBeaconLen = 35 // 1 VPN IP byte + 32 WG pubkey + 2 WG listen port
|
||||
mcSignedBeaconLen = sign.Overhead + mcBeaconLen // 64-byte nacl/sign prefix + payload
|
||||
mcBroadcastInterval = 32 * time.Second
|
||||
mcErrorRetryInterval = 16 * time.Second
|
||||
)
|
||||
@@ -21,18 +23,23 @@ var mcAddr = net.UDPAddrFromAddrPort(netip.AddrPortFrom(
|
||||
netip.AddrFrom4([4]byte{224, 0, 0, 157}),
|
||||
4560))
|
||||
|
||||
// RunMCWriter broadcasts a beacon on the local multicast group every
|
||||
// RunMCWriter broadcasts a signed beacon on the local multicast group every
|
||||
// mcBroadcastInterval so that LAN peers can discover our WireGuard endpoint.
|
||||
func RunMCWriter(selfVPNIP netip.Addr, pubKey wgtypes.Key, wgPort uint16) {
|
||||
func RunMCWriter(selfVPNIP netip.Addr, pubKey wgtypes.Key, wgPort uint16, signKey *[64]byte) {
|
||||
conn, err := net.ListenMulticastUDP("udp", nil, mcAddr)
|
||||
if err != nil {
|
||||
log.Fatalf("[MCWriter] bind: %v", err)
|
||||
log.Printf("[MCWriter] bind: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
beacon := buildBeacon(selfVPNIP, pubKey, wgPort)
|
||||
payload := buildBeacon(selfVPNIP, pubKey, wgPort)
|
||||
signed := sign.Sign(nil, payload, signKey)
|
||||
|
||||
if _, err := conn.WriteToUDP(signed, mcAddr); err != nil {
|
||||
log.Printf("[MCWriter] write: %v", err)
|
||||
}
|
||||
for range time.Tick(mcBroadcastInterval) {
|
||||
if _, err := conn.WriteToUDP(beacon, mcAddr); err != nil {
|
||||
if _, err := conn.WriteToUDP(signed, mcAddr); err != nil {
|
||||
log.Printf("[MCWriter] write: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -64,7 +71,7 @@ func runMCReaderInner(vpnNet netip.Prefix, selfVPNIP netip.Addr, ch chan<- Multi
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
buf := make([]byte, 64)
|
||||
buf := make([]byte, mcSignedBeaconLen+1) // +1 to detect oversized packets
|
||||
netAddr := vpnNet.Addr().As4()
|
||||
|
||||
for {
|
||||
@@ -73,29 +80,25 @@ func runMCReaderInner(vpnNet netip.Prefix, selfVPNIP netip.Addr, ch chan<- Multi
|
||||
if err != nil {
|
||||
return fmt.Errorf("read: %w", err)
|
||||
}
|
||||
if n != mcBeaconLen {
|
||||
if n != mcSignedBeaconLen {
|
||||
continue
|
||||
}
|
||||
|
||||
// Peek at VPN IP byte (first byte of payload after 64-byte sig prefix)
|
||||
// to skip our own beacon before verifying.
|
||||
octets := netAddr
|
||||
octets[3] = buf[0]
|
||||
octets[3] = buf[sign.Overhead]
|
||||
vpnIP := netip.AddrFrom4(octets)
|
||||
if vpnIP == selfVPNIP {
|
||||
continue
|
||||
}
|
||||
|
||||
pubKey, err := wgtypes.NewKey(buf[1:33])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
wgPort := binary.BigEndian.Uint16(buf[33:35])
|
||||
endpoint := netip.AddrPortFrom(src.Addr().Unmap(), wgPort)
|
||||
signed := make([]byte, mcSignedBeaconLen)
|
||||
copy(signed, buf[:mcSignedBeaconLen])
|
||||
|
||||
ch <- MulticastEvent{
|
||||
pubKey: pubKey,
|
||||
vpnIP: vpnIP,
|
||||
endpoint: endpoint,
|
||||
signed: signed,
|
||||
src: src.Addr().Unmap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user