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.
61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
package wg
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"golang.org/x/crypto/curve25519"
|
|
)
|
|
|
|
// GeneratePrivateKey returns a fresh Curve25519 private key, clamped the way
|
|
// WireGuard expects.
|
|
func GeneratePrivateKey() (Key, error) {
|
|
var k Key
|
|
if _, err := rand.Read(k[:]); err != nil {
|
|
return Key{}, fmt.Errorf("generate private key: %w", err)
|
|
}
|
|
k[0] &= 248
|
|
k[31] &= 127
|
|
k[31] |= 64
|
|
return k, nil
|
|
}
|
|
|
|
// GeneratePresharedKey returns 32 random bytes for use as a preshared key.
|
|
func GeneratePresharedKey() (Key, error) {
|
|
var k Key
|
|
if _, err := rand.Read(k[:]); err != nil {
|
|
return Key{}, fmt.Errorf("generate preshared key: %w", err)
|
|
}
|
|
return k, nil
|
|
}
|
|
|
|
// PublicKey derives the public key of a private key.
|
|
func (k Key) PublicKey() Key {
|
|
var pub Key
|
|
priv := k
|
|
curve25519.ScalarBaseMult((*[32]byte)(&pub), (*[32]byte)(&priv))
|
|
return pub
|
|
}
|
|
|
|
// String renders the key the way wg(8) does: standard base64.
|
|
func (k Key) String() string { return base64.StdEncoding.EncodeToString(k[:]) }
|
|
|
|
// IsZero reports whether the key is all zeros.
|
|
func (k Key) IsZero() bool { return k == Key{} }
|
|
|
|
// ParseKey parses a base64 key as produced by wg genkey / wg pubkey.
|
|
func ParseKey(s string) (Key, error) {
|
|
b, err := base64.StdEncoding.DecodeString(s)
|
|
if err != nil {
|
|
return Key{}, errors.New("key is not valid base64")
|
|
}
|
|
if len(b) != 32 {
|
|
return Key{}, errors.New("key must decode to 32 bytes")
|
|
}
|
|
var k Key
|
|
copy(k[:], b)
|
|
return k, nil
|
|
}
|