package handlers import ( "encoding/json" "net/http" "nano-router/config" "nano-router/nat" ) 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 } 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 } appCfg.NAT.Interfaces = cfg.Interfaces if err := config.Save(appCfg); err != nil { fail(w, http.StatusInternalServerError, "save config.yaml: "+err.Error()) return } if err := applyAllRules(appCfg); err != nil { fail(w, http.StatusInternalServerError, "apply: "+err.Error()) return } ok(w, map[string]string{"message": "nat applied"}) }