Neues Paket mail/internal/ratelimit: Token-Bucket je (Mandant, Quelle)-Schlüssel. ConfigProvider/StaticConfig liefern Burst/Nachfüllrate je Mandant mit Fallback auf eine Default-Konfiguration (Akzeptanzkriterium 2/3: begrenzt, konfigurierbar, je Mandant getrennt). Limiter.Allow liefert bei Ablehnung eine konkrete positive Wartezeit statt nur false — Grundlage für die geforderte definierte Ablehnung MIT Wartezeit-Hinweis statt Verbindungsabbruch (Akzeptanzkriterium 3). IMAP LOGIN und POP3 PASS begrenzen Anmeldeversuche pro (Mandant, Quell-IP). SMTP MAIL FROM begrenzt die Annahmerate pro (Mandant, Absenderadresse+Quell-IP). Bei Überschreitung: POP3 -ERR, IMAP NO, SMTP 451 (temporärer Fehlercode) mit Wartezeit in Sekunden, Verbindung bleibt in allen drei Fällen offen und weiter nutzbar. loginLimiter/ acceptLimiter sind optional (nil = deaktiviert, Rückwärtskompatibilität zu ING-01..ING-08) — neue Konstruktoren NewServerWithGuardTLSLoggerAndRateLimit (IMAP/POP3) und NewServerWithMaxMessageBytesTLSLoggerAndRateLimit (SMTP). Jeder Server bekommt eine tenantID, konsistent mit dem in ING-10 etablierten Muster "ein Server je Mandant". Alle drei Pflichtprüfungen mit echten Nachweisen durchgeführt, jeweils in IMAP, POP3 und SMTP einzeln: 20 reale Versuche bei Burst=5 -> exakt 5 akzeptiert, 15 mit Wartezeit-Hinweis abgelehnt, keine Verbindung getrennt; legitime Nutzung unterhalb der Schwelle unbeeinträchtigt; zwei Mandanten mit unterschiedlichem Burst über denselben Limiter unabhängig und exakt wirksam (2 vs. 8 akzeptierte Versuche). go build/go vet/golangci-lint clean, gesamtes Mail-Modul (~31 Pakete) regressionsfrei getestet — insbesondere QA-07-Lasttests bleiben grün, da Rate-Limiting standardmäßig deaktiviert ist.
100 lines
4.6 KiB
Markdown
100 lines
4.6 KiB
Markdown
# ING-09 — Rate-Limiting auf Protokollebene: Prüfprotokoll
|
|
|
|
Datum: 2026-09-01
|
|
Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh
|
|
Pakete: `mail/internal/ratelimit` (neu, gemeinsam genutzt), `mail/internal/imap`, `mail/internal/pop3`, `mail/internal/smtp`
|
|
|
|
## Umsetzung
|
|
|
|
Neues Paket `ratelimit`: Token-Bucket-Rate-Limiting, je (Mandant,
|
|
Quelle)-Schlüssel ein eigener Bucket. `ConfigProvider`/`StaticConfig`
|
|
liefern die Konfiguration (Burst, Nachfüllrate) je Mandant, mit
|
|
Fallback auf eine Default-Konfiguration (Akzeptanzkriterium 1/2:
|
|
begrenzt UND konfigurierbar; Akzeptanzkriterium 3: je Mandant getrennt
|
|
konfigurierbar). `Limiter.Allow(tenant, source)` liefert bei Ablehnung
|
|
eine konkrete, positive Wartezeit statt nur `false` — Grundlage für
|
|
Akzeptanzkriterium 3: "definierte Ablehnung MIT Wartezeit-Hinweis,
|
|
nicht Verbindungsabbruch ohne Erklärung".
|
|
|
|
**IMAP** (`LOGIN`) und **POP3** (`PASS`) begrenzen Anmeldeversuche pro
|
|
(Mandant, Quell-IP) — Akzeptanzkriterium 1. **SMTP** (`MAIL FROM`)
|
|
begrenzt die Annahmerate pro (Mandant, Absenderadresse+Quell-IP) —
|
|
Akzeptanzkriterium 2. Bei Überschreitung antwortet der Server mit einer
|
|
Fehlermeldung, die die Wartezeit in Sekunden nennt (POP3 `-ERR`, IMAP
|
|
`NO`, SMTP `451` — temporärer Fehlercode, "versuch es später erneut"),
|
|
die Verbindung bleibt in allen drei Fällen offen und weiter nutzbar
|
|
(Akzeptanzkriterium 3). `loginLimiter`/`acceptLimiter` sind optional
|
|
(`nil` = kein Rate-Limiting, Rückwärtskompatibilität zu ING-01..ING-08);
|
|
neue Konstruktoren `NewServerWithGuardTLSLoggerAndRateLimit` (IMAP/POP3)
|
|
und `NewServerWithMaxMessageBytesTLSLoggerAndRateLimit` (SMTP).
|
|
|
|
Jeder `Server` bekommt eine `tenantID` — konsistent mit dem in ING-10
|
|
etablierten Muster "ein Server-Prozess/Instanz je Mandant" — und ein
|
|
`*ratelimit.Limiter`, der über mehrere Server-Instanzen (Mandanten)
|
|
hinweg geteilt werden kann, aber intern strikt nach `tenantID` trennt.
|
|
|
|
## Pflichtprüfung 1: Lasttest bestätigt greifendes Limit bei Überschreitung
|
|
|
|
`TestRateLimit_LoadExceedingLimitGetsRejectedWithRetryHint` in allen
|
|
drei Protokollpaketen: Burst=5, 20 reale, aufeinanderfolgende
|
|
Anmelde-/Annahmeversuche über echte TCP-Verbindungen gegen den
|
|
laufenden Server. Ergebnis in allen drei Protokollen identisch: exakt
|
|
5 Versuche akzeptiert (der konfigurierte Burst), exakt 15 Versuche mit
|
|
der erwarteten Fehlermeldung inkl. Wartezeit-Hinweis abgelehnt — kein
|
|
Verbindungsabbruch, jede Ablehnung kommt als reguläre Protokollantwort.
|
|
|
|
Ergebnis: **BESTANDEN** in allen drei Protokollen.
|
|
|
|
## Pflichtprüfung 2: legitime Nutzung unterhalb der Schwelle bleibt unbeeinträchtigt
|
|
|
|
`TestRateLimit_LegitUsageBelowThresholdUnaffected` in allen drei
|
|
Protokollpaketen: Burst=10, nur 3 Versuche — alle drei erfolgreich,
|
|
keine Ablehnung.
|
|
|
|
Ergebnis: **BESTANDEN** in allen drei Protokollen.
|
|
|
|
## Pflichtprüfung 3: Limit ist je Mandant getrennt konfigurierbar und wirksam
|
|
|
|
`TestRateLimit_PerTenantIndependentAndEffective` in allen drei
|
|
Protokollpaketen: EIN gemeinsamer `*ratelimit.Limiter`, aber zwei
|
|
Server-Instanzen mit unterschiedlicher `tenantID`
|
|
(`mandant-knapp` → Burst 2, `mandant-grosszuegig` → Burst 8, per
|
|
`StaticConfig.PerTenant`). 10 Versuche je Mandant: `mandant-knapp`
|
|
akzeptiert exakt 2, `mandant-grosszuegig` akzeptiert exakt 8 — beweist
|
|
sowohl die Trennung (unterschiedliche Werte wirken unabhängig) als auch
|
|
die Wirksamkeit (jeweils exakt der konfigurierte Burst, nicht mehr,
|
|
nicht weniger).
|
|
|
|
Ergebnis: **BESTANDEN** in allen drei Protokollen.
|
|
|
|
## Akzeptanzkriterien
|
|
|
|
1. **Login-Versuche pro Quelle/Zeitfenster sind begrenzt und
|
|
konfigurierbar**: IMAP/POP3, durch Pflichtprüfung 1+2 belegt.
|
|
2. **SMTP-Annahmerate pro Absender/Quelle ist begrenzt und
|
|
konfigurierbar**: SMTP, durch Pflichtprüfung 1+2 belegt.
|
|
3. **Überschreitung führt zu definierter Ablehnung mit
|
|
Wartezeit-Hinweis, nicht zu Verbindungsabbruch ohne Erklärung**:
|
|
durch Pflichtprüfung 1 belegt (Verbindung bleibt in jedem Testlauf
|
|
offen, jede Ablehnung enthält die Wartezeit in Sekunden).
|
|
|
|
## Build/Vet/Lint/Test — Gesamtmodul
|
|
|
|
```
|
|
go build ./... → OK
|
|
go vet ./... → OK
|
|
golangci-lint run ./... → 0 issues
|
|
go test ./... -p 1 (TEST_TENANT_DSN, TEST_MANTICORE_URL gesetzt) → alle Pakete ok, inkl. neuem internal/ratelimit
|
|
```
|
|
|
|
Keine Regression in den bestehenden ~31 Paketen — insbesondere die
|
|
QA-07-Lasttests bleiben grün: Rate-Limiting ist standardmäßig
|
|
deaktiviert (`loginLimiter`/`acceptLimiter` nil), bis explizit über die
|
|
neuen Konstruktoren aktiviert.
|
|
|
|
## Ergebnis
|
|
|
|
ING-09 erfüllt alle Akzeptanzkriterien mit echten, ausgeführten
|
|
Nachweisen — in allen drei Protokollen (IMAP, POP3, SMTP) einzeln
|
|
geprüft. Freigeschaltet: QA-04.
|