The firewall page now manages zones (assign each LAN or tunnel, add and remove zones) and rules with zone, address and port on both sides plus the protocol. router.firewall.zones declares zones without members and rules take sourcePorts. The temperature chart draws every thermal zone and hwmon sensor; the overview defaults to 15 minutes, 1h stays an option. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
80 lines
4.3 KiB
HTML
80 lines
4.3 KiB
HTML
{{define "content"}}
|
|
{{with .Data}}
|
|
{{$e := .Errors}}
|
|
<p class="hint">Every LAN and tunnel belongs to a zone. Traffic inside a zone is allowed; between zones it is denied
|
|
unless a rule allows it. A rule works in one direction (replies are always allowed), so letting two zones talk
|
|
to each other takes two rules.</p>
|
|
<form method="post" action="/firewall">
|
|
<input type="hidden" name="csrf" value="{{$.CSRF}}">
|
|
<fieldset>
|
|
<legend>Zones</legend>
|
|
<input type="hidden" name="members" value="{{len .Members}}">
|
|
<table>
|
|
<tr><th>Interface</th><th>Device</th><th>Zone</th></tr>
|
|
{{range $i, $m := .Members}}
|
|
<tr>
|
|
<td>{{if eq $m.Kind "lan"}}LAN{{else}}Tunnel{{end}} <strong>{{$m.Name}}</strong>
|
|
<input type="hidden" name="member.{{$i}}.kind" value="{{$m.Kind}}">
|
|
<input type="hidden" name="member.{{$i}}.name" value="{{$m.Name}}">
|
|
<input type="hidden" name="member.{{$i}}.device" value="{{$m.Device}}"></td>
|
|
<td><code>{{$m.Device}}</code></td>
|
|
<td><select name="member.{{$i}}.zone">
|
|
{{range $.Data.Zones}}<option value="{{.}}" {{if eq . $m.Zone}}selected{{end}}>{{.}}</option>{{end}}
|
|
</select></td>
|
|
</tr>
|
|
{{with index $e (printf "member[%d]" $i)}}<tr><td colspan="3" class="field-error">{{.}}</td></tr>{{end}}
|
|
{{end}}
|
|
</table>
|
|
<p class="hint">Several interfaces can share a zone. The uplink is the zone <code>wan</code>; rules from it publish services.</p>
|
|
{{range .Empty}}
|
|
<p>Zone <strong>{{.}}</strong> has no interface. <label class="inline"><input type="checkbox" name="rmzone" value="{{.}}"> remove</label>
|
|
{{with index $e (printf "zone.%s" .)}}<span class="field-error">{{.}}</span>{{end}}</p>
|
|
{{end}}
|
|
<label>New zones <input name="newzones" value="{{.New}}" size="24" placeholder="guests, iot"></label>
|
|
{{with index $e "newzone"}}<span class="field-error">{{.}}</span>{{end}}
|
|
<p class="hint">A new zone can be picked above (and in the rules) after saving.</p>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<legend>Rules</legend>
|
|
<input type="hidden" name="rows" value="{{len .Rows}}">
|
|
<div class="scroll">
|
|
<table>
|
|
<tr><th>From zone</th><th>From address</th><th>From port</th><th>To zone</th><th>To address</th><th>To port</th><th>Protocol</th><th>Remove</th></tr>
|
|
{{range $i, $r := .Rows}}
|
|
<tr>
|
|
<td><select name="rule.{{$i}}.from"><option value=""></option>
|
|
{{range $.Data.Zones}}<option value="{{.}}" {{if eq . $r.From}}selected{{end}}>{{.}}</option>{{end}}
|
|
</select></td>
|
|
<td><input name="rule.{{$i}}.sources" value="{{$r.Sources}}" size="16" spellcheck="false" placeholder="any"></td>
|
|
<td><input name="rule.{{$i}}.sourceports" value="{{$r.SourcePorts}}" size="8" placeholder="any"></td>
|
|
<td><select name="rule.{{$i}}.to"><option value=""></option>
|
|
{{range $.Data.Zones}}<option value="{{.}}" {{if eq . $r.To}}selected{{end}}>{{.}}</option>{{end}}
|
|
</select></td>
|
|
<td><input name="rule.{{$i}}.destination" value="{{$r.Destination}}" size="16" spellcheck="false" placeholder="whole zone"></td>
|
|
<td><input name="rule.{{$i}}.ports" value="{{$r.Ports}}" size="10" placeholder="all"></td>
|
|
<td><select name="rule.{{$i}}.protocol">
|
|
{{range $p := list "any" "tcp" "udp" "icmp"}}<option value="{{$p}}" {{if eq $p $r.Protocol}}selected{{end}}>{{$p}}</option>{{end}}
|
|
</select></td>
|
|
<td>{{if or $r.From $r.To}}<input type="checkbox" name="rule.{{$i}}.remove">{{end}}</td>
|
|
</tr>
|
|
{{range $f := list "from" "sources" "sourcePorts" "to" "destination" "ports" "protocol"}}{{with index $e (printf "rule[%d].%s" $i $f)}}<tr><td colspan="8" class="field-error">{{$f}}: {{.}}</td></tr>{{end}}{{end}}
|
|
{{end}}
|
|
</table>
|
|
</div>
|
|
<p class="hint">Fill in the last row to add a rule. Addresses (several separated by commas) are IPv4 or IPv6, single or CIDR;
|
|
to address is one address or network. Ports (tcp and udp only): <code>22, 443, 5000-5100</code>.</p>
|
|
</fieldset>
|
|
<button>Save</button>
|
|
</form>
|
|
|
|
{{if .Other}}
|
|
<section>
|
|
<h2>Other rules</h2>
|
|
<p class="muted">Port forwards and rules with more options are kept as they are; change them in <code>settings.json</code>.</p>
|
|
<ul>{{range .Other}}<li>{{.}}</li>{{end}}</ul>
|
|
</section>
|
|
{{end}}
|
|
{{end}}
|
|
{{end}}
|