Skip to content

Instantly share code, notes, and snippets.

@jacopotediosi
Last active October 26, 2024 19:45
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):
[email protected]
30 6 * * * cronic /etc/fail2ban/block-tor.sh
@jacopotediosi
Copy link
Author

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

@simonmanuel
Copy link

Thank you for this script. Using it the way it was originally intended. Malicious TOR traffic has increased exponentially on one of my websites and the 'whack-a-mole' approach with fail2ban wasn't helping. So far, so good.

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