I was recently working on a little project that essentially was nothing more than a little data collection form, completely open to the web and therefore open to abuse. Within a matter of minutes after publishing it I was hit by the first wave of abuse... Simple, I thought - I'm logging the IP address of the person posting it, I'll just block it.

Ah, stumbling block. They're using the Tor network to anonymise their browsing. While Tor certainly has its uses - in this instance, anybody posting anonymously was almost certainly up to no good. Fortunately, a good man called Daniel Austin has a little tool on his website that has a list of IP addresses from Tor exit nodes.

So, how do we use that to stop these people causing a nuisance? Simple, we use a combination of tools built in to the operating system to regularly obtain the list from Daniel's website and update a htaccess file with the latest IP addresses.

So how do we accomplish this? First of all, you need to create a shell script somewhere within your server that can be executed from cron.

$ touch block-tor.sh

You then need to make this executable.

$ chmod +x block-tor.sh

Once we have done that, we can get down to business. This tutorial assumes you're running a version of Apache, either 2.2 or 2.4.

Apache 2.2

Apache 2.2 uses the 'deny from' syntax which is fairly straight forward. In your block-tor.sh file, copy and paste the below contents in to it:

# Specify path to your htaccess file
HTACCESSPATH=/path/to/.htaccess;

# Remove all lines between & including TOREXITNODES & END-TOREXITNODES
sed -i '/#\ TOREXITNODES/,/#\ END-TOREXITNODES/d' $;

# Retrieve list of Tor exit node IPs and add them to the htaccess file
wget -q https://www.dan.me.uk/torlist/ -O - | sed "s/^/deny from /g; 1i# TOREXITNODES" | sed '$a# END-TOREXITNODES' >> $;

Okay, let me break that down.

First of all, you need to update the HTACCESSPATH variable to the correct location of your .htaccess file.

The second line, looks for the comments: # TOREXITNODES and # END-TOREXITNODES and removes them, and all contents between them if they already exist - ready to add the new ones.

The third line obtains the exit node list from dan.me.uk, loops through each line - prepends it with "deny from " - adds the comment lines mentioned above and then outputs it in to your given .htaccess file.

Simple, right?

Apache 2.4

In Apache 2.4, the syntax has slightly changed. Instead of just passing a single "deny from xx.xx.xx.xx" line, we now need to pass "require not ip xx.xx.xx.xx" - above that we also need to specify "require all granted" which tells the web server to allow all connections, excluding the IPs specified.

In your block-tor.sh file, copy and paste the below contents in to it:

# Specify path to your htaccess file
HTACCESSPATH=/path/to/.htaccess;

# Remove all lines between & including TOREXITNODES & END-TOREXITNODES
sed -i '/#\ TOREXITNODES/,/#\ END-TOREXITNODES/d' $;

# Retrieve list of Tor exit node IPs and add them to the htaccess file
wget -q https://www.dan.me.uk/torlist/ -O - | sed "s/^/Require not ip /g; 1i# TOREXITNODES\n\<RequireAll\>\nRequire all granted" | sed '$a\<\/RequireAll\>\n# END-TOREXITNODES' >> $;

And that's it. Now I recommend you add this shell script to a cronjob to ensure your .htaccess file is kept up-to-date. An example config is:

0 0 * * * block-tor.sh >/dev/null 2>&1

This will run your block-tor.sh script every night at midnight, ensuring you're staying up-to-date with the latest exit node list.

If you have any questions, please comment below!

Cheers!