0

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?

1

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

  • I don't mind if the offender can see cached pages. I just want him not to be able to attempt a lot of auth. I think checking the packet corresponding to the POST verb (some tcp flag) + string comparison is burdersome. As for the match on nginx itself, it does not seem feasible with the limit_req module, so either I have to write a custom nginx plugin or handle that at applicative level on the auth server. As of now I will choose the latter one (because it is straightforward) although I really would prefer the request to be rejected before targetting the backend. Still open for suggestions! – user753642 Nov 14 '16 at 14:03
  • nginx can tcp reject a connection if you specify error 444. – Aaron Nov 14 '16 at 15:10
  • @user753642, updated my answer with a link to another question on how to ratelimit on nginx based on X-Forwarded-For. – Fredi Nov 14 '16 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.