← 전체 글로 돌아가기

서버 운영

Reverse Proxy Note: Keeping the Real Client IP

A server configuration note on client IPs, trusted proxies, and rate limits.

Every login looked like localhost

After adding login rate limits, every user appeared as 127.0.0.1 in the application log. Nginx was forwarding requests to the local Node process. The tempting fix was to trust every forwarded header, but a public client can forge one.

Pass headers and limit trust

Nginx can append the source address while the app trusts only the local proxy.

location / {
  proxy_pass http://127.0.0.1:3000;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
}
app.set("trust proxy", "loopback");

I chose loopback rather than true because only local Nginx should be able to assert this information. I also checked that port 3000 was not exposed publicly.

sudo ss -ltnp | grep :3000
sudo ufw status numbered

Verification notes

  • Confirm the app port is private.
  • Log the parsed address during a real request.
  • Decide which proxy hop is trusted.
  • Confirm HTTPS forwarding matches the public scheme.

Client IP is an authorization input for many rate limiters. It deserves a defined trust boundary.