Add per-vhost CustomLog directives; document access-log root cause

Real root cause turned out to differ from the original TODO: there was
no broken global CustomLog, mod_vhost_combined was already logging
every vhost without its own CustomLog into other_vhosts_access.log.
Added a dedicated CustomLog per real site anyway for easier incident
review, verified live with curl against all 7 domains after reload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 20:43:19 +02:00
co-authored by Claude Sonnet 5
parent cff15408bf
commit 3f51d6016e
2 changed files with 26 additions and 14 deletions
+2
View File
@@ -380,3 +380,5 @@ that key file, not group membership, since the `bind` group also owns
`rndc.key` — and (b) that access logging for every real vhost on this
host is currently a no-op, and (c) that the dyndns app has no real
per-user auth binding. (b) and (c) are left open — see `TODO.md`.)
(b) fixed 2026-07-25 — see `TODO.md` for the root cause and the
per-vhost `CustomLog` fix; (c) remains open.
+24 -14
View File
@@ -16,22 +16,32 @@ Nothing here is urgent; all are low-risk, no-downtime changes.
tokens, or add a static host-allowlist per `.htpasswd` user in the
PHP.
- [ ] **dyndns/default-vhost access logging is a no-op**found
2026-07-20, while investigating the command injection below.
- [x] **dyndns/default-vhost access logging is a no-op**done 2026-07-25
found 2026-07-20 while investigating the command injection below.
`dyndns.jayfield.org`, `jayfield.org`, `www.jayfield.org`,
`mail.jayfield.org`, `web.jayfield.org`, and `cloud.jayfield.org`
have no `CustomLog` directive of their own, so requests to them
should fall back to the global `CustomLog ${APACHE_LOG_DIR}/access.log`
in `apache2.conf` — but that file had 0 lines when checked. Only
`default-ssl.conf`/`000-default.conf` explicitly set `CustomLog`.
Net effect: there's currently no access-log trail for any real
vhost on this host, which is exactly the evidence that would be
needed to rule out past abuse of things like the dyndns injection
above. Needs root-causing (global `CustomLog` not actually wired up
to these vhosts? logs going somewhere else? log rotation wiping it
right before checks?) and likely a per-vhost `CustomLog` added to
each site, matching the `default-ssl.conf`/`000-default.conf`
pattern.
had no `CustomLog` directive of their own, and `access.log` (only
written by `default-ssl.conf`/`000-default.conf`) had 0-8 lines —
looking like no real vhost was being logged at all.
Root cause (2026-07-25 re-check): the fallback assumption was wrong.
There's no global `CustomLog access.log` in `apache2.conf`; instead
`conf-enabled/other-vhosts-access-log.conf` enables `mod_vhost_combined`,
which was already writing every vhost-without-its-own-`CustomLog`'s
traffic to `/var/log/apache2/other_vhosts_access.log` (5,432 lines,
confirmed real traffic incl. bot scans against `cloud.jayfield.org`).
So requests were never actually un-logged — just commingled in one
shared, harder-to-grep file instead of `access.log`.
Fixed anyway, since a dedicated per-site log remains the better
end state for incident review: added an explicit
`CustomLog ${APACHE_LOG_DIR}/<site>_access.log combined` to every
`<VirtualHost>` block for `dyndns`, `jayfield.org`, `www`, `mail`,
`web`, `cloud`, and `portainer` (the `:80` and `:443`/`le-ssl` blocks
of each site share one log file). Configs backed up to
`/root/removed-configs-backup/vhost-customlog-20260725203959/`.
`/etc/logrotate.d/apache2` already globs `*.log`, so no logrotate
change needed. Validated with `apache2ctl configtest`, applied via
`systemctl reload apache2`, verified live with `curl` against all 7
domains and confirmed each new `<site>_access.log` recorded the hit.
- [x] **OS command injection in the dyndns update scripts** — done 2026-07-20
`/var/www/dyndns/nsupdate.php`, `nsupdate_ipv4.php`, and