Files
vps/.agents/skills/encrypted-dns-skill/README.md
T

234 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Encrypted DNS Skill
[![CI](https://github.com/windyboy/encrypted-dns-skill/actions/workflows/ci.yml/badge.svg)](https://github.com/windyboy/encrypted-dns-skill/actions/workflows/ci.yml)
An [Agent Skill](https://agentskills.io/specification) and deterministic Go CLI
for querying and diagnosing encrypted DNS resolvers.
The skill tells an agent when and how to perform encrypted DNS diagnostics;
`ednsdiag` performs the protocol exchange. Agents do not need to construct DoH
URLs, TLS sessions, or DNS wire messages themselves.
## Status
| Protocol | Status | Standard |
| --- | --- | --- |
| DNS over HTTPS (DoH) | Available (GET and POST) | [RFC 8484](https://www.rfc-editor.org/rfc/rfc8484.html) |
| DNS over TLS (DoT) | Available (strict authentication) | [RFC 7858](https://www.rfc-editor.org/rfc/rfc7858.html), [RFC 8310](https://www.rfc-editor.org/rfc/rfc8310.html) |
| DNS over QUIC (DoQ) | Available | [RFC 9250](https://www.rfc-editor.org/rfc/rfc9250.html) |
| DoH over HTTP/3 (DoH3) | Available (GET and POST) | RFC 8484 over HTTP/3 |
| DNSCrypt | Available (v2 over UDP) | [DNSCrypt protocol specification](https://github.com/DNSCrypt/dnscrypt-protocol) |
| Oblivious DoH (ODoH) | Research | [RFC 9230](https://www.rfc-editor.org/rfc/rfc9230.html) |
| Anonymized DNSCrypt | Research | [Anonymized DNSCrypt specification](https://github.com/DNSCrypt/dnscrypt-protocol/blob/master/ANONYMIZED-DNSCRYPT.txt) |
Run `ednsdiag capabilities` instead of assuming a protocol is implemented.
## Why a Skill and a CLI?
- `SKILL.md` provides compact instructions, safety boundaries, and result
interpretation for an AI agent.
- `ednsdiag` provides repeatable wire-format DNS, HTTP, TLS, input validation,
and structured JSON output.
- Reference files keep protocol, provider, and security details grounded in
authoritative sources without bloating the agent's active context.
The CLI never silently downgrades to plaintext DNS, and it does not connect to
addresses returned in DNS answers.
## Requirements
- Go 1.26.6 or later when running or building from source
- Network access to the selected encrypted DNS resolver
- A host that supports the [Agent Skills package format](https://agentskills.io/specification) when using the repository as a Skill
## Install the Skill
Clone or copy this repository into a skill discovery directory supported by
your agent host. Keep the repository layout intact so `SKILL.md`, `references/`,
`schemas/`, and the Go source remain together.
For example, in a host that discovers project-local skills from `.agents/skills`:
```bash
git clone https://github.com/windyboy/encrypted-dns-skill.git \
.agents/skills/encrypted-dns-skill
```
Discovery paths differ between hosts. Follow the host's documentation rather
than moving only `SKILL.md`.
## Run from Source
No precompiled executable is required. Go can compile and run the command from
the repository root:
```bash
go run ./cmd/ednsdiag capabilities
go run ./cmd/ednsdiag query example.com A --protocol doh --provider cloudflare
go run ./cmd/ednsdiag query gmail.com MX --protocol dot --provider google --timeout 5s
HTTPS_PROXY=http://127.0.0.1:8080 go run ./cmd/ednsdiag query example.com A --protocol doh
go run ./cmd/ednsdiag query example.com A --protocol dot --proxy http://127.0.0.1:8080
go run ./cmd/ednsdiag query example.com AAAA --protocol doq --provider adguard
go run ./cmd/ednsdiag query example.com HTTPS --protocol doh3 --provider cloudflare
go run ./cmd/ednsdiag query example.com A --protocol dnscrypt --provider adguard
go run ./cmd/ednsdiag probe example.com A --protocol dot --provider cloudflare
go run ./cmd/ednsdiag compare example.com A \
--target doh:cloudflare --target dot:google
```
The first run may download the modules pinned in `go.mod` and `go.sum`.
To build a reusable local executable:
```bash
go build -o ./bin/ednsdiag ./cmd/ednsdiag
./bin/ednsdiag capabilities
```
Do not download or execute an unverified third-party binary. This repository
does not currently publish release binaries.
## Usage
```text
ednsdiag capabilities
ednsdiag version
ednsdiag query <domain> [type] \
[--protocol doh|dot|doq|doh3|dnscrypt|odoh|anonymized-dnscrypt] \
[--provider cloudflare|google|quad9|adguard] \
[--method post|get] \
[--proxy http://host:port] \
[--timeout 5s]
ednsdiag probe <domain> [type] [query options]
ednsdiag compare <domain> [type] \
--target protocol:provider[:method] \
--target protocol:provider[:method] \
[--proxy http://host:port] \
[--attempt-timeout 5s] [--timeout 30s] [--max-attempts 4]
```
Defaults are `A`, `doh`, `cloudflare`, `post`, and `5s`. `--method` applies
only to DoH and DoH3. The timeout must be between `250ms` and `30s`.
Research protocols are accepted as inputs so automation receives a structured
`unsupported` result and exit code `4`; they are never silently substituted.
DoH and DoT honor Go's standard `HTTPS_PROXY`/`https_proxy` and
`NO_PROXY`/`no_proxy` environment variables. `--proxy` overrides environment
selection and accepts an `http://` or `https://` proxy URL, including optional
Basic-auth userinfo. DoT uses HTTP CONNECT before its resolver TLS handshake.
DoH3, DoQ, and DNSCrypt are UDP/QUIC transports and cannot use this TCP CONNECT
proxy; an explicit proxy combined with one of those protocols is rejected.
The same `--proxy` is shared by every DoH/DoT target in a `compare` operation.
See Go's official [`ProxyFromEnvironment` documentation](https://pkg.go.dev/net/http#ProxyFromEnvironment)
for environment-variable and `NO_PROXY` matching rules.
`compare` accepts 28 unique, allowlisted targets, bounded by `--max-attempts`.
Its total timeout is `250ms``60s`; each attempt timeout is `250ms``30s` and
cannot exceed the total. Comparison targets start concurrently, results retain
the requested target order, and answers are never merged.
Supported record types are `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SOA`,
`CAA`, `SRV`, `PTR`, `HTTPS`, and `SVCB`. For `PTR`, pass an IP address; the CLI
constructs the reverse name. Other IP literals and local names remain blocked.
Built-in resolver profiles:
| Provider | Profile | DoH | DoT | DoQ | DoH3 | DNSCrypt |
| --- | --- | --- | --- | --- | --- | --- |
| Cloudflare | Unfiltered | Yes | Yes | No | Yes | No |
| Google | Unfiltered | Yes | Yes | No | Yes | No |
| Quad9 | Security-filtered | Yes | Yes | No | No | No |
| AdGuard | Ad- and security-filtered | Yes | Yes | Yes | No | Yes |
Filtering policies can affect DNS answers. Results always identify the
provider and profile used.
## Result Semantics
Every query returns structured JSON compatible with
[`schemas/result-v1.schema.json`](schemas/result-v1.schema.json).
- `completed: true` means the encrypted protocol exchange completed; it does
not mean the DNS response was `NOERROR`.
- `dns.rcode` is the DNS result. `NXDOMAIN`, `SERVFAIL`, and `REFUSED` are DNS
outcomes, not transport failures.
- Empty `dns.answers` with `NOERROR` means NODATA.
- `transport.server_authenticated` reports resolver endpoint authentication.
- `dns.resolver_reports_dnssec_authenticated` reflects the resolver's AD bit;
it is not local DNSSEC validation.
- `transport.bootstrap: system_resolver` means the operating system resolver
was used to locate the encrypted resolver endpoint.
- `transport.proxy`, when present, is the HTTP(S) proxy endpoint actually
selected for DoH or DoT. Embedded credentials are never reported.
- DNSCrypt reports `bootstrap: stamp_ip`, the authenticated provider name,
resolver certificate serial, and selected crypto construction.
- DoH and DoH3 subtract a valid HTTP `Age` value from returned answer TTLs and
report it as `transport.http_age_seconds`.
- Truncated or non-representable DNS answers are protocol failures rather than
partial `completed: true` results.
Human-readable usage errors go to stderr. Machine-readable operational results
go to stdout. Stable exit codes are:
| Code | Meaning |
| --- | --- |
| `0` | The requested encrypted DNS operation completed; inspect `dns.rcode`. |
| `1` | Local or internal failure. |
| `2` | Invalid input or CLI usage. |
| `3` | Transport or DNS protocol failure. |
| `4` | Known but unsupported capability or provider/protocol combination. |
See [`references/contracts.md`](references/contracts.md) for the complete v1
command and result contract.
## Security Model
- DoH uses standard `application/dns-message` wire messages.
- DoT verifies the PKIX certificate chain and configured authentication domain.
- DoT advertises ALPN `dot`; an empty selection is accepted and reported, while
selection of a different application protocol is rejected.
- DNSCrypt validates the resolver stamp, Ed25519-signed certificate, validity
interval, provider identity, and encrypted response before accepting DNS data.
- Plaintext fallback is prohibited.
- DNS errors are not retried through another protocol as transport failures.
- Provider and protocol results remain separate.
- DNS answers are data only; the tool does not make application connections to
returned addresses.
See [`references/security.md`](references/security.md) for the complete threat
model and privacy boundaries.
## Development
```bash
go test ./...
go test -race ./...
go vet ./...
go run honnef.co/go/tools/cmd/staticcheck@v0.7.0 ./...
go run golang.org/x/vuln/cmd/govulncheck@v1.6.0 ./...
python3 scripts/validate_skill.py .
```
Public endpoint interoperability tests are opt-in and skip cleanly when the
host cannot reach the network:
```bash
EDNSDIAG_PUBLIC_INTEROP=1 go test ./internal/edns \
-run '^TestPublicCloudflareDo[HT]Interoperability$' -count=1 -v
```
Protocol behavior must remain aligned with
[`references/standards.md`](references/standards.md), provider changes with
[`references/providers.md`](references/providers.md), and output with the v1
JSON schema.
## Scope
This project targets client-to-recursive encrypted DNS diagnostics. It is not a
system stub resolver, an authoritative DNS server, a hosted DNS record manager,
or a zone-transfer tool.
## License
Licensed under the [Apache License 2.0](LICENSE).