Files
2026-08-16 21:18:45 -05:00

131 lines
5.0 KiB
HTML

{{define "content"}}
{{$form := .Data.Form}}{{$r := .Data.Result}}
<div class="mb-4">
<h1 class="page-title">Tools</h1>
<p class="text-body-secondary mb-0">
Run a query through the full server pipeline exactly as a client on a given address
would experience it — policy, authoritative zones, cache and recursion included.
</p>
</div>
<div class="row g-3">
<div class="col-12 col-lg-4">
<div class="card">
<div class="card-header">Look up a name</div>
<div class="card-body">
<form method="post" action="/tools/lookup">
<input type="hidden" name="_csrf" value="{{.CSRF}}">
<div class="mb-3">
<label class="form-label" for="lookupName">Name</label>
<input type="text" class="form-control mono" id="lookupName" name="name"
value="{{index $form "name"}}" placeholder="example.com" required autocomplete="off">
</div>
<div class="mb-3">
<label class="form-label" for="lookupType">Record type</label>
<select class="form-select" id="lookupType" name="type">
{{$sel := index $form "type"}}
{{range list "A" "AAAA" "CNAME" "MX" "TXT" "NS" "SRV" "PTR" "CAA" "SOA" "DS" "DNSKEY" "HTTPS" "ANY"}}
<option value="{{.}}" {{if eq . $sel}}selected{{end}}>{{.}}</option>
{{end}}
</select>
</div>
<div class="mb-3">
<label class="form-label" for="lookupClient">Query as client</label>
<input type="text" class="form-control mono" id="lookupClient" name="client"
value="{{index $form "client"}}" placeholder="127.0.0.1" autocomplete="off">
<div class="form-text">
Policy and recursion ACLs are evaluated against this address, so you can
confirm what a guest device actually sees.
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="lookupDNSSEC"
name="dnssec" value="true" {{if index $form "dnssec"}}checked{{end}}>
<label class="form-check-label" for="lookupDNSSEC">Request DNSSEC records</label>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">
<i class="bi bi-search me-1"></i>Resolve
</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-12 col-lg-8">
{{if .Data.Error}}
<div class="alert alert-danger">
<i class="bi bi-exclamation-triangle me-1"></i>{{.Data.Error}}
</div>
{{end}}
{{if $r}}
<div class="card mb-3">
<div class="card-header d-flex flex-wrap justify-content-between align-items-center gap-2">
<span class="mono">{{$r.Question}}</span>
<span>
<span class="badge {{rcodeBadge $r.Rcode}}">{{$r.Rcode}}</span>
<span class="badge {{sourceBadge $r.Source}}">{{$r.Source}}</span>
<span class="badge text-bg-light text-dark">{{duration $r.Duration}}</span>
</span>
</div>
<div class="card-body">
<h2 class="h6">Answer section</h2>
{{if $r.Answers}}
<pre class="answer-block mb-3">{{range $r.Answers}}{{.}}
{{end}}</pre>
{{else}}
<p class="text-body-secondary fst-italic">Empty — no records of that type exist for this name.</p>
{{end}}
{{if $r.Authority}}
<h2 class="h6">Authority section</h2>
<pre class="answer-block mb-0">{{range $r.Authority}}{{.}}
{{end}}</pre>
{{end}}
</div>
</div>
{{end}}
{{if .Data.ListHits}}
<div class="card mb-3">
<div class="card-header">Policy list matches</div>
<div class="card-body">
<p class="text-body-secondary small">
Lists that cover this name. Whether it is actually blocked also depends on which
policies the client's network has assigned.
</p>
<div class="table-responsive">
<table class="table table-sm align-middle mb-0">
<thead><tr><th>List</th><th>Kind</th><th>Matched entry</th></tr></thead>
<tbody>
{{range .Data.ListHits}}
<tr>
<td><a href="/policies/lists/{{.ListID}}" class="text-decoration-none">{{.ListName}}</a></td>
<td>
<span class="badge {{if eq .Kind "blacklist"}}text-bg-danger{{else}}text-bg-success{{end}}">{{.Kind}}</span>
</td>
<td class="mono">{{.Matched}}</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
</div>
{{end}}
{{if not $r}}
<div class="card">
<div class="card-body">
{{template "empty" dict "Icon" "bi-tools" "Title" "No lookup run yet"
"Message" "Enter a name on the left and resolve it. The result shows which stage of the pipeline answered — a local zone, the cache, an upstream resolver, or a policy block."}}
</div>
</div>
{{end}}
</div>
</div>
{{end}}