본문 바로가기
Q&A해결2026년 8월 1일1분 읽기

express-rate-limit을 켰더니 특정 시간대에 정상 사용자까지 다 429가 뜹니다

r
ratelimit_jaewon
조회 783댓글 2

로그인 API에 무차별 대입 막으려고 express-rate-limit 붙였어요. IP당 15분에 100회로 넉넉하게 잡았는데, 트래픽 몰리는 시간대가 되면 멀쩡한 사용자들까지 429 Too Many Requests를 뱉습니다.

구성은 사용자 → Cloudflare → Nginx 리버스 프록시 → Node(Express) 이렇게 돼 있어요. 로그를 보니 rate limit이 세는 IP가 죄다 우리 Nginx 내부 IP 하나로 찍혀 있더라고요.

그러니까 전 세계 사용자가 전부 같은 카운터를 공유해서 순식간에 100회를 넘겨버리는 상황인 것 같습니다. 실제 클라이언트 IP로 세게 하려면 어떻게 설정하나요?

댓글 2

김김영삼3개월 전
바로 그거예요. 리버스 프록시 뒤에 있으면 Express 입장에서 req.socket.remoteAddress는 항상 Nginx의 IP라, rate limiter가 모든 사용자를 한 IP로 묶어서 세고 있는 겁니다. 그래서 트래픽 조금만 몰려도 다 같이 429를 맞아요.

핵심은 실제 클라이언트 IP를 X-Forwarded-For 헤더에서 읽게 하는 건데, Express한테 프록시를 신뢰하라고 알려줘야 합니다. app.set('trust proxy', ...)를 설정하면 req.ip가 remoteAddress 대신 X-Forwarded-For를 파싱한 실제 클라이언트 IP를 돌려주고, express-rate-limit은 기본적으로 req.ip로 키를 잡으니 그때부터 사용자별로 제대로 세집니다.

다만 여기서 흔히 하는 실수가 app.set('trust proxy', true)로 전부 믿어버리는 거예요. 그러면 아무나 X-Forwarded-For 헤더를 위조해서 rate limit을 우회하거나 남의 IP로 위장할 수 있습니다. 신뢰할 프록시 홉 수만큼만 믿게 숫자로 주세요. 예를 들어 Nginx가 바로 앞이면 app.set('trust proxy', 1) 처럼 홉 수를 지정하거나, 신뢰하는 프록시 IP 대역을 직접 지정하는 방식이 안전합니다.

확인은 간단해요. 설정 후 아무 라우트에서 req.ip를 찍어보세요. 진짜 클라이언트 IP가 나오면 성공입니다. Nginx 쪽도 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 가 들어가 있는지 같이 확인하시고요. 그리고 Cloudflare가 맨 앞이면 원본 IP는 CF-Connecting-IP 헤더에 있으니, 정밀하게 하려면 keyGenerator에서 그 헤더를 우선으로 읽게 커스텀하는 것도 방법이에요.

하나 더: 최신 express-rate-limit은 trust proxy가 true(전부 신뢰)면 위험하다고 startup에서 경고나 에러를 냅니다. 그 메시지가 뜨면 지금 이 문제라는 신호예요.
rratelimit_jaewon(guest)3개월 전
trust proxy를 홉 수로 지정하니 req.ip에 진짜 IP가 찍히고 429도 사라졌습니다. true로 다 믿으면 위험하다는 것도 몰랐네요. 정말 감사합니다 🙏
Ctrl+Enter로 등록