feat(addon): Diagnose-an-IP tool + actionable auth-error messages

Two complementary improvements for operators debugging a misconfigured
addon — both motivated by a live production incident where "every IP
shows no zone" took several hypotheses (wrong serverId, wrong key,
stale cache) before landing on the real cause.

1. Diagnose-an-IP panel on the addon admin page (VirtFusionDns.php
   _output()). Takes an IP in a text input and runs the full pipeline
   inline: prints the current config snapshot, forces a fresh zone
   list from PowerDNS (bypassing cache), shows the computed PTR name,
   shows what IpUtil::findZoneAndPtrName selects, and fetches the
   current PTR content. Every common failure mode — wrong key, wrong
   serverId, forgotten zone, mis-aligned RFC 2317 label, stale cache
   — produces a distinctive shape in that output.

2. More actionable error messages in PowerDns\Client::ping():

   - On 401/403: now spells out the three real causes (API key
     mismatch, api-allow-from excluding the WHMCS IP, whitespace in
     the stored key) as a checklist, so the operator doesn't have to
     guess which they're hitting.

   - On 404: explicitly names serverId as the field to check and
     reminds that "localhost" is the PowerDNS API server identifier,
     NOT the nameserver's hostname (a surprisingly common misreading
     of the field label).

The addon helper virtfusiondns_load_server_libs() now also pulls in
Resolver + PtrManager lazily since the diagnostic pane needs IpUtil's
pipeline-level output. They're optional — missing files don't break
the basic status page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Prophet731
2026-04-17 22:04:42 -04:00
parent 7e7f3c1c14
commit c1c579dd14
2 changed files with 165 additions and 1 deletions

View File

@@ -128,7 +128,38 @@ class Client
return ['ok' => false, 'http' => 0, 'error' => $err];
}
if ($http === 401 || $http === 403) {
return ['ok' => false, 'http' => $http, 'error' => 'authentication failed (check API key)'];
// Three distinct causes all produce 401/403 here:
// (a) Actual wrong API key — the #1 obvious cause.
// (b) `api-allow-from` in PowerDNS config excludes the WHMCS
// host's IP. PowerDNS rejects pre-auth in some configs,
// producing 401/403 even with a valid key.
// (c) Invisible whitespace in the stored key (fixed in Config
// via trim(), but a pre-upgrade install might still have
// a cached request dating from before the fix).
// Listing all three gives the operator a concrete checklist.
return [
'ok' => false,
'http' => $http,
'error' => 'HTTP ' . $http . ' — PowerDNS rejected authentication. Check: ' .
'(1) the X-API-Key matches the `api-key=` in PowerDNS config, ' .
'(2) `api-allow-from=` includes this WHMCS host\'s IP, and ' .
'(3) the key has no trailing whitespace/newlines (re-paste it if unsure).',
];
}
if ($http === 404) {
// The endpoint reached PowerDNS (no 0/connection-refused) but the
// server ID path segment isn't known. By far the most common cause
// is an addon misconfiguration where someone entered the nameserver
// FQDN instead of the literal string "localhost" into the Server ID
// field. Surface that hypothesis directly — it's the single highest-
// probability fix and turns a mystery into an actionable error.
return [
'ok' => false,
'http' => 404,
'error' => 'HTTP 404 — PowerDNS does not recognise server id "' . $this->serverId .
'". This field should almost always be the literal string "localhost" ' .
'(the PowerDNS API server identifier, NOT your nameserver hostname).',
];
}
return ['ok' => false, 'http' => $http, 'error' => 'unexpected HTTP ' . $http . ': ' . substr((string) $body, 0, 200)];