Changeset c88783e in Klonkt


Ignore:
Timestamp:
06/11/2026 12:08:23 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
b5bae24
Parents:
353c39c
Message:

fix: rate limiter crash behind Cloudflare/Caddy (req.ip with port)

express-rate-limit v7 validates req.ip and throws ERR_ERL_INVALID_IP_ADDRESS
when the IP contains a port (e.g. "104.23.170.162:11046" via the proxy chain).
Uncaught async -> process crashes -> pm2 restart loop -> EADDRINUSE on :3000.

Fix: custom keyGenerator (clientKey) that strips a trailing IPv4 port + falls
back to the socket, and validate:{ip:false} on both limiters so a non-standard
IP format can never crash the process again.

Co-Authored-By: Claude Opus 4.8 <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/middleware/rate-limit.js

    r353c39c rc88783e  
    1313import rateLimit from 'express-rate-limit';
    1414import { renderPage } from './render.js';
     15
     16// Achter Cloudflare/Caddy kan req.ip binnenkomen als "1.2.3.4:11046" (IPv4 met
     17// poort). express-rate-limit v7 valideert het IP en gooit anders
     18// ERR_ERL_INVALID_IP_ADDRESS — onafgevangen async → het proces crasht (en pm2
     19// loopt in een restart-loop). Strip een trailing IPv4-poort, val terug op de
     20// socket, en laat IPv6 (meerdere dubbele punten) ongemoeid.
     21function clientKey(req) {
     22  let ip = req.ip || req.socket?.remoteAddress || '';
     23  if (/^\d{1,3}(\.\d{1,3}){3}:\d+$/.test(ip)) ip = ip.split(':')[0];
     24  return ip || 'unknown';
     25}
    1526
    1627function blockedHandler(viewName, bodyClass, friendlyMsg) {
     
    4253  standardHeaders: true,
    4354  legacyHeaders: false,
     55  keyGenerator: clientKey,
     56  validate: { ip: false },
    4457  // Only count failed attempts. Successful logins don't burn the budget.
    4558  skipSuccessfulRequests: true,
     
    5265  standardHeaders: true,
    5366  legacyHeaders: false,
     67  keyGenerator: clientKey,
     68  validate: { ip: false },
    5469  skipSuccessfulRequests: false,   // any attempt counts (registration spam is the concern)
    5570  handler: blockedHandler('pages/auth-register', 'on-special', 'Too many signup attempts.'),
Note: See TracChangeset for help on using the changeset viewer.