Skip to content

Instantly share code, notes, and snippets.

@jacopotediosi
Last active February 16, 2024 06:52
Show Gist options
  • Save jacopotediosi/5dcad9c9b90f23935b08c1911f76f3c4 to your computer and use it in GitHub Desktop.
Save jacopotediosi/5dcad9c9b90f23935b08c1911f76f3c4 to your computer and use it in GitHub Desktop.
Block Tor Exit Nodes with Fail2ban

Below is the procedure to automate the ip ban of tor exit nodes with fail2ban.

  1. Install fail2ban:
sudo apt install fail2ban
  1. Create a new fail2ban jail (editing /etc/fail2ban/jail.local):
[tor]
enabled  = true
bantime  = 25h
action   = iptables-allports[name=fail2banTOR, protocol=all]
  1. Create a dummy filter file to /etc/fail2ban/filter.d/tor.conf:
[Definition]
failregex =
ignoreregex =
  1. Adjust fail2ban file limits (create /etc/systemd/system/fail2ban.service.d/limits.conf):
[Service]
LimitNOFILE=2048
  1. Restart systemctl and fail2ban:
sudo systemctl daemon-reload
sudo service fail2ban restart
  1. Create a bash script to download the list of tor exit nodes and add their ips to the fail2ban jail:
#!/bin/bash
set -o nounset -o xtrace -o errexit

IPV4_REGEX='^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$'
IPV6_REGEX='^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$'

banned_ip_counter=0

for ip in $(curl -fsS https://check.torproject.org/torbulkexitlist); do
  if ! [[ $ip =~ $IPV4_REGEX || $ip =~ $IPV6_REGEX ]]; then
      echo "Error: $ip is not a valid IPv4/IPv6 address" >&2
      continue
  fi

  sudo fail2ban-client set "tor" banip "$ip"
  banned_ip_counter="$((banned_ip_counter+1))"
done

if [[ $banned_ip_counter -lt 1 ]]; then
  echo "Error: no IP banned" >&2
fi
  1. Run the script periodically by adding the following lines to crontab -e (install cronic to be notified via email in case of script failure):
MAILTO=mail@example.com
30 6 * * * cronic /etc/fail2ban/block-tor.sh
@psyray
Copy link

psyray commented Jul 1, 2020

20 minutes ... it takes 2 on mine :)
You're right in your case, my gap is a little more restricted.
Anyway thanks for your script ;)

@BrixSat
Copy link

BrixSat commented Nov 17, 2021

Here takes about 34 seconds.

@jacopotediosi
Copy link
Author

Just added more checks to the bash script: regex on ip addresses and improved error messages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment