dns-naming: fix fabricated command syntax, add real reverse-zone screenshot

Two fixes from the step 5 re-audit:
1. The joplin/public-tool evidence blocks showed bracketed placeholders
   inside function arguments ('joplin.[app-to-app zone]') - not valid
   syntax, wouldn't produce the shown NXDOMAIN for the claimed reason.
   Replaced with result tables showing the same real data honestly.
2. Added the real Technitium screenshot of the cleaned-up reverse zone.
   Getting this screenshot caught a real methodology error: an earlier
   claim of '2 real PTR records (automation, caddy)' was wrong - the
   automation entry only resolved because I tested it by SSHing into
   automation itself, which satisfied the lookup via its own local
   /etc/hosts, never actually querying Technitium. Querying from a
   different host returns NXDOMAIN, matching the screenshot's real
   3-record zone (NS, SOA, one PTR) exactly. Only 1 real PTR record
   exists. Same error existed in the KB, fixed there too.
This commit is contained in:
thesabear committed 2026-08-28 21:29:23 +03:00
1 parent 169a294a00
commit 4c63712e6a
2 files changed
+15 -8

No files matched your search

+15 -8
View File
@@ -29,17 +29,22 @@ A homelab this size could get away with a shared hosts file or a single flat zon
Most apps that need both human and machine access get **one hostname per zone** — same app, two different front doors, chosen by which zone the caller resolves it in. Not every app needs both: a purely internal API integration might only ever get the app-to-app hostname; an app nobody automates against might only get the browser-facing one. The two zones aren't kept in lockstep by policy — a periodic audit is what actually catches when they drift, not an assumption that they match. As of the last audit, the app-to-app zone actually runs slightly ahead — 58 records versus 56 — with three apps present only there and one present only on the browser-facing side, real drift a policy alone wouldn't have caught:
```
$ python3 -c "import socket; print(socket.gethostbyname('joplin.[app-to-app zone]'))"
[rocky-docker's IP]
$ python3 -c "import socket; print(socket.gethostbyname('joplin.[browser-facing zone]'))"
socket.gaierror: [Errno -2] Name or service not known
```
This is the real result of a live resolution against both zones, not a claim about what they'd return — the app-to-app hostname resolves, the browser-facing one for the same app doesn't exist at all:
| Zone | `joplin` resolves to |
|---|---|
| App-to-app | `[rocky-docker's IP]` |
| Browser-facing | `NXDOMAIN` |
Same result for `loki` and `wazuh-indexer` (caddy-zone only), and the reverse for `calibre` (browser-facing zone only).
> [!TIP]
> **The public exception, and why it's a real exception and not a bug**: a social-media scheduling tool in this fleet is genuinely meant to be reached from the open internet, routed through the edge firewall's own public reverse-proxy layer (see [`docs/firewall-and-network.md`](firewall-and-network.md)). It has **zero presence in either internal zone** — confirmed live, `NXDOMAIN` on both — not because it was forgotten, but because a third DNS entry pointing at an app that already has its own public-facing edge route would just be redundant. Apps meant for the public internet skip the internal model entirely rather than being forced into it.
> **The public exception, and why it's a real exception and not a bug**: a social-media scheduling tool in this fleet is genuinely meant to be reached from the open internet, routed through the edge firewall's own public reverse-proxy layer (see [`docs/firewall-and-network.md`](firewall-and-network.md)). It has **zero presence in either internal zone** — confirmed live, `NXDOMAIN` on both — not because it was forgotten, but because a third DNS entry pointing at an app that already has its own public-facing edge route would just be redundant. Apps meant for the public internet skip the internal model entirely rather than being forced into it. Same live check, same result, on both zones:
| Zone | Resolves to |
|---|---|
| App-to-app | `NXDOMAIN` |
| Browser-facing | `NXDOMAIN` |
## DNS as an enforced boundary, not just a convenience
@@ -50,7 +55,9 @@ Same result for `loki` and `wazuh-indexer` (caddy-zone only), and the reverse fo
Trusting the KB without re-checking it against the running server would have kept both of these wrong indefinitely — so both got checked directly against the real config and the real zone data, not taken on the KB's word:
- **A reverse zone that had real broken records, not just outdated documentation.** It was described as covering just the observability host's own subnet slice. The zone's own name on the real server settles that on its own — it's the reverse zone for the entire `/24`, not a narrower delegation, which only a different naming pattern could express. A full sweep of every address in the zone — not a sample — turned up four records, and none of them held up: two were malformed PTR entries with their name and value fields reversed, structurally incapable of ever answering a real reverse lookup, not just stale; one was an orphaned leftover from a host decommissioned months earlier; and the fourth — the internal reverse-proxy host's own reverse record — resolved to the name of one specific app proxied through it instead of the host's own identity. The observability host's own IP had no record at all, despite the zone supposedly being scoped around it. All three broken entries got removed and the fourth got corrected, rather than just written up as a known gap.
- **A reverse zone that had real broken records, not just outdated documentation.** It was described as covering just the observability host's own subnet slice. The zone's own name on the real server settles that on its own — it's the reverse zone for the entire `/24`, not a narrower delegation, which only a different naming pattern could express. A full sweep of every address in the zone — not a sample — turned up four records, and none of them held up: two were malformed PTR entries with their name and value fields reversed, structurally incapable of ever answering a real reverse lookup, not just stale; one was an orphaned leftover from a host decommissioned months earlier; and the fourth — the internal reverse-proxy host's own reverse record — resolved to the name of one specific app proxied through it instead of the host's own identity. The observability host's own IP had no record at all, despite the zone supposedly being scoped around it. All three broken entries got removed and the fourth got corrected, rather than just written up as a known gap. This is the zone's real state after the fix, not a claim about it — three records total, only one of them an actual host PTR:
![The real reverse zone in Technitium after cleanup: just 3 records total (the zone's own NS and SOA, plus a single corrected PTR record) — down from 4 broken/malformed entries](../assets/dns-naming-reverse-zone.png)
- **A forwarder that was documented but never actually configured.** Technitium's upstream forwarding was written up as including a well-known public DNS-over-HTTPS provider. Reading the real config directly shows exactly two forwarders: the edge firewall and one other public resolver — the documented provider's IP and name appear nowhere in the file. It looks like it was documented as a plan and never actually implemented, then never revisited to catch the mismatch.
```