14.04.2026 Update

This commit is contained in:
2026-04-15 11:38:26 +03:00
parent 6aa0349f5d
commit f50d79fab3
45 changed files with 5645 additions and 751 deletions

View File

@@ -6,9 +6,9 @@ import (
"net/http"
"strings"
"alpine-router/clients"
"alpine-router/config"
"alpine-router/dhcp"
"nano-router/clients"
"nano-router/config"
"nano-router/dhcp"
)
func HandleClients(w http.ResponseWriter, r *http.Request) {
@@ -42,13 +42,14 @@ func HandleClientUpdate(w http.ResponseWriter, r *http.Request) {
Hostname string `json:"hostname"`
Blocked bool `json:"blocked"`
StaticIP string `json:"static_ip"`
Policy string `json:"policy"` // "disabled" | "direct" | "vpn" | ""
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
return
}
if err := updateClient(mac, req.Hostname, req.Blocked, req.StaticIP); err != nil {
if err := updateClient(mac, req.Hostname, req.Blocked, req.StaticIP, req.Policy); err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
@@ -58,7 +59,88 @@ func HandleClientUpdate(w http.ResponseWriter, r *http.Request) {
ok(w, map[string]string{"message": "updated"})
}
func updateClient(mac, hostname string, blocked bool, staticIP string) error {
// HandleClientPolicyDefault handles GET/POST for the default client routing policy.
func HandleClientPolicyDefault(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
cfg, err := config.Load()
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
ok(w, map[string]string{"default": cfg.ClientPolicy.Default})
case http.MethodPost:
var req struct {
Default string `json:"default"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
return
}
if req.Default != "disabled" && req.Default != "direct" && req.Default != "vpn" {
fail(w, http.StatusBadRequest, "invalid policy: must be disabled, direct, or vpn")
return
}
cfg, err := config.Load()
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
cfg.ClientPolicy.Default = req.Default
if err := config.Save(cfg); err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
go applyBlockedFirewall()
ok(w, map[string]string{"default": req.Default})
default:
fail(w, http.StatusMethodNotAllowed, "method not allowed")
}
}
// HandleClientPolicyApplyAll sets the given policy on every known device.
func HandleClientPolicyApplyAll(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
fail(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
var req struct {
Policy string `json:"policy"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
return
}
if req.Policy != "disabled" && req.Policy != "direct" && req.Policy != "vpn" {
fail(w, http.StatusBadRequest, "invalid policy: must be disabled, direct, or vpn")
return
}
cfg, err := config.Load()
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
for i := range cfg.KnownDevices {
cfg.KnownDevices[i].Policy = req.Policy
// Keep Blocked flag consistent: disabled policy means blocked.
cfg.KnownDevices[i].Blocked = req.Policy == "disabled"
}
if err := config.Save(cfg); err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
go applyBlockedFirewall()
ok(w, map[string]int{"updated": len(cfg.KnownDevices)})
}
func updateClient(mac, hostname string, blocked bool, staticIP, policy string) error {
cfg, err := config.Load()
if err != nil {
return err
@@ -67,9 +149,11 @@ func updateClient(mac, hostname string, blocked bool, staticIP string) error {
found := false
for i := range cfg.KnownDevices {
if cfg.KnownDevices[i].MAC == mac {
cfg.KnownDevices[i].Blocked = blocked
cfg.KnownDevices[i].Hostname = hostname
cfg.KnownDevices[i].StaticIP = staticIP
cfg.KnownDevices[i].Policy = policy
// Derive Blocked from policy for backward compatibility.
cfg.KnownDevices[i].Blocked = policy == "disabled"
found = true
break
}
@@ -79,15 +163,15 @@ func updateClient(mac, hostname string, blocked bool, staticIP string) error {
cfg.KnownDevices = append(cfg.KnownDevices, config.KnownDevice{
MAC: mac,
Hostname: hostname,
Blocked: blocked,
StaticIP: staticIP,
Policy: policy,
Blocked: policy == "disabled",
})
}
return config.Save(cfg)
}
func applyDHCPStaticBindings() {
if !dhcp.IsInstalled() {
return