| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- package api
- import (
- "encoding/json"
- "net/http"
- "proxmox-router/internal/firewall"
- "proxmox-router/internal/routing"
- )
- // ======================== Firewall Summary ========================
- func (s *Server) handleFirewallSummary(w http.ResponseWriter, r *http.Request) {
- writeJSON(w, http.StatusOK, s.fwMgr.GetSummary())
- }
- func (s *Server) handleResetFirewallCounters(w http.ResponseWriter, r *http.Request) {
- if err := s.fwMgr.ResetCounters(); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true})
- }
- // ======================== Filter Rules ========================
- func (s *Server) handleListFilterRules(w http.ResponseWriter, r *http.Request) {
- rules := s.fwMgr.ListFilterRules()
- writeJSON(w, http.StatusOK, rules)
- }
- func (s *Server) handleSaveFilterRule(w http.ResponseWriter, r *http.Request) {
- var rule firewall.FilterRule
- if err := json.NewDecoder(r.Body).Decode(&rule); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := s.fwMgr.SaveFilterRule(rule); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": rule.ID})
- }
- func (s *Server) handleDeleteFilterRule(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- if err := s.fwMgr.DeleteFilterRule(id); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleMoveFilterRule(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Direction string `json:"direction"` // "up" or "down"
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.MoveFilterRule(id, req.Direction); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleSetFilterRuleState(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Disabled bool `json:"disabled"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.SetFilterRuleState(id, req.Disabled); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled})
- }
- // ======================== NAT Rules ========================
- func (s *Server) handleListNATRules(w http.ResponseWriter, r *http.Request) {
- rules := s.fwMgr.ListNATRules()
- writeJSON(w, http.StatusOK, rules)
- }
- func (s *Server) handleSaveNATRule(w http.ResponseWriter, r *http.Request) {
- var rule firewall.NATRule
- if err := json.NewDecoder(r.Body).Decode(&rule); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := s.fwMgr.SaveNATRule(rule); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": rule.ID})
- }
- func (s *Server) handleDeleteNATRule(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- if err := s.fwMgr.DeleteNATRule(id); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleMoveNATRule(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Direction string `json:"direction"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.MoveNATRule(id, req.Direction); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleSetNATRuleState(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Disabled bool `json:"disabled"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.SetNATRuleState(id, req.Disabled); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled})
- }
- // ======================== Mangle Rules ========================
- func (s *Server) handleListMangleRules(w http.ResponseWriter, r *http.Request) {
- rules := s.fwMgr.ListMangleRules()
- writeJSON(w, http.StatusOK, rules)
- }
- func (s *Server) handleSaveMangleRule(w http.ResponseWriter, r *http.Request) {
- var rule firewall.MangleRule
- if err := json.NewDecoder(r.Body).Decode(&rule); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := s.fwMgr.SaveMangleRule(rule); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": rule.ID})
- }
- func (s *Server) handleDeleteMangleRule(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- if err := s.fwMgr.DeleteMangleRule(id); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleMoveMangleRule(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Direction string `json:"direction"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.MoveMangleRule(id, req.Direction); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleSetMangleRuleState(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Disabled bool `json:"disabled"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.SetMangleRuleState(id, req.Disabled); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled})
- }
- // ======================== Address Lists ========================
- func (s *Server) handleListAddressLists(w http.ResponseWriter, r *http.Request) {
- lists := s.fwMgr.ListAddressLists()
- writeJSON(w, http.StatusOK, lists)
- }
- func (s *Server) handleSaveAddressListEntry(w http.ResponseWriter, r *http.Request) {
- var entry firewall.AddressListEntry
- if err := json.NewDecoder(r.Body).Decode(&entry); err != nil || entry.Name == "" || entry.Address == "" {
- writeError(w, http.StatusBadRequest, "name and address are required")
- return
- }
- if err := s.fwMgr.SaveAddressListEntry(entry); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": entry.ID})
- }
- func (s *Server) handleDeleteAddressListEntry(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- if err := s.fwMgr.DeleteAddressListEntry(id); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleSetAddressListEntryState(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Disabled bool `json:"disabled"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.SetAddressListEntryState(id, req.Disabled); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled})
- }
- // ======================== Geo-Location ========================
- func (s *Server) handleGeoIPStatus(w http.ResponseWriter, r *http.Request) {
- status := s.fwMgr.GeoIP().GetStatus()
- writeJSON(w, http.StatusOK, status)
- }
- func (s *Server) handleGeoIPConfig(w http.ResponseWriter, r *http.Request) {
- var req struct {
- AutoUpdate bool `json:"auto_update"`
- IntervalHours int `json:"interval_hours"`
- }
- if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := s.fwMgr.GeoIP().SetConfig(req.AutoUpdate, req.IntervalHours); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "config": req})
- }
- func (s *Server) handleListGeoCountries(w http.ResponseWriter, r *http.Request) {
- countries := s.fwMgr.GeoIP().ListCountries()
- writeJSON(w, http.StatusOK, countries)
- }
- func (s *Server) handleToggleGeoCountry(w http.ResponseWriter, r *http.Request) {
- code := r.PathValue("code")
- var req struct {
- Enabled bool `json:"enabled"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.fwMgr.GeoIP().ToggleCountry(code, req.Enabled); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "code": code, "enabled": req.Enabled})
- }
- func (s *Server) handleUpdateGeoCountry(w http.ResponseWriter, r *http.Request) {
- code := r.PathValue("code")
- count, err := s.fwMgr.GeoIP().SyncCountryZone(code)
- if err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "code": code, "subnets": count})
- }
- func (s *Server) handleGeoIPUpdateNow(w http.ResponseWriter, r *http.Request) {
- if err := s.fwMgr.GeoIP().UpdateNow(); err != nil {
- writeError(w, http.StatusConflict, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "message": "update started"})
- }
- func (s *Server) handleGeoIPBatchToggle(w http.ResponseWriter, r *http.Request) {
- var req struct {
- Preset string `json:"preset"`
- Codes []string `json:"codes"`
- Enabled bool `json:"enabled"`
- }
- if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := s.fwMgr.GeoIP().BatchToggle(req.Preset, req.Enabled, req.Codes); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "preset": req.Preset, "enabled": req.Enabled})
- }
- func (s *Server) handleGeoCountrySubnets(w http.ResponseWriter, r *http.Request) {
- code := r.PathValue("code")
- subnets := s.fwMgr.GeoIP().GetCountrySubnets(code, 100)
- writeJSON(w, http.StatusOK, map[string]any{"code": code, "subnets": subnets})
- }
- // ======================== Active Connections ========================
- func (s *Server) handleListConnections(w http.ResponseWriter, r *http.Request) {
- conns, err := firewall.ListActiveConnections()
- if err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, conns)
- }
- func (s *Server) handleKillConnection(w http.ResponseWriter, r *http.Request) {
- var req struct {
- Protocol string `json:"protocol"`
- Src string `json:"src"`
- Sport int `json:"sport"`
- Dst string `json:"dst"`
- Dport int `json:"dport"`
- }
- if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := firewall.KillConnection(req.Protocol, req.Src, req.Sport, req.Dst, req.Dport); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true})
- }
- // ======================== Routes & Policy Routing ========================
- func (s *Server) handleListRoutes(w http.ResponseWriter, r *http.Request) {
- routes := s.routingMgr.ListRoutes()
- writeJSON(w, http.StatusOK, routes)
- }
- func (s *Server) handleSaveRoute(w http.ResponseWriter, r *http.Request) {
- var route routing.RouteItem
- if err := json.NewDecoder(r.Body).Decode(&route); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := s.routingMgr.SaveRoute(route); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": route.ID})
- }
- func (s *Server) handleDeleteRoute(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- if err := s.routingMgr.DeleteRoute(id); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleSetRouteState(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- var req struct {
- Disabled bool `json:"disabled"`
- }
- _ = json.NewDecoder(r.Body).Decode(&req)
- if err := s.routingMgr.SetRouteState(id, req.Disabled); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled})
- }
- func (s *Server) handleListPolicyRules(w http.ResponseWriter, r *http.Request) {
- rules := s.routingMgr.ListPolicyRules()
- writeJSON(w, http.StatusOK, rules)
- }
- func (s *Server) handleSavePolicyRule(w http.ResponseWriter, r *http.Request) {
- var rule routing.PolicyRuleItem
- if err := json.NewDecoder(r.Body).Decode(&rule); err != nil {
- writeError(w, http.StatusBadRequest, "invalid request body")
- return
- }
- if err := s.routingMgr.SavePolicyRule(rule); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": rule.ID})
- }
- func (s *Server) handleDeletePolicyRule(w http.ResponseWriter, r *http.Request) {
- id := r.PathValue("id")
- if err := s.routingMgr.DeletePolicyRule(id); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
- }
- func (s *Server) handleListRoutingTables(w http.ResponseWriter, r *http.Request) {
- tables := s.routingMgr.ListTables()
- writeJSON(w, http.StatusOK, tables)
- }
- func (s *Server) handleSaveRoutingTable(w http.ResponseWriter, r *http.Request) {
- var table routing.RoutingTableItem
- if err := json.NewDecoder(r.Body).Decode(&table); err != nil || table.Name == "" {
- writeError(w, http.StatusBadRequest, "table name is required")
- return
- }
- if err := s.routingMgr.SaveTable(table); err != nil {
- writeError(w, http.StatusInternalServerError, err.Error())
- return
- }
- writeJSON(w, http.StatusOK, map[string]any{"success": true, "name": table.Name})
- }
|