Files
vibedns/web/templates/pages/settings_resolver.html
2026-08-16 21:18:45 -05:00

161 lines
7.2 KiB
HTML

{{define "content"}}
{{$s := .Data.S}}
<h1 class="page-title mb-1">Settings</h1>
<p class="text-body-secondary mb-4">Server configuration, stored in the database.</p>
{{template "settingsnav" .}}
<form method="post" action="/settings/resolver">
<input type="hidden" name="_csrf" value="{{.CSRF}}">
<div class="row g-3">
<div class="col-12 col-xl-8">
<div class="card">
<div class="card-header">Recursive resolution</div>
<div class="card-body">
<div class="form-section">
<div class="form-section-title">Upstream servers</div>
<label class="form-label" for="upstreams">Resolvers, one per line</label>
<textarea class="form-control list-input" id="upstreams" name="upstreams" rows="5"
placeholder="1.1.1.1:53
9.9.9.9:53
[2606:4700:4700::1111]:53">{{joinLines $s.Resolver.Upstreams}}</textarea>
<div class="form-text">
Literal IP addresses only — a host name here could not be resolved, because
this is the resolver that would have to resolve it. Port 53 is assumed if
omitted; bracket IPv6 addresses when specifying a port.
</div>
</div>
<div class="form-section">
<div class="form-section-title">Selection and timing</div>
<div class="row g-3">
<div class="col-12 col-md-6">
<label class="form-label" for="strategy">Server selection</label>
<select class="form-select" id="strategy" name="strategy">
{{range .Data.Strategies}}
<option value="{{.}}" {{if eq . $s.Resolver.Strategy}}selected{{end}}>
{{if eq . "fastest"}}Fastest — prefer the lowest observed latency
{{else if eq . "sequential"}}Sequential — always try the first server first
{{else if eq . "round_robin"}}Round robin — spread queries evenly
{{else}}Random — pick one at random{{end}}
</option>
{{end}}
</select>
<div class="form-text">
A server that fails repeatedly is rested briefly and moved to the back of
the order, whichever strategy is chosen.
</div>
</div>
<div class="col-6 col-md-3">
<label class="form-label" for="timeoutMS">Timeout</label>
<input type="number" class="form-control" id="timeoutMS" name="timeout_ms"
value="{{$s.Resolver.TimeoutMS}}" min="100" max="30000">
<div class="form-text">Milliseconds per attempt</div>
</div>
<div class="col-6 col-md-3">
<label class="form-label" for="retries">Retries</label>
<input type="number" class="form-control" id="retries" name="retries"
value="{{$s.Resolver.Retries}}" min="0" max="10">
<div class="form-text">Extra servers to try</div>
</div>
<div class="col-12 col-md-6">
<label class="form-label" for="maxConcurrent">Maximum concurrent queries</label>
<input type="number" class="form-control" id="maxConcurrent" name="max_concurrent"
value="{{$s.Resolver.MaxConcurrent}}" min="1" max="10000">
<div class="form-text">
Bounds how many upstream exchanges are in flight at once.
</div>
</div>
</div>
</div>
<div class="form-section">
<div class="form-section-title">Protocol preferences</div>
<div class="form-check form-switch mb-2">
<input type="hidden" name="dnssec" value="false">
<input class="form-check-input" type="checkbox" role="switch" id="dnssec"
name="dnssec" value="true" {{if $s.Resolver.DNSSEC}}checked{{end}}>
<label class="form-check-label" for="dnssec">Request DNSSEC records from upstreams</label>
</div>
<div class="form-text mb-3">
Sets the DO bit so signatures are returned and passed through to clients that
ask for them. Validation itself is performed by the upstream resolver.
</div>
<div class="form-check form-switch">
<input type="hidden" name="prefer_ipv6" value="false">
<input class="form-check-input" type="checkbox" role="switch" id="preferIPv6"
name="prefer_ipv6" value="true" {{if $s.Resolver.PreferIPv6}}checked{{end}}>
<label class="form-check-label" for="preferIPv6">Prefer IPv6 upstreams</label>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">
<i class="bi bi-check-lg me-1"></i>Save resolver settings
</button>
</div>
</div>
</div>
</div>
<div class="col-12 col-xl-4">
<div class="card mb-3 border-warning-subtle">
<div class="card-header bg-warning-subtle">
<i class="bi bi-shield-lock me-1"></i>Recursion access control
</div>
<div class="card-body">
<div class="alert alert-warning small">
An empty allow list denies recursion to everyone. A list that is too broad turns
this server into an open resolver, which will be abused for amplification
attacks. Keep it to networks you control.
</div>
<div class="mb-3">
<label class="form-label" for="allowNetworks">Allowed networks</label>
<textarea class="form-control list-input" id="allowNetworks" name="allow_networks" rows="7"
placeholder="192.168.0.0/16
10.0.0.0/8">{{joinLines $s.Resolver.AllowNetworks}}</textarea>
<div class="form-text">One CIDR block or address per line.</div>
</div>
<div>
<label class="form-label" for="denyNetworks">Denied networks</label>
<textarea class="form-control list-input" id="denyNetworks" name="deny_networks" rows="4"
placeholder="192.168.99.0/24">{{joinLines $s.Resolver.DenyNetworks}}</textarea>
<div class="form-text">
Evaluated before the allow list, so you can exclude a range from a broader
allowance.
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">Current upstream health</div>
<div class="card-body p-0">
<table class="table table-sm table-compact mb-0">
<tbody>
{{range .Data.Upstreams}}
<tr>
<td class="mono small">{{.Address}}</td>
<td>
{{if .Healthy}}<span class="badge text-bg-success">ok</span>
{{else}}<span class="badge text-bg-danger">down</span>{{end}}
</td>
<td class="text-end small">{{ms .LatencyMS}}</td>
</tr>
{{else}}
<tr><td class="text-body-secondary small p-3">No upstreams configured.</td></tr>
{{end}}
</tbody>
</table>
</div>
</div>
</div>
</div>
</form>
{{end}}