Caddy L4 cannot close non-SMTP probes on 25 and 587 without stalling banner-first clients
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 65/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Domain
- infrastructure
Research direction
Read deploy/k8s/caddy/Caddyfile at lines 30–48 and review plan step 2 of #409. Keep ports 25 and 587 proxying unconditionally rather than adding the proposed data-matcher close routes. Done means banner-first SMTP clients can still reach the backend without waiting for a matching timeout.
Written by the indexing model from the issue text.
Description
The planned Caddy close rules for non-SMTP probes drop every real SMTP client. Step 2 of #409 (@x http and @x tls plus close on 25 and 587) cannot ship as written.
What I measured
A layer4 data matcher before the proxy route makes caddy-l4 read the first bytes of the client before it forwards the connection. A router with a matcher that still needs data skips the matcherless fallback. Real SMTP clients wait for the banner, so no bytes arrive. The 3 s matching_timeout hits, and the server closes the connection instead of proxying it.
I built Caddy v2.11.7 with github.com/mholt/caddy-l4 and ran the planned config in front of a banner-first backend:
:18025 {
@http http
@tls tls
route @http @tls {
close
}
route {
proxy 127.0.0.1:18026
}
}
| Client | Result |
|---|---|
| Passive client, waits for the banner (all real SMTP clients) | closed after 3.00 s, no banner |
| HTTP probe | closed immediately |
| TLS probe | closed after 3.00 s |
Pre-greet EHLO (10+ bytes on one line) |
proxied, got the banner |
caddy-l4's RouteList.Compile returns nil on ErrMatchingTimeout (layer4/routes.go). Server.handle closes every connection it returns nil for (layer4/server.go). The matcherless fallback route is skipped while an earlier matcher reports ErrConsumedAllPrefetchedBytes (layer4/routes.go, the len(route.matcherSets) == 0 guard). No ordering saves the connection.
What follows
Keep :25 and :587 proxying unconditionally. The non-SMTP probe cost stays. The app-level guard from this work is what bounds it: per-IP connection limits in Redis, a deny set, and RELAY_PROXY_PROTOCOL_TIMEOUT. If proxy-level filtering is still wanted later, it needs a different tool. CrowdSec with a firewall bouncer, or nginx or HAProxy in front.
side quest: sec @x http/@x tls close routes on 25 and 587 drop every banner-first SMTP client. Cannot be implemented in caddy-l4 as planned. [deploy/k8s/caddy/Caddyfile:L30-L48]
Work reference: codingjoe/relay#409, branch codingjoe-mx-msa-connect-abuse-protection.
- Dominant language
- Python
- Stars
- 4
- Forks
- 0
- Avg merge
- 2h 40m
- Merged PRs (30d)
- 163
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from codingjoe/relay
-
bug side quest
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Maintainers usually reply within 1 day
-
bug side quest
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
bug side quest
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
side quest test
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
side quest test
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
microsoft/agent-lightning#661 ·
Maintainers usually reply within 2 days
-
area/profiles comp/cli P3 type/feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
NousResearch/hermes-agent#146372 ·
Maintainers usually reply within 1 day
-
[BUG] OpenAI-compatible embedding model alias breaks embedder constructionPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 1 day
-
[oblt-aw][autodoc] Document obs-aw-automerge contract and fix automerge doc inconsistenciesPossibly taken @github-actions claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
GeoSeries scale and skew tests fail with pytest 9.2.0Possibly taken @jiayuasu claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day