This commit is contained in:
jdl
2026-06-07 20:30:31 +02:00
parent 747d73890f
commit 3877ec5f35
15 changed files with 173 additions and 80 deletions

View File

@@ -2,6 +2,7 @@ package peer
import (
"bytes"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
@@ -10,6 +11,7 @@ import (
"os"
"path/filepath"
"golang.org/x/crypto/nacl/sign"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"vppn/m"
@@ -19,6 +21,7 @@ import (
// loaded on every subsequent run.
type LocalState struct {
PrivKey wgtypes.Key
SignKey [64]byte // nacl/sign Ed25519 private key
VPNIP netip.Addr
VPNNet netip.Prefix
WGPort uint16
@@ -28,7 +31,8 @@ type LocalState struct {
// localStateJSON is the on-disk representation.
type localStateJSON struct {
PrivKey string `json:"priv_key"` // standard base64
PrivKey string `json:"priv_key"` // standard base64
SignKey string `json:"sign_key"` // standard base64
VPNIP netip.Addr `json:"vpn_ip"`
VPNNet netip.Prefix `json:"vpn_net"`
WGPort uint16 `json:"wg_port"`
@@ -60,8 +64,17 @@ func LoadOrInit(statePath, hubURL, apiKey string) (LocalState, error) {
}
func initFromHub(hubURL, apiKey string, privKey wgtypes.Key) (LocalState, error) {
pubKey := privKey.PublicKey()
body, _ := json.Marshal(m.PeerInitArgs{WGPubKey: pubKey[:]})
wgPubKey := privKey.PublicKey()
signPubKey, signPrivKey, err := sign.GenerateKey(rand.Reader)
if err != nil {
return LocalState{}, fmt.Errorf("generate sign key: %w", err)
}
body, _ := json.Marshal(m.PeerInitArgs{
WGPubKey: wgPubKey[:],
SignPubKey: signPubKey[:],
})
req, err := http.NewRequest(http.MethodPost, hubURL+"/peer/init/", bytes.NewReader(body))
if err != nil {
@@ -105,6 +118,7 @@ func initFromHub(hubURL, apiKey string, privKey wgtypes.Key) (LocalState, error)
return LocalState{
PrivKey: privKey,
SignKey: *signPrivKey,
VPNIP: vpnIP,
VPNNet: vpnNet,
WGPort: wgPort,
@@ -126,8 +140,18 @@ func parseLocalState(data []byte) (LocalState, error) {
if err != nil {
return LocalState{}, fmt.Errorf("invalid key: %w", err)
}
signKeyBytes, err := base64.StdEncoding.DecodeString(j.SignKey)
if err != nil {
return LocalState{}, fmt.Errorf("decode sign key: %w", err)
}
if len(signKeyBytes) != 64 {
return LocalState{}, fmt.Errorf("invalid sign key length: %d", len(signKeyBytes))
}
var signKey [64]byte
copy(signKey[:], signKeyBytes)
return LocalState{
PrivKey: key,
SignKey: signKey,
VPNIP: j.VPNIP,
VPNNet: j.VPNNet,
WGPort: j.WGPort,
@@ -139,6 +163,7 @@ func parseLocalState(data []byte) (LocalState, error) {
func saveLocalState(path string, s LocalState) error {
j := localStateJSON{
PrivKey: base64.StdEncoding.EncodeToString(s.PrivKey[:]),
SignKey: base64.StdEncoding.EncodeToString(s.SignKey[:]),
VPNIP: s.VPNIP,
VPNNet: s.VPNNet,
WGPort: s.WGPort,