I ran into a case where a popular website was receiving a large number of undesirable http requests (>20k per second) that the application was unable to reject efficiently with a 400 range status code without adding more web servers.
It was quickly apparent the traffic all originated from single user-Agent that for the purpose of this post we will call ‘BADAGENT’
The first attempt to block this traffic was done using varnish, this worked well but required multiple servers with high end CPU’s to analysis the http headers and drop them - The code used for this is below
1 2 3 |
|
The below was also used to try and block based upon the URL not just the User-Agent to test how flexible this was:
1 2 3 |
|
After reading good reviews about haproxy Performance, I moved to dropping traffic in haproxy and then sending it back into varnish - This dramatically reduced the CPU usage compared to varnish but did have the undesirable effect of having to proxy traffic to a high end port number when sending traffic back into varnish - The code used for this is below
1 2 3 4 5 |
|
I also found it possible to provide a file containing a line separated list of BADAGENTS as follows
1 2 3 4 5 |
|
It was also possible to use the above to block on url parameters such as http://domain.com/my_api.php?var1=userbob - We could use the below to block on the url key value pair of ‘userbob’
1 2 3 4 5 |
|
This really stabilised the environment but I really wanted rid of haproxy so using the Solarflare Communications SFC9120 card with the Filter Engine licence It was possible to drop the traffic in the network card before it even hit Linux - This not only saved CPU but also saved bandwith in responding to the http requests. The bandwidth saving was to the tune of > 50TB PCM.
The code used to do this on the card for a User-Agent is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
It is also possible to filter on items within the URL with the below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
This was the ideally solution - there are many more possible options with the SolarFlare card, full details with more examples can be found in the user guide