Even the simple websites of the world are often hit with massive attacks. They are at the mercy of their attacker and can’t do anything to help themselves until it is over. I’ve seen it time and time again when users get attacked by a simple Denial of Service attack that could have been prevented by a simple rate limit in the ever popular UFW on Ubuntu 16.04. Follow the steps below to help protect yourself just a little more!

Use the following at your own risk. 45Squared takes no responsibility for any unwanted results from this guide.

Rate Limiting With UFW

This guide is written for Ubuntu 16.04. While it may work for other variants, it is untested.

First let’s login to your web server.

Next, we need to be root. All modifications including starting and stopping UFW must be done either with sudo or just by simply being root.

$ sudo -s

Navigate to the UFW configuration directory

$ cd /etc/ufw/

We are going to be modifying the before.rules file. These are all the rules that happen before any custom rules. There is also an after.rules file that runs rules after any custom entries.

$ nano before.rules

Yes, I use nano. If you like VI or another text editor better, by all means, use it!

We are going to add a few lines directly under the

# End Required Lines section

#CUSTOM UFW
:ufw-http - [0:0] :ufw-http-logdrop - [0:0] # END CUSTOM

Next scroll down and before the last line COMMIT insert the following:
### Start HTTP ###
# Enter rule
-A ufw-before-input -p tcp --dport 80 -j ufw-http
-A ufw-before-input -p tcp --dport 443 -j ufw-http
# Limit connections per Class C
-A ufw-http -p tcp --syn -m connlimit --connlimit-above 50 --connlimit-mask 24 -j ufw-http-logdrop
# Limit connections per IP
-A ufw-http -m state --state NEW -m recent --name conn_per_ip --set
-A ufw-http -m state --state NEW -m recent --name conn_per_ip --update --seconds 10 --hitcount 45 -j ufw-http-logdrop
# Limit packets per IP
-A ufw-http -m recent --name pack_per_ip --set
-A ufw-http -m recent --name pack_per_ip --update --seconds 1 --hitcount 45 -j ufw-http-logdrop
# Finally accept
-A ufw-http -j ACCEPT
# Log
-A ufw-http-logdrop -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW HTTP DROP] "
-A ufw-http-logdrop -j DROP
### END HTTP ###

I’m going to explain a little bit of what is happening with these rules. The general concept of a rate limit is that we are going to allow X number of connections per Y amount of seconds. If X connections have happened within Y seconds all connections will be dropped.

Connections Per IP

A connection is a channel to your server. In this tutorial, we are rate limiting for HTTP requests so these would be channels to your web server. In the example, I am limiting a user to 45 connections per 10 second. This will help stop most attacks while allowing normal functions to happen.

Packets Per IP

This is a little tricky to measure and you may need to tweak this for your use case. A packet is a unit of data that is routed from an origin to a destination. This could be parts of a website or a file. In my example, I am allowing 1 packet for every 45 seconds.

Connections Per Class C

I am going to make the assumption that you know what a Class C network is. In the rules, we are limiting the connections for Class C networks to be 50 simultaneous connections.

This example of Rate Limiting for UFW is very simple. Feel free to customize it to make it do what you want it to do! Please share with us how you utilized this guide and any modifications you may have made!

Connect with 45Squared