Refactor - now wireguard based. (#7)

This commit is contained in:
2026-06-12 15:11:01 +00:00
parent 5ae075647d
commit 9a3cb2d1c2
105 changed files with 3776 additions and 4251 deletions

View File

@@ -1,28 +1,133 @@
// The package `m` contains models shared between the hub and peer programs.
package m
import (
"encoding/base64"
"encoding/json"
"fmt"
"net/netip"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
type PeerInitArgs struct {
EncPubKey []byte
PubSignKey []byte
WGPubKey []byte
SignPubKey []byte
}
type PeerInitResp struct {
PeerIP byte
Network []byte
LocalDomain string
NetworkState NetworkState
}
// Peer is the network membership record for a single peer, exchanged between
// the hub and peers. Addr4/Addr6 are the peer's public endpoint addresses (zero
// if it has none); Port is its WireGuard listen port, meaningful even for a
// non-public peer (it is the peer's own bind/beacon port).
type Peer struct {
PeerIP byte
Version int64
Name string
PublicIP []byte
Addr4 netip.Addr // zero if none
Addr6 netip.Addr // zero if none
Port uint16
Relay bool
PubKey []byte
PubSignKey []byte
WGPubKey wgtypes.Key
SignPubKey [32]byte
}
// IsPublic reports whether the peer advertises at least one reachable endpoint.
func (p Peer) IsPublic() bool {
return p.Addr4.IsValid() || p.Addr6.IsValid()
}
// Endpoint4 returns the IPv4 endpoint (addr+port), or the zero AddrPort if the
// peer has no IPv4 address.
func (p Peer) Endpoint4() netip.AddrPort {
if !p.Addr4.IsValid() {
return netip.AddrPort{}
}
return netip.AddrPortFrom(p.Addr4, p.Port)
}
// Endpoint6 returns the IPv6 endpoint (addr+port), or the zero AddrPort if the
// peer has no IPv6 address.
func (p Peer) Endpoint6() netip.AddrPort {
if !p.Addr6.IsValid() {
return netip.AddrPort{}
}
return netip.AddrPortFrom(p.Addr6, p.Port)
}
// PreferredEndpoint returns the IPv4 endpoint if present, else IPv6.
func (p Peer) PreferredEndpoint() netip.AddrPort {
if ep := p.Endpoint4(); ep.IsValid() {
return ep
}
return p.Endpoint6()
}
// peerJSON is the wire representation. netip.Addr fields round-trip as text
// strings automatically; only the fixed-size key arrays need base64 (otherwise
// encoding/json would emit them as arrays of numbers).
type peerJSON struct {
PeerIP byte
Name string
Addr4 netip.Addr
Addr6 netip.Addr
Port uint16
Relay bool
WGPubKey string
SignPubKey string
}
func (p Peer) MarshalJSON() ([]byte, error) {
return json.Marshal(peerJSON{
PeerIP: p.PeerIP,
Name: p.Name,
Addr4: p.Addr4,
Addr6: p.Addr6,
Port: p.Port,
Relay: p.Relay,
WGPubKey: base64.StdEncoding.EncodeToString(p.WGPubKey[:]),
SignPubKey: base64.StdEncoding.EncodeToString(p.SignPubKey[:]),
})
}
func (p *Peer) UnmarshalJSON(data []byte) error {
var j peerJSON
if err := json.Unmarshal(data, &j); err != nil {
return err
}
wg, err := base64.StdEncoding.DecodeString(j.WGPubKey)
if err != nil {
return fmt.Errorf("decode WGPubKey: %w", err)
}
key, err := wgtypes.NewKey(wg)
if err != nil {
return fmt.Errorf("invalid WGPubKey: %w", err)
}
sign, err := base64.StdEncoding.DecodeString(j.SignPubKey)
if err != nil {
return fmt.Errorf("decode SignPubKey: %w", err)
}
if len(sign) != 32 {
return fmt.Errorf("invalid SignPubKey length: %d", len(sign))
}
*p = Peer{
PeerIP: j.PeerIP,
Name: j.Name,
Addr4: j.Addr4,
Addr6: j.Addr6,
Port: j.Port,
Relay: j.Relay,
WGPubKey: key,
SignPubKey: [32]byte(sign),
}
return nil
}
type NetworkState struct {
Peers [256]*Peer
Peers []Peer
}