1

I am trying to setup HaProxy with DDoS protection rules (rate limiting). However, I think HaProxy is now rate limiting CloudFlare IPs instead of Visitor/Real IPs. (note: my site itself is fine, because I have fixed that in the PHP code of my site) How can I fix that?

My /etc/haproxy/haproxy.cfg

global
      log 127.0.0.1 local0 notice
      maxconn 10000
      user haproxy
      group haproxy
defaults
      log global
      mode http
      option httplog
      option dontlognull
      retries 3
      option redispatch
      timeout http-request 10s
      timeout connect 5000
      timeout client 30s
      timesout server 5000

frontend domain
      bind *:80
      stick-table type ip size 1m expire 10s store gpc0,http_req_rate(10s)
      tcp-request connection track-sc1 src
      tcp-request connection reject if { src_get_gpc0 gt 0 }
      default_backend nginx

backend nginx
      mode http
      stats enable
      stats uri /HIDDEN
      stats realm Strictly\ Private
      stats auth USER:PASSWORD
      balance roundrobin
      option httpclose
      option httpchk HEAD / HTTP/1.1\r\nHost:domainhidden.eu
      acl abuse src_http_req_rate(domain) ge 100
      acl flag_abuser src_inc_gpc0(domain)
      tcp-request content reject if abuse flag_abuser
      server web1 iphere1:80 check
      server web2 iphere2:80 check
      server web3 iphere3:80 check

I have changed the domain, user and password in the config, because otherwise people could get into my website stats :P (domainhidden.eu, USER:PASSWORD and 'iphere')

2 Answers 2

4

Cloudflare puts original IP address in CF-Connecting-IP HTTP header. So in order to distinguish attacker going through CF server from other people going through the same server this header value can be used as key.

Here's configuration that helped for me against someone brute forcing URLs on my site.

frontend www-https
    # ...
    # front-end config details skipped
    # ...

    default_backend www-backend

    # Use General Purpose Couter 0 in SC0 as a global abuse counter
    stick-table type string len 40 size 1m expire 300s store gpc0

    # wait for at most 5 seconds for HTTP headers
    tcp-request inspect-delay 5s
    # use CF-Connecting-IP header as identifier
    tcp-request content track-sc0 hdr(CF-Connecting-IP)

    tcp-request content reject if { sc0_get_gpc0 gt 0 }

backend www-backend
    # ...
    # back-end config details skipped
    # ...

    # prevent new requests for 300 seconds from someone who got more than 10 HTTP errors in 60 seconds
    stick-table type string len 40 size 1m expire 300s store http_err_rate(60s)
    acl abuse sc1_http_err_rate ge 10
    # tell front-end to reject future requests for this address
    # (replace www-https with your front-end name)
    acl flag_abuser sc0_inc_gpc0(www-https) gt 0

    # wait for at most 5 seconds for HTTP headers
    tcp-request inspect-delay 5s
    # use CF-Connecting-IP header as identifier
    tcp-request content track-sc1 hdr(CF-Connecting-IP)
    tcp-request content reject if abuse flag_abuser

In case you want to see HTTP headers in logs add capture directive as following:

    option httplog
    capture request header cf-connecting-ip len 100
    capture request header x-forwarded-for len 100
    log stdout format raw daemon
3

You have to whitelist their IP's from your rate limit =).

https://www.cloudflare.com/ips

So your ACL would be something like (not sure if completely right):

acl rate_whitelist src -f /path/to/whitelist-ips
acl abuse src_http_req_rate(domain) ge 100
acl flag_abuser src_inc_gpc0(domain)
tcp-request content reject if abuse flag_abuser !rate_whitelist

and then your whitelist-ips file will be the list of IP's (I think, not sure if the format is correct):

199.27.128.0/21
173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/12
4
  • But what if someone is attacking via CloudFlare? (layer 7 attack)
    – Calvin
    Jan 15, 2015 at 9:23
  • 3
    Shouldn't CloudFlare stop that? And If not, I don't really see a way you can stop it without affecting everyone going through CloudFlare.
    – Wildex999
    Jan 15, 2015 at 13:12
  • You could look at the ip from X-Forwarded-For in the HTTP header, that CloudFlare should include, and do rate limiting based on that.
    – Wildex999
    Jan 15, 2015 at 15:30
  • Can you give an example with my config how I should apply that header? I have no idea how to do that in HaProxy.
    – Calvin
    Jan 15, 2015 at 15:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .