Specs: ufw is in the way of the ACME test, and the rules say so

/etc/ufw/user.rules is world-readable, so this needed no privilege after
all. The default input policy is DROP and 8899 is not among the allowed
ports, so pebble's connection to the suite's listener is dropped. That
matches the live run, where twelve probes from a container completed no
handshake while the same openssl reached pebble's own TLS port.

The nc readings that pointed the other way — instant refusals on closed
ports, where a DROP should hang — are still unexplained, and are left on
the page as unexplained rather than quietly dropped, since they are what
sent an earlier pass through this page in the wrong direction.

Nobody has added the allow rule and re-run the suite, so the fix is
written down as a prediction. The cutover draft says the same: the test
failing here is not evidence that renewal works on the host.
This commit is contained in:
2026-09-19 21:27:40 -07:00
parent 26759a1847
commit 63fe315457
2 changed files with 32 additions and 27 deletions
+26 -22
View File
@@ -122,32 +122,36 @@ them.
all, and the client polls as RFC 8555 section 7.5.1 says to. all, and the client polls as RFC 8555 section 7.5.1 says to.
The suite still doesn't pass here. Half of the reason first recorded on The suite still doesn't pass here. Half of the reason first recorded on
this page is wrong: pebble does validate, and the authorizations do not this page was wrong pebble does validate, and the authorizations do not
stay pending. Whether `ufw` is in the way is still open. Checked on stay pending — and half was right: `ufw` is in the way. Checked on
2026-09-19: 2026-09-19:
- **TCP reaches the host.** From containers on `stalwart-test-acme`, on - **`ufw` does drop it, and the rules say so.** `/etc/ufw/user.rules` is
two different images, `nc` to the host's gateway addresses connects on world-readable, so this needed no privilege in the end.
port 22 and is refused *immediately* on every closed port tried (8899, `DEFAULT_INPUT_POLICY="DROP"`, and the allow-list is 22, 2056, 6667,
9, 14000). A `ufw` DROP would hang until the timeout instead. No 29900, 28910, 13139, 6500 and 2300-2400. **8899 is not on it.** So
firewall rule was read or changed to establish this — `ufw status` while the suite is listening, pebble's connection is dropped, which is
needs a privilege this session doesn't have. what a live run showed: twelve probes from a container completed no
handshake, with or without `-alpn acme-tls/1`, while the same
`openssl` in the same container talks to pebble's own TLS port and
prints its certificate.
**But the network question is not settled, and the probes disagree.** The rule that should fix it, narrowed to the ACME bridge:
`openssl s_client` against the same closed 8899 hung for its full
timeout instead of reporting the refusal `nc` had just seen. Worse,
during a live run — when the suite certainly is listening on 8899, it
takes `with_default_listeners()` — twelve probes from a container
completed no handshake at all, with or without `-alpn acme-tls/1`,
while the same `openssl` connects to pebble's own TLS port from the
same container and prints its certificate.
A listener that is up but unreachable from a container is what a `ufw` ```
DROP looks like; an instant refusal when nothing listens is not. Both sudo ufw allow from 172.21.0.0/16 to any port 8899 proto tcp \
were observed, minutes apart. Settling it needs `sudo ufw status comment 'ACME tests'
verbose`, and a listener bound by hand on `0.0.0.0:8899` to probe ```
against — neither of which this session could do. Until then the
original `ufw` suspicion is neither confirmed nor dismissed. **Unexplained, and left that way:** `nc` from two container images was
refused *immediately* on closed ports 8899, 9 and 14000, where a DROP
should hang until the timeout. That reading is what sent an earlier
pass through this page in the wrong direction. The live-run
observation and the rules agree with each other, so they are what this
entry rests on; the `nc` behaviour is noted rather than explained.
**Not yet retested.** Nobody has added the rule and re-run
`automation_tests`, so "this fixes it" is a prediction.
- **Pebble does validate.** Its log shows 20 validation attempts in the - **Pebble does validate.** Its log shows 20 validation attempts in the
regression run, five for each of `autoconfig`, `autodiscover`, regression run, five for each of `autoconfig`, `autodiscover`,
`mta-sts` and `ua-auto-config.tls.org`, and it then sets each `mta-sts` and `ua-auto-config.tls.org`, and it then sets each
+6 -5
View File
@@ -15,11 +15,12 @@ has to do things nothing has yet asked of it:
- hold INBUXA's ports (25, 465, 587, 143, 993, 110, 995, 443) under load, - hold INBUXA's ports (25, 465, 587, 143, 993, 110, 995, 443) under load,
as an unprivileged user with `CAP_NET_BIND_SERVICE`; as an unprivileged user with `CAP_NET_BIND_SERVICE`;
- keep certificates renewing. ACME renewal was found broken and fixed - keep certificates renewing. ACME renewal was found broken and fixed
(`309835b`), and the remaining test failure is unexplained (`309835b`), and the test that still fails here fails for a reason local
(`container-tests.md`, "What a plain regression leaves failing"). A to this machine: `ufw` drops the port pebble validates against
certificate that fails to renew is a 90-day fuse, not an outage on the (`container-tests.md`). That is not evidence the renewal works on the
day, so it is the first thing to watch and the least likely to announce host, only that the failure isn't the fork's. A certificate that fails to
itself; renew is a 90-day fuse, not an outage on the day, so it is the first thing
to watch and the least likely to announce itself;
- write to a store that the Enterprise build wrote until an hour earlier. - write to a store that the Enterprise build wrote until an hour earlier.
The rehearsal below exists to turn those from assumptions into observations. The rehearsal below exists to turn those from assumptions into observations.