Go backend that drives kernel WireGuard over netlink (wireguard-go as the fallback), nftables NAT with MSS clamping, forwarding and buffer sysctls, SQLite for peers, users, sessions, traffic history and the audit log. React console: dashboard with live rates and usage history, peer management with QR codes and .conf downloads, disconnect, session reset, key rotation, expiry, client-supplied keys, settings, users with admin and viewer roles, two-factor authentication with recovery codes, audit log. Docker image on Alpine with compose files for bridged and host networking, CI and GHCR publish workflows, performance notes.
57 lines
1.7 KiB
Go
57 lines
1.7 KiB
Go
package engine
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/netip"
|
|
)
|
|
|
|
// allocate returns the lowest free host address in the subnet, skipping the
|
|
// network address, the server's own (first host) and, for IPv4, the
|
|
// broadcast address. `used` holds addresses already handed out.
|
|
func allocate(subnet netip.Prefix, used map[string]bool) (netip.Addr, error) {
|
|
subnet = subnet.Masked()
|
|
base := subnet.Addr()
|
|
server := base.Next()
|
|
var last netip.Addr
|
|
if base.Is4() {
|
|
// Broadcast: all host bits set.
|
|
a := base.As4()
|
|
hostBits := 32 - subnet.Bits()
|
|
var n uint32 = uint32(a[0])<<24 | uint32(a[1])<<16 | uint32(a[2])<<8 | uint32(a[3])
|
|
n |= (1 << hostBits) - 1
|
|
last = netip.AddrFrom4([4]byte{byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n)})
|
|
}
|
|
// Cap the scan: a /64 is not walked to the end, and nobody has 65k peers.
|
|
const maxScan = 65536
|
|
addr := server.Next()
|
|
for i := 0; i < maxScan && subnet.Contains(addr); i++ {
|
|
if base.Is4() && addr == last {
|
|
break
|
|
}
|
|
if !used[addr.String()] {
|
|
return addr, nil
|
|
}
|
|
addr = addr.Next()
|
|
}
|
|
return netip.Addr{}, errors.New("no free addresses left in " + subnet.String())
|
|
}
|
|
|
|
// checkAddress validates an operator-chosen address for a peer.
|
|
func checkAddress(subnet netip.Prefix, s string, used map[string]bool) (netip.Addr, error) {
|
|
a, err := netip.ParseAddr(s)
|
|
if err != nil {
|
|
return netip.Addr{}, fmt.Errorf("%q is not an IP address", s)
|
|
}
|
|
if !subnet.Contains(a) {
|
|
return netip.Addr{}, fmt.Errorf("%s is outside %s", a, subnet.Masked())
|
|
}
|
|
if a == subnet.Masked().Addr() || a == subnet.Masked().Addr().Next() {
|
|
return netip.Addr{}, fmt.Errorf("%s is reserved for the server", a)
|
|
}
|
|
if used[a.String()] {
|
|
return netip.Addr{}, fmt.Errorf("%s is already assigned", a)
|
|
}
|
|
return a, nil
|
|
}
|