1

I am using nginx with cloudflare in front of my sites to protect them from layer 7 attacks but now some attackers found this new way and they are daily attacking my default IP directly with layer 7 attack instead of attacking the sites. I am returning 444 response to them when they open default page on direct ip address but still the attacks are too big so they are making all the site/server unavailable for few minutes and sometime for longer period depending on attack making Nginx busy.

So i wanted to ask if it's possible to disable port 80 access on default ip without affecting my other sites and services? These attacks are too big that that my log file for default vhost is becoming 1GB in less thn 1 hour so even returning 444 isn't working thats why i think blocking it at firewall level will be better?

Any suggestion how to achieve this with iptables?

I am using CentOS 6.9 with Ngiinx 1.13.

Anymore ideas? Still waiting!

Surfer
  • 11
  • 3

1 Answers1

2

You could setup iptables rules to only allow CloudFlare IPs to reach your Nginx instance on port 80 etc. This can be achieved by first creating an ipset with a list of CloudFlare's IPv4 ranges (available at https://www.cloudflare.com/ips-v4), then applying the appropriate iptables rules to utilise the set.

Something like the below should work:

ipset -N cloudflare nethash

ipset -q -A cloudflare A.B.C.D/M
... [ repeat above for each entry in CF ips-v4 file ]

iptables -A INPUT -p tcp --dport 80 -m set --match-set cloudflare src -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j DROP

Further Nginx Trick using the CloudFlare Ray-ID Header

For each site that does have CloudFlare in front of it, you can also apply this trick into Nginx. It effectively checks for the existence of the CloudFlare CF-Ray header, in the expected format. If this does NOT exist, 444 is returned (an immediate drop of the request).

server {
    listen A.B.C.D:80;
    server_name _;
    if ($http_cf_ray !~ '^[0-9a-f]{16}-[A-Z]{3}$') { return 444; }
...

I would imagine you could also disable logging at this point to further mitigate any excessive log noise (untested):

    if ($http_cf_ray !~ '^[0-9a-f]{16}-[A-Z]{3}$') { access_log off; error_log off; return 444; }
parkamark
  • 1,118
  • 6
  • 11
  • Actually not all the sites hosted on this server are protected by cloudflare. Other siets are safe the attack was first on one site which is now protected by cloudflare (attack happened before protection) and after moving to cloudflare now attack is directly on the default server ip address. So i was thinking if somehow i can block access to port 80 on default ip without affecting cloudflare and non cloudflare sites so those layer 7 hits on default ip don't reach nginx and make it busy. The attack happens for 4 to 6 hours daily. – Surfer Oct 31 '17 at 13:11
  • Kind of difficult as "they" evidently know the original server IP address. In this case, the only other method is to disable logging on your default Nginx website configuration (which is serving the 444) by adding `access_log off; error_log off;` to the `server` block. – parkamark Oct 31 '17 at 13:17
  • oh ok but disabling logging will decrease the load on nginx? I just want some way which makes nginx available instead of becoming so busy during attacks that makes all the sites and services available on the site unavailable to new connections. – Surfer Oct 31 '17 at 13:34
  • Disabling logging will help somewhat but if the attack becomes large enough, it will still not help you. The issue is that the original server IP address is known, thus any attack can be made against it. The best solution here is to place all sites behind CloudFlare, and then lock down port 80 using the iptables suggestion I've made above. This will make the server totally unresponsive to any and all HTTP requests that are NOT initially routed through CloudFlare. This is an ALL or NOTHING solution, there is no other way around it. – parkamark Oct 31 '17 at 13:39
  • Ok i will disable the logging and see the results. Actually my host is able to handle all type of ddos attacks syn/tcp flood etc so no issue for me even if the real ip is exposed but only layer 7 is something they are unable to handle. These attacking guys use those cloudflare revolver tools to easily get the real ip of sites and attack them. – Surfer Oct 31 '17 at 13:46
  • Can I create a script that checks the ips and add them to ipset again? or is there a problem if I add two ips twice? – Freedo Mar 30 '20 at 09:40
  • @Freedo You can use `ipset -!` which will ignore errors. You can also use `ipset -o save list ` and filter for lines beginning with `add` and then use this data in a Python script to perform a set difference between the entries that CloudFlare are reporting on their site and the entries that already exist in your ipset. Then run `ipset -! add ` and `ipset -! del ` to add/remove network/mask entries to adjust the set so it aligns with the list sourced from CloudFlare, and then have all this scheduled in a daily cronjob. That's how I've done it. – parkamark Mar 30 '20 at 20:54