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

149 lines
5.8 KiB
HTML

{{define "content"}}
{{$s := .Data.Settings}}{{$st := .Data.Stats}}
<div class="d-flex flex-wrap justify-content-between align-items-start gap-3 mb-4">
<div>
<h1 class="page-title">Resolver</h1>
<p class="text-body-secondary mb-0">
Recursive resolution is performed by forwarding to the upstream servers below.
</p>
</div>
<a href="/settings/resolver" class="btn btn-primary btn-sm">
<i class="bi bi-gear me-1"></i>Resolver settings
</a>
</div>
{{if not $s.DNS.Recursion}}
<div class="alert alert-secondary d-flex align-items-center gap-2">
<i class="bi bi-info-circle"></i>
<div>
Recursion is turned off. This server answers only for its own authoritative zones;
every other query is refused.
</div>
</div>
{{end}}
<div class="row g-3 mb-4">
{{template "stat" dict "Label" "Forwarded queries" "Value" (num $st.Queries) "Icon" "bi-globe2"}}
{{template "stat" dict "Label" "Failures" "Value" (num $st.Failures) "Icon" "bi-exclamation-triangle" "Tone" "danger"}}
{{template "stat" dict "Label" "Average latency" "Value" (ms $st.AvgLatencyMS) "Icon" "bi-stopwatch"}}
{{template "stat" dict "Label" "Healthy upstreams" "Value" (printf "%d / %d" $st.Healthy $st.Upstreams) "Icon" "bi-heart-pulse" "Tone" "success"}}
</div>
<div class="row g-3">
<div class="col-12 col-xl-7">
<div class="card h-100">
<div class="card-header">Upstream servers</div>
{{if .Data.Upstreams}}
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead>
<tr>
<th>Server</th><th>Status</th>
<th class="text-end">Latency</th><th class="text-end">Queries</th>
<th class="text-end">Failures</th><th>Last used</th>
</tr>
</thead>
<tbody>
{{range .Data.Upstreams}}
<tr>
<td class="mono fw-semibold">{{.Address}}</td>
<td>
{{if .Healthy}}
<span class="badge text-bg-success">healthy</span>
{{else}}
<span class="badge text-bg-danger">resting</span>
{{end}}
{{if .LastError}}
<div class="small text-body-secondary truncate-cell" title="{{.LastError}}">{{truncate 60 .LastError}}</div>
{{end}}
</td>
<td class="text-end">{{ms .LatencyMS}}</td>
<td class="text-end">{{num .Queries}}</td>
<td class="text-end">{{num .Failures}}</td>
<td class="small text-body-secondary">
{{if .LastUsed}}{{timeAgo .LastUsed}}{{else}}never{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
<div class="card-body pt-2">
<p class="form-text mb-0">
A server that fails three times in a row is rested for twenty seconds and moved
to the back of the selection order. The current strategy is
<span class="badge text-bg-light text-dark">{{$s.Resolver.Strategy}}</span>.
</p>
</div>
{{else}}
<div class="card-body">
{{template "empty" dict "Icon" "bi-globe2" "Title" "No upstream resolvers configured"
"Message" "Recursive resolution needs at least one upstream server. Add one in the resolver settings."}}
</div>
{{end}}
</div>
</div>
<div class="col-12 col-xl-5">
<div class="card mb-3">
<div class="card-header">Test an upstream</div>
<div class="card-body">
<form method="post" action="/resolver/test" class="row g-2">
<input type="hidden" name="_csrf" value="{{.CSRF}}">
<div class="col-12">
<label class="form-label" for="testAddress">Server</label>
<input type="text" class="form-control form-control-sm mono" id="testAddress" name="address"
placeholder="1.1.1.1:53" required
value="{{if .Data.Upstreams}}{{(index .Data.Upstreams 0).Address}}{{end}}">
</div>
<div class="col-12">
<label class="form-label" for="testName">Name to resolve</label>
<input type="text" class="form-control form-control-sm mono" id="testName" name="name"
placeholder="example.com" value="example.com">
</div>
<div class="col-12 d-grid">
<button type="submit" class="btn btn-outline-primary btn-sm">
<i class="bi bi-broadcast me-1"></i>Send a test query
</button>
</div>
</form>
</div>
</div>
<div class="card">
<div class="card-header">Recursion access control</div>
<div class="card-body">
<p class="form-text">
Recursion is refused for any client not listed here. This is what keeps the
server from becoming an open resolver.
</p>
<div class="mb-3">
<div class="fw-semibold small mb-1">Allowed networks</div>
{{if $s.Resolver.AllowNetworks}}
<div class="d-flex flex-wrap gap-1">
{{range $s.Resolver.AllowNetworks}}
<span class="badge text-bg-success-subtle border border-success-subtle text-success-emphasis mono">{{.}}</span>
{{end}}
</div>
{{else}}
<div class="text-danger small">None — recursion is denied to every client.</div>
{{end}}
</div>
{{if $s.Resolver.DenyNetworks}}
<div>
<div class="fw-semibold small mb-1">Denied networks</div>
<div class="d-flex flex-wrap gap-1">
{{range $s.Resolver.DenyNetworks}}
<span class="badge text-bg-danger-subtle border border-danger-subtle text-danger-emphasis mono">{{.}}</span>
{{end}}
</div>
<div class="form-text">Denies are evaluated before allows.</div>
</div>
{{end}}
</div>
</div>
</div>
</div>
{{end}}