init commit
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// initParams carries the init-server form fields from the web wizard. Empty
|
||||
// fields fall back to the same defaults the interactive CLI prompt offers.
|
||||
type initParams struct {
|
||||
Interface string `json:"interface"`
|
||||
Network string `json:"network"`
|
||||
Port string `json:"port"`
|
||||
PublicIP string `json:"public_ip"`
|
||||
DNS string `json:"dns"`
|
||||
MTU string `json:"mtu"`
|
||||
}
|
||||
|
||||
// initServerWeb is the non-interactive twin of initServer used by the web
|
||||
// wizard. It performs the same steps — verify deps flag, generate keys and
|
||||
// obfuscation parameters, write configs, enable forwarding, start the service —
|
||||
// but takes its inputs from a form instead of stdin prompts.
|
||||
func initServerWeb(p initParams) *Config {
|
||||
osInfo := detectOS()
|
||||
|
||||
st := loadState()
|
||||
if !st.DepsInstalled {
|
||||
die("Dependencies not installed — run install-deps first")
|
||||
}
|
||||
requireBinary("awg")
|
||||
|
||||
c := &Config{}
|
||||
c.Interface = valueOr(strings.TrimSpace(p.Interface), "awg0")
|
||||
c.Network = valueOr(strings.TrimSpace(p.Network), "10.0.0.0/24")
|
||||
requireSlash24(c.Network)
|
||||
c.Port = valueOr(strings.TrimSpace(p.Port), "51820")
|
||||
c.PublicIP = strings.TrimSpace(p.PublicIP)
|
||||
if c.PublicIP == "" {
|
||||
c.PublicIP = detectPublicIP()
|
||||
}
|
||||
c.DNS = valueOr(strings.TrimSpace(p.DNS), "1.1.1.1")
|
||||
c.MTU = valueOr(strings.TrimSpace(p.MTU), "1420")
|
||||
|
||||
mtu := atoiOrDie(c.MTU)
|
||||
|
||||
// Obfuscation parameters — same ceilings/constraints as initServer:
|
||||
// Jmin < Jmax <= MTU ; S1 <= MTU-148 ; S2 <= MTU-92 ; S1+56 != S2.
|
||||
mtuJunkCeil := mtu
|
||||
mtuS1Ceil := mtu - 148
|
||||
mtuS2Ceil := mtu - 92
|
||||
|
||||
rndJc := randRange(4, 12)
|
||||
rndJmin := randRange(8, minInt(mtuJunkCeil-2, 32))
|
||||
rndJmax := randRange(maxInt(rndJmin+32, 80), minInt(mtuJunkCeil, 200))
|
||||
rndS1 := randRange(15, minInt(mtuS1Ceil, 150))
|
||||
rndS2 := randRange(15, minInt(mtuS2Ceil, 150))
|
||||
for rndS1+56 == rndS2 {
|
||||
rndS2 = randRange(15, minInt(mtuS2Ceil, 150))
|
||||
}
|
||||
|
||||
c.Jc = itoa(rndJc)
|
||||
c.Jmin = itoa(rndJmin)
|
||||
c.Jmax = itoa(rndJmax)
|
||||
c.S1 = itoa(rndS1)
|
||||
c.S2 = itoa(rndS2)
|
||||
|
||||
// Four distinct magic-header values in [5, 2^31-1].
|
||||
h1 := randMagic()
|
||||
h2 := randMagic()
|
||||
for h2 == h1 {
|
||||
h2 = randMagic()
|
||||
}
|
||||
h3 := randMagic()
|
||||
for h3 == h1 || h3 == h2 {
|
||||
h3 = randMagic()
|
||||
}
|
||||
h4 := randMagic()
|
||||
for h4 == h1 || h4 == h2 || h4 == h3 {
|
||||
h4 = randMagic()
|
||||
}
|
||||
c.H1 = itoa64(h1)
|
||||
c.H2 = itoa64(h2)
|
||||
c.H3 = itoa64(h3)
|
||||
c.H4 = itoa64(h4)
|
||||
|
||||
// Server keys.
|
||||
priv, err := output("awg", "genkey")
|
||||
if err != nil {
|
||||
die("awg genkey failed: %v", err)
|
||||
}
|
||||
pub, err := outputWithInput(priv, "awg", "pubkey")
|
||||
if err != nil {
|
||||
die("awg pubkey failed: %v", err)
|
||||
}
|
||||
c.ServerPriv = priv
|
||||
c.ServerPub = pub
|
||||
|
||||
srvIP := serverIP(c.Network)
|
||||
defIface := defaultRouteIface()
|
||||
|
||||
writeConfig(c)
|
||||
|
||||
confPath := awgConfPath(c.Interface)
|
||||
if err := os.MkdirAll(awgConfDir, 0755); err != nil {
|
||||
die("Failed to create %s: %v", awgConfDir, err)
|
||||
}
|
||||
if err := os.WriteFile(confPath, []byte(awgConfHeader(c, c.ServerPriv, srvIP, c.Port, c.MTU)), 0600); err != nil {
|
||||
die("Failed to write %s: %v", confPath, err)
|
||||
}
|
||||
writeNftRules(c.Interface, defIface, c.MTU)
|
||||
|
||||
// IP forwarding (persistent).
|
||||
enableIPForwarding()
|
||||
|
||||
serviceEnable(osInfo, c.Interface)
|
||||
serviceStart(osInfo, c.Interface)
|
||||
|
||||
initStorage()
|
||||
info("Server initialised via web: interface=%s pubkey=%s", c.Interface, c.ServerPub)
|
||||
return c
|
||||
}
|
||||
|
||||
// syncConfigWeb is the non-interactive twin of syncConfig: it rebuilds the
|
||||
// interface conf from the ACTIVE peers in the registry and optionally restarts
|
||||
// the service, without the CLI's stdin confirmation prompt.
|
||||
func syncConfigWeb(c *Config, osInfo *OSInfo, restart bool) {
|
||||
confPath := awgConfPath(c.Interface)
|
||||
if _, err := os.Stat(confPath); err != nil {
|
||||
die("%s not found — run init-server first", confPath)
|
||||
}
|
||||
|
||||
srvIP := serverIP(c.Network)
|
||||
defIface := defaultRouteIface()
|
||||
mtu := c.mtuOr("1420")
|
||||
|
||||
clients := loadRegistry()
|
||||
var b strings.Builder
|
||||
b.WriteString(awgConfHeader(c, c.ServerPriv, srvIP, c.Port, mtu))
|
||||
for _, cl := range clients {
|
||||
if cl.IsEnabled == "ACTIVE" {
|
||||
b.WriteString(peerBlock(cl.Name, cl.PublicKey, cl.PSKKey, cl.IP))
|
||||
}
|
||||
}
|
||||
if err := os.WriteFile(confPath, []byte(b.String()), 0600); err != nil {
|
||||
die("Failed to write %s: %v", confPath, err)
|
||||
}
|
||||
writeNftRules(c.Interface, defIface, mtu)
|
||||
|
||||
if restart {
|
||||
serviceRestart(osInfo, c.Interface)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user