Edit port forwards and openings from the internet on the firewall page
Rules from wan are edited in their own table: protocol, ports, zone, host, host port, allowed sources, port forward (NAT), hairpin, log and rate limit, with the module's checks done up front. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
@@ -123,6 +123,9 @@ func (s Settings) firewallRules() (simple []FirewallRule, other []string) {
|
||||
if r == nil {
|
||||
continue
|
||||
}
|
||||
if wanRuleSimple(r) {
|
||||
continue
|
||||
}
|
||||
if !ruleSimple(r) {
|
||||
desc := str(r, "from") + " → " + str(r, "to")
|
||||
if d := str(r, "destination"); d != "" {
|
||||
@@ -260,7 +263,7 @@ func (s Settings) applyZones(zf ZoneForm, errs FormErrors) {
|
||||
|
||||
// applyFirewall changes the zones, then replaces the rules the page edits with
|
||||
// rows (an untouched "add" row is skipped); the other rules stay as they are.
|
||||
func (s Settings) applyFirewall(zf ZoneForm, rows []FirewallRule) error {
|
||||
func (s Settings) applyFirewall(zf ZoneForm, rows []FirewallRule, fwds []WANRule) error {
|
||||
errs := FormErrors{}
|
||||
s.applyZones(zf, errs)
|
||||
zones := s.zones()
|
||||
@@ -333,12 +336,13 @@ func (s Settings) applyFirewall(zf ZoneForm, rows []FirewallRule) error {
|
||||
}
|
||||
next = append(next, rule)
|
||||
}
|
||||
next = append(next, s.forwardRules(fwds, zones, errs)...)
|
||||
router := obj(s, "router")
|
||||
fw := obj(router, "firewall")
|
||||
old, _ := fw["rules"].([]any)
|
||||
for _, v := range old {
|
||||
r, _ := v.(map[string]any)
|
||||
if r == nil || ruleSimple(r) {
|
||||
if r == nil || ruleSimple(r) || wanRuleSimple(r) {
|
||||
continue
|
||||
}
|
||||
// Port forwards and the like are not edited here, but must keep a zone to point at.
|
||||
@@ -365,18 +369,19 @@ func (s Settings) applyFirewall(zf ZoneForm, rows []FirewallRule) error {
|
||||
}
|
||||
|
||||
type firewallData struct {
|
||||
Rows []FirewallRule
|
||||
Other []string
|
||||
Zones []string
|
||||
Members []ZoneMember
|
||||
Empty []string // zones without members, which can be removed
|
||||
New string
|
||||
Errors FormErrors
|
||||
Rows []FirewallRule
|
||||
Forwards []WANRule
|
||||
Other []string
|
||||
Zones []string
|
||||
Members []ZoneMember
|
||||
Empty []string // zones without members, which can be removed
|
||||
New string
|
||||
Errors FormErrors
|
||||
}
|
||||
|
||||
func (s Settings) firewallData(rows []FirewallRule, members []ZoneMember, errs FormErrors) firewallData {
|
||||
func (s Settings) firewallData(rows []FirewallRule, fwds []WANRule, members []ZoneMember, errs FormErrors) firewallData {
|
||||
_, other := s.firewallRules()
|
||||
d := firewallData{Rows: rows, Other: other, Zones: s.zones(), Members: members, Errors: errs}
|
||||
d := firewallData{Rows: rows, Forwards: fwds, Other: other, Zones: s.zones(), Members: members, Errors: errs}
|
||||
if d.Members == nil {
|
||||
d.Members = s.zoneMembers()
|
||||
}
|
||||
@@ -398,7 +403,7 @@ func (a *app) firewallPage(w http.ResponseWriter, r *http.Request, sess session)
|
||||
}
|
||||
rows, _ := s.firewallRules()
|
||||
add := FirewallRule{From: r.URL.Query().Get("from"), To: r.URL.Query().Get("to"), Protocol: "any"}
|
||||
p.Data = s.firewallData(append(rows, add), nil, nil)
|
||||
p.Data = s.firewallData(append(rows, add), append(s.portForwards(), WANRule{Protocol: "tcp", NAT: true}), nil, nil)
|
||||
a.render(w, "firewall", p)
|
||||
}
|
||||
|
||||
@@ -417,19 +422,27 @@ func (a *app) firewall(w http.ResponseWriter, r *http.Request, sess session) {
|
||||
zf.Members = append(zf.Members, ZoneMember{Kind: v("kind"), Name: v("name"), Device: v("device"), Zone: v("zone")})
|
||||
}
|
||||
n, _ := strconv.Atoi(r.PostFormValue("rows"))
|
||||
nf, _ := strconv.Atoi(r.PostFormValue("forwards"))
|
||||
var fwds []WANRule
|
||||
for i := range min(nf, 512) {
|
||||
v := func(k string) string { return r.PostFormValue(fmt.Sprintf("fwd.%d.%s", i, k)) }
|
||||
fwds = append(fwds, WANRule{Protocol: v("protocol"), Ports: v("ports"), To: v("to"), Destination: v("destination"),
|
||||
ToPort: v("toport"), Sources: v("sources"), NAT: v("nat") == "on", Hairpin: v("hairpin") == "on",
|
||||
Log: v("log") == "on", RateLimit: v("ratelimit"), Remove: v("remove") == "on"})
|
||||
}
|
||||
var rows []FirewallRule
|
||||
for i := range min(n, 512) {
|
||||
v := func(k string) string { return r.PostFormValue(fmt.Sprintf("rule.%d.%s", i, k)) }
|
||||
rows = append(rows, FirewallRule{From: v("from"), Sources: v("sources"), SourcePorts: v("sourceports"),
|
||||
To: v("to"), Destination: v("destination"), Ports: v("ports"), Protocol: v("protocol"), Remove: v("remove") == "on"})
|
||||
}
|
||||
if err := s.applyFirewall(zf, rows); err != nil {
|
||||
if err := s.applyFirewall(zf, rows, fwds); err != nil {
|
||||
var fe FormErrors
|
||||
errors.As(err, &fe)
|
||||
// Show what was entered; the zone lists are those before this attempt.
|
||||
s, _ = loadSettings(a.sys.settingsPath())
|
||||
p.Error = "Please correct the marked fields."
|
||||
d := s.firewallData(rows, zf.Members, fe)
|
||||
d := s.firewallData(rows, fwds, zf.Members, fe)
|
||||
d.New = zf.New
|
||||
p.Data = d
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
|
||||
Reference in New Issue
Block a user