Nginx – reject X-Forwarded-For IP from nginx/iptables

fail2bannginx

infra is the following


visitor --> Cloudflare proxy --> Front --> Back
                                ^^^^^^
                    -->iptables(fail2ban)-->nginx-->

What I want to do is track a bruteforcing IP via 401 rejects and ban this IP to make any subsequent request.


   FE                    BE
    |                     |
..  |                     |
    |  POST /oauth/token  |
    |-------------------->|
    | 401 (access denied) |
    |<--------------------|
..  |                     |
    |                     |

However, the only incoming address on FE is the cloudflare's IP and not the visitor's IP.
Thus I can't ban the incoming IP via iptable.

I only see two ways:

  1. Configure nginx to use the X-Forwarded-For (or CF-Connecting-IP addionnally given by cloudflare), coupled with the evaluation of 401 response plus a limit_req (is this feasible? How?)
  2. Instead of jailing the detected bruteforcingIP via fail2ban, map it to a banned ip (e.g 140.1.1.1 or whatever IP in africa) and reject the http traffic via a Deny directive on nginx.

Are one of the latters feasible? If no, any alternative?

Best Answer

As the TCP Session get's terminated on Cloudflare's servers, that means you can't ban your clients directly or easily with iptables, except if you're going all the trouble to ban with iptables searching for strings like in here: Iptables rule to block all web requests to domain.com.

Even in that case, some requests from client will be cached from cloudflare, after all it's one of the reasons to use a CDN, so you won't even see the request coming.

What you can do is to do the match on nginx based on the X-Forwarded-For content and apply rate limiting to that, for more details check this answer:

nginx rate limiting with X-Forwarded-For header