How to block TOR exit nodes from accessing your website on Apache and Nginx

If you ever want to block TOR users from your accessing website completely or block them from accessing specific file(s) / location(s) only for any reasons you may have and you’re running Nginx or Apache, hopefully this post can help you with that.

First thing first, the command used here for both Apache and Nginx were designed to be use in cron because TOR ip often change. But make sure that it’s scheduled for 1 hour at minimum to respect those that gives you free service to lookup tor ip =)

Getting a list of TOR IP Addresses

Before anything else we need to get a list of TOR IP Address, and to do that we have two options (but of course feel free to use your own source if you have one):

  • Use TOR Bulk Exit List from Torproject
  • Use an external sites that list TOR IP Address such as from dan.me.uk

Note: dan.me.uk website only allow you to fetch it every 1 hour only (even if you accidentally clicked it), i choose to not link to the ip address url directly because of that reason and so you have to copy the url directly

For example purpose, here i’m going to use the list from dan.me.uk website and i obviously would like to thank him first for providing tor ip list

Blocking TOR on Nginx

I assume that:

  • Nginx is located at /usr/local/nginx
  • The conf directory is at /usr/local/nginx/conf

If you have Nginx at different location make sure to adjust it accordingly

1. Edit your vhost configuration let’s say it’s called mydomain.conf

# Example configuration on blocking tor on Nginx for a specific server block
# /usr/local/nginx/conf/mydomain.conf

server {

	[...] # your access_log, error_log, etc

	# include tor ip list for a whole vhost
	include tor-ip.conf;

	location / {
		[...] # root configuration
	}

}

# And here's an example if you want to block it for specific location / file only

server {

	[...] # your access_log, error_log, etc

	location ~ "/no-tor-allowed/" {
		# include tor ip list for this location
		include tor-ip.conf;
	}

	location / {
		[...] # root other configuration
	}

}

But don’t go reloading your nginx configuration just yet

2. Downloading the ip list and automatically reload nginx

# run this command once before putting it in cron, but make sure to adjust the path in the command below to match your nginx location
# the output file is /usr/local/nginx/conf/tor-ip.conf

wget -q https://www.dan.me.uk/torlist/ -O - | sed "s/^/deny /g; s/$/;/g" > /usr/local/nginx/conf/tor-ip.conf; /usr/local/nginx/sbin/nginx -s reload

And done for the Nginx part

Blocking TOR on Apache

Depending on whether you have access to your Apache configuration file or not, the configuration will be different. But i’ll cover them both just in case you don’t have access to Apache configuration file and only have access to .htaccess file. Although it’s not recommended to be used in htaccess but for completion’s sake, i might as well include it :).

If you have access to Apache configuration

The steps are pretty much the same like Nginx with the only difference is the location and the syntax of the block directive, anyway:

I assume that:

  • Apache is at /usr/local/apache
  • The conf file is at /usr/local/apache/conf

If you have Apache at different location make sure to adjust it accordingly

1. Open your vhost configuration file (if you put your vhost configuration file in httpd.conf then edit that file) and then locate your desired virtualhost (e.g mydomain.com)

# Example configuration on blocking tor on Apache for a specific virtualhost block
<VirtualHost 1.2.3.4:80>

	[...] # other stuff such as server name and so on

	# Adjust the directory if you want to block tor for specific directory only
	# The example below will block access from TOR users completely
	<Directory />
		# Include tor ip
		Include conf/tor-ip.conf
	</Directory>

	# Or you can also use location directive
	# in this example TOR users is not allowed to visit /no-tor-allowed url and its contents
	<Location /no-tor-allowed>
		# Include tor ip
		Include conf/tor-ip.conf
	</Location>

	# Or use this to block specific file only
	<Files my-files.html>
		# Include tor ip
		Include conf/tor-ip.conf
	</Files>

</VirtualHost>

But don’t restart Apache just yet or else it’ll fail

2. Downloading the ip list and automatically restart Apache

If you’re running Apache 2.2 and below

# Run this once before putting it in cron, but make sure to adjust the path before running it
# This will save the output tor ip to /usr/local/apache/conf/tor-ip.conf

wget -q https://www.dan.me.uk/torlist/ -O - | sed 's/^/deny from /g' > /usr/local/apache/conf/tor-ip.conf; /usr/local/apache/bin/apachectl graceful

If you’re running Apache 2.4

# Run this once before putting it in cron, but make sure to adjust the path before running it
# This will save the output tor ip to /usr/local/apache/conf/tor-ip.conf

wget -q https://www.dan.me.uk/torlist/ -O - | sed "s/^/Require not ip /g; 1i\<RequireAll\>\nRequire all granted" | sed '$a\<\/RequireAll\>' > /usr/local/apache/conf/tor-ip.conf; /usr/local/apache/bin/apachectl graceful

Note: Actually as long as you have mod_access_compat compiled into Apache 2.4 (if i remember it correctly it’s included by default if you compile Apache yourself) you can still use the old allow deny directives but for future proof using Require would be better

If you only have access to .htaccess file

You are still able to use this but make sure to change /your/www/directory/.htaccess into the full path to your .htaccess file but please note that i’m not sure about the performance penalty for blocking many ip addresses in a .htaccess file

If you’re on Apache 2.2 and below

# Note: This will append new lines to your .htaccess file and will block all access from TOR ips to all section of your site by default
# If you need to block for specific file, you need to modify the command below
# Also make sure to backup your .htaccess file first and adjust the path to point to your .htaccess file

# Run this once before putting it in cron if you have ssh access
# otherwise put it in cron directly but make sure to set a minimum of 1 hour

sed -i '/#\ REAPER-TOR/,/#\ END-REAPER-TOR/d' /your/www/directory/.htaccess; wget -q https://www.dan.me.uk/torlist/ -O - | sed "s/^/deny from /g; 1i# REAPER-TOR" | sed '$a# END-REAPER-TOR' >> /your/www/directory/.htaccess

If you’re on CPanel Shared Hosting there’s a high chance that you’re on Apache 2.2

If you’re on Apache 2.4

# Note: This will append new lines to your .htaccess file and will block all access from TOR ips to all section of your site by default
# If you need to block for specific file, you need to modify the command below
# Also make sure to backup your .htaccess file first and adjust the path to point to your .htaccess file

# Run this once before putting it in cron if you have ssh access
# otherwise put it in cron directly but make sure to set a minimum of 1 hour

sed -i '/#\ REAPER-TOR/,/#\ END-REAPER-TOR/d' /your/www/directory/.htaccess; wget -q https://www.dan.me.uk/torlist/ -O - | sed "s/^/Require not ip /g; 1i#\ REAPER-TOR\n\<RequireAll\>\nRequire all granted" | sed '$a\<\/RequireAll\>\n# END-REAPER-TOR' >> /your/www/directory/.htaccess

And that’s it

Comment?

Note: Comment may not appear right away.

4 comments on “How to block TOR exit nodes from accessing your website on Apache and Nginx

  1. You are actually blocking all tor relays with this move. Not only the exit nodes.

    dan.co.uk include all the nodes, just not the exit ones, this means people that run a non-exit relay from home wont be able to browse your site from their home ip.

    I would love to see a solution that i could use for my clients instead of using dan.co.uk, but thx for posting this. should be plenty for most.

  2. If you aren’t blocking bridge relays, you’re not blocking Tor at all. And don’t forget about Obsfproxy bridges, even China hasn’t figured those out yet.

    1. Ah i think you’re getting the wrong idea here, this post is about blocking Tor exit nodes from accessing your site (or restricting them) not blocking them from accessing Tor nodes :)