188 lines
5.0 KiB
Go
188 lines
5.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// Paths mirror the bash profiler's layout so both tools can share on-disk
|
|
// state. They are resolved relative to the executable's directory (overridable
|
|
// with AWG_PROFILER_DIR), the Go analogue of the script's SCRIPT_DIR.
|
|
var (
|
|
scriptDir string
|
|
configFile string
|
|
dataDir string
|
|
clientDir string
|
|
registryFile string
|
|
statsFile string
|
|
stateFile string
|
|
|
|
// Directory awg-quick reads interface configs from (AmneziaWG default).
|
|
awgConfDir = "/etc/amnezia/amneziawg"
|
|
)
|
|
|
|
func resolveScriptDir() string {
|
|
if d := os.Getenv("AWG_PROFILER_DIR"); d != "" {
|
|
return d
|
|
}
|
|
exe, err := os.Executable()
|
|
if err != nil {
|
|
die("Cannot determine executable path: %v", err)
|
|
}
|
|
if resolved, err := filepath.EvalSymlinks(exe); err == nil {
|
|
exe = resolved
|
|
}
|
|
return filepath.Dir(exe)
|
|
}
|
|
|
|
func initPaths() {
|
|
scriptDir = resolveScriptDir()
|
|
configFile = filepath.Join(scriptDir, "awg_config")
|
|
dataDir = filepath.Join(scriptDir, "data")
|
|
clientDir = filepath.Join(scriptDir, "awg_clients")
|
|
registryFile = filepath.Join(dataDir, "awg_clients.json")
|
|
statsFile = filepath.Join(dataDir, "awg_stats.json")
|
|
stateFile = filepath.Join(scriptDir, "awg_state.json")
|
|
}
|
|
|
|
func usage() {
|
|
fmt.Print(`AmneziaWG Profiler — server + client management tool (AmneziaWG variant)
|
|
|
|
Usage: awg_profiler <command> [options]
|
|
|
|
SERVER SETUP
|
|
install-deps Install AmneziaWG, jq, qrencode for this OS and
|
|
record a deps-installed flag (run this FIRST)
|
|
init-server Interactive server setup: verifies dependencies are
|
|
installed, then generates keys + obfuscation
|
|
parameters, writes config, enables IP forwarding and
|
|
starts the service (does NOT install packages)
|
|
|
|
SERVER MANAGEMENT
|
|
server-status Show interface stats and peer list
|
|
server-start Start AmneziaWG service
|
|
server-stop Stop AmneziaWG service
|
|
server-restart Restart AmneziaWG service
|
|
show-config Print current config (private keys hidden)
|
|
sync-config Rebuild <conf-dir>/<iface>.conf from client
|
|
registry and optionally restart the service
|
|
|
|
CLIENT MANAGEMENT
|
|
create <name> Create new VPN client; generates keys, .conf and QR
|
|
code
|
|
delete <id> Remove client by ID (deletes files + registry entry)
|
|
disable <id> Set client status to DISABLED
|
|
enable <id> Set client status to ACTIVE
|
|
list List all registered clients
|
|
|
|
WEB UI
|
|
web [--addr host:port] Start the management web UI (default 127.0.0.1:8080).
|
|
Set AWG_WEB_USER + AWG_WEB_PASS for HTTP Basic auth.
|
|
[--theme name] Select the design (or AWG_WEB_THEME env):
|
|
classic original Modern Dark UI (default)
|
|
glass glassmorphism · Slate + Amber
|
|
[--ui-mode mode] Colour mode (or AWG_WEB_MODE env):
|
|
dark force dark palette (default)
|
|
light force light palette (classic only)
|
|
auto follow the viewer's OS preference
|
|
|
|
Supported OS: Ubuntu, Debian, Linux Mint, Alpine Linux
|
|
`)
|
|
}
|
|
|
|
func main() {
|
|
initPaths()
|
|
|
|
args := os.Args[1:]
|
|
cmd := ""
|
|
if len(args) > 0 {
|
|
cmd = args[0]
|
|
}
|
|
rest := args
|
|
if len(args) > 0 {
|
|
rest = args[1:]
|
|
}
|
|
|
|
switch cmd {
|
|
|
|
case "init-server":
|
|
initServer()
|
|
|
|
case "install-deps":
|
|
installDeps()
|
|
|
|
case "server-status":
|
|
requireBinary("awg")
|
|
c := loadConfig()
|
|
osInfo := detectOS()
|
|
serverStatus(c, osInfo)
|
|
|
|
case "server-start":
|
|
c := loadConfig()
|
|
osInfo := detectOS()
|
|
serviceStart(osInfo, c.Interface)
|
|
info("AmneziaWG started: %s", c.Interface)
|
|
|
|
case "server-stop":
|
|
c := loadConfig()
|
|
osInfo := detectOS()
|
|
serviceStop(osInfo, c.Interface)
|
|
info("AmneziaWG stopped: %s", c.Interface)
|
|
|
|
case "server-restart":
|
|
c := loadConfig()
|
|
osInfo := detectOS()
|
|
serviceRestart(osInfo, c.Interface)
|
|
info("AmneziaWG restarted: %s", c.Interface)
|
|
|
|
case "show-config":
|
|
showConfig()
|
|
|
|
case "sync-config":
|
|
// jq is no longer needed: the Go port reads/writes the registry natively.
|
|
c := loadConfig()
|
|
osInfo := detectOS()
|
|
syncConfig(c, osInfo)
|
|
|
|
case "create":
|
|
requireBinary("awg")
|
|
requireBinary("qrencode")
|
|
c := loadConfig()
|
|
initStorage()
|
|
createClient(c, detectOS(), rest)
|
|
|
|
case "delete":
|
|
c := loadConfig()
|
|
initStorage()
|
|
deleteClient(c, detectOS(), rest)
|
|
|
|
case "disable":
|
|
c := loadConfig()
|
|
initStorage()
|
|
disableClient(c, detectOS(), rest)
|
|
|
|
case "enable":
|
|
c := loadConfig()
|
|
initStorage()
|
|
enableClient(c, detectOS(), rest)
|
|
|
|
case "list":
|
|
// load_config enforces that the server has been initialised first.
|
|
loadConfig()
|
|
initStorage()
|
|
listClients()
|
|
|
|
case "web":
|
|
runWeb(rest)
|
|
|
|
case "--help", "-h", "help", "":
|
|
usage()
|
|
|
|
default:
|
|
fmt.Fprintf(os.Stderr, "Unknown command: %s\n\n", cmd)
|
|
usage()
|
|
os.Exit(1)
|
|
}
|
|
}
|