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.
4.6 KiB
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
- Login-Versuche pro Quelle/Zeitfenster sind begrenzt und konfigurierbar: IMAP/POP3, durch Pflichtprüfung 1+2 belegt.
- SMTP-Annahmerate pro Absender/Quelle ist begrenzt und konfigurierbar: SMTP, durch Pflichtprüfung 1+2 belegt.
- Ü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.