2026-04-13 09:46:02 +03:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"net/http"
|
|
|
|
|
|
2026-04-15 11:38:26 +03:00
|
|
|
"nano-router/config"
|
|
|
|
|
"nano-router/nat"
|
2026-04-13 09:46:02 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func HandleNATGet(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodGet {
|
|
|
|
|
fail(w, http.StatusMethodNotAllowed, "method not allowed")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cfg, err := nat.Load()
|
|
|
|
|
if err != nil {
|
|
|
|
|
fail(w, http.StatusInternalServerError, err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ok(w, map[string]interface{}{
|
|
|
|
|
"installed": nat.IsInstalled(),
|
|
|
|
|
"interfaces": cfg.Interfaces,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func HandleNATSave(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
fail(w, http.StatusMethodNotAllowed, "method not allowed")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cfg nat.Config
|
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
|
|
|
|
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if cfg.Interfaces == nil {
|
|
|
|
|
cfg.Interfaces = []string{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !nat.IsInstalled() {
|
|
|
|
|
fail(w, http.StatusServiceUnavailable, "nftables (nft) не установлен — выполните: apk add nftables")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
appCfg, err := config.Load()
|
|
|
|
|
if err != nil {
|
|
|
|
|
fail(w, http.StatusInternalServerError, "load config.yaml: "+err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-04-15 11:38:26 +03:00
|
|
|
|
|
|
|
|
for _, ifaceName := range cfg.Interfaces {
|
|
|
|
|
if appCfg.Interfaces != nil {
|
|
|
|
|
if ic, ok := appCfg.Interfaces[ifaceName]; ok && ic.Type == "wan" {
|
|
|
|
|
fail(w, http.StatusBadRequest, "WAN interface "+ifaceName+" cannot have NAT/Masquerade")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := nat.Save(&cfg); err != nil {
|
|
|
|
|
fail(w, http.StatusInternalServerError, "save: "+err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-13 09:46:02 +03:00
|
|
|
appCfg.NAT.Interfaces = cfg.Interfaces
|
|
|
|
|
if err := config.Save(appCfg); err != nil {
|
|
|
|
|
fail(w, http.StatusInternalServerError, "save config.yaml: "+err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-13 12:40:49 +03:00
|
|
|
if err := applyAllRules(appCfg); err != nil {
|
2026-04-13 09:46:02 +03:00
|
|
|
fail(w, http.StatusInternalServerError, "apply: "+err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ok(w, map[string]string{"message": "nat applied"})
|
2026-04-13 12:40:49 +03:00
|
|
|
}
|