Implements the from-scratch multi-server WireGuard management fork per CLAUDE.md spec: sqlite schema (servers/peers/audit_log/users), Curve25519 key generation, per-interface config rendering + wg-quick/systemd control, nftables hook scaffolding, session+CSRF-protected REST API with QR code and config download endpoints, a minimal vanilla-JS web UI, legacy wg0.conf migration, and both a native installer and a Proxmox LXC provisioning script (with auto-detected latest Debian template). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
79 lines
2.0 KiB
Go
79 lines
2.0 KiB
Go
package wireguard
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// Status of a WireGuard interface.
|
|
type Status string
|
|
|
|
const (
|
|
StatusUp Status = "UP"
|
|
StatusDown Status = "DOWN"
|
|
)
|
|
|
|
// Up brings up the given interface via wg-quick.
|
|
func Up(iface string) error {
|
|
return run("wg-quick", "up", iface)
|
|
}
|
|
|
|
// Down brings down the given interface via wg-quick.
|
|
func Down(iface string) error {
|
|
return run("wg-quick", "down", iface)
|
|
}
|
|
|
|
// Reload applies config changes to a running interface without a full restart,
|
|
// using `wg syncconf` against a stripped config (wg-quick strip).
|
|
func Reload(iface, confPath string) error {
|
|
strip := exec.Command("wg-quick", "strip", confPath)
|
|
stripped, err := strip.Output()
|
|
if err != nil {
|
|
return fmt.Errorf("wg-quick strip: %w", err)
|
|
}
|
|
sync := exec.Command("wg", "syncconf", iface, "/dev/stdin")
|
|
sync.Stdin = strings.NewReader(string(stripped))
|
|
if out, err := sync.CombinedOutput(); err != nil {
|
|
return fmt.Errorf("wg syncconf: %w: %s", err, out)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IsUp checks whether the interface currently exists / is up.
|
|
func IsUp(iface string) bool {
|
|
cmd := exec.Command("wg", "show", iface)
|
|
return cmd.Run() == nil
|
|
}
|
|
|
|
func GetStatus(iface string) Status {
|
|
if IsUp(iface) {
|
|
return StatusUp
|
|
}
|
|
return StatusDown
|
|
}
|
|
|
|
// EnableService enables and starts the systemd wg-quick@<iface>.service unit.
|
|
func EnableService(iface string) error {
|
|
if err := run("systemctl", "enable", "wg-quick@"+iface); err != nil {
|
|
return err
|
|
}
|
|
return run("systemctl", "start", "wg-quick@"+iface)
|
|
}
|
|
|
|
// DisableService stops and disables the systemd wg-quick@<iface>.service unit.
|
|
func DisableService(iface string) error {
|
|
if err := run("systemctl", "stop", "wg-quick@"+iface); err != nil {
|
|
return err
|
|
}
|
|
return run("systemctl", "disable", "wg-quick@"+iface)
|
|
}
|
|
|
|
func run(name string, args ...string) error {
|
|
cmd := exec.Command(name, args...)
|
|
if out, err := cmd.CombinedOutput(); err != nil {
|
|
return fmt.Errorf("%s %s: %w: %s", name, strings.Join(args, " "), err, out)
|
|
}
|
|
return nil
|
|
}
|