Using Ipsets to Block Tor Anonymity Network
Besides VPN and SOCKS5 proxies using the Tor anonymity network to scan servers and run brute force attacks is a common choice.
It is especially useful to circumvent rate limiting given that you have easy access to a set of over 1500 IP addresses.
So if you have your own rate limiting implementation make sure to not only limit by IP address but also by targeted user.
Disclaimer: This was just a fun evening project to learn iptable sets. Generally you would want to run a fully fledged firewall with a anonymity database or IPS.
Nevertheless it’s security through obscurity so keep that in mind.
Setup torblock.sh
Ipset uses hash tables to apply actions on a set of IP addresses.
You have to install ipset, dnsutils and wget.
apt install ipset dnsutils wget
The following script gets all tor exit nodes that can reach your server, adds them to a ipset and sets up a iptable rule to reject any incoming connections.
cat << 'EOF' > /root/scripts/torblock.sh
#!/bin/bash
PORTS=(22 80 443 143 993)
# Make sure we are running as root
if [[ "$EUID" -ne 0 ]]; then
echo "Please run as root"
exit 1
fi
if [[ ! -f /etc/debian_version ]]
echo "Only Linux Debian has been tested"
echo "For safety reasons the script will terminate now"
exit 1
fi
WANIP=`dig +short myip.opendns.com @resolver1.opendns.com`
if [[ ! $WANIP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error Wan IP resolving failed"
exit 1
fi
# Cleaning up previous rules
echo "Cleaning up previous rules";
/sbin/iptables -D INPUT -j torblock >/dev/null 2>&1
/sbin/iptables -D FORWARD -j torblock >/dev/null 2>&1
/sbin/iptables -F torblock >/dev/null 2>&1
/sbin/iptables -X torblock >/dev/null 2>&1
/sbin/iptables -F torlognreject >/dev/null 2>&1
/sbin/iptables -X torlognreject >/dev/null 2>&1
/sbin/ipset -F torblockset >/dev/null 2>&1
/sbin/ipset -X torblockset >/dev/null 2>&1
echo "Setting up ipset hash table this can take some time..";
# Create a new set for individual IP addresses
/sbin/ipset -N torblockset iphash
UNEXPECTEDRESULT=false
# IPCOUNT TEMPFILE
TEMPFILE=/tmp/$$.tmp
echo 0 > $TEMPFILE
for PORT in "${PORTS[@]}"
do
# Get a list of Tor exit nodes that can access $WANIP with $PORT, skip the comments and read IP line by line
wget -q -O - "https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=$WANIP&port=$PORT" | sed '/^#/d' | while read IP
do
# Check if ipv4 is valid
if [[ $IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
# Check if IP is NOT already in ipset
if /sbin/ipset test torblockset "$IP" 2>&1 >/dev/null | grep -q "NOT"; then
# Add each IP address to the new set
/sbin/ipset -A torblockset "$IP"
IPCOUNT=$(($(cat $TEMPFILE) + 1))
echo $IPCOUNT > $TEMPFILE
fi
else
UNEXPECTEDRESULT=true
fi
done
done
IPCOUNT=$(($(cat $TEMPFILE)))
unlink $TEMPFILE
if [ "$UNEXPECTEDRESULT" = false ] ; then
# Filter our new set in iptables Prepended to other firewall rules (-I prepend)
# Rejects are logged to /var/log/kern.log
/sbin/iptables -N torblock
/sbin/iptables -N torlognreject
/sbin/iptables -I INPUT -j torblock
/sbin/iptables -I FORWARD -j torblock
/sbin/iptables -A torblock -m set --match-set torblockset src -j torlognreject
/sbin/iptables -A torlognreject -m limit --limit 1/hour --limit-burst 1 -j LOG --log-prefix "IPTABLES_TORBLOCK_REJECTED: " --log-level 4
/sbin/iptables -A torlognreject -j REJECT
echo "Iptables TOR Network REJECT set up";
echo "$IPCOUNT TOR Exit Nodes BLOCKED";
else
echo "Error Unexpected TorBulkExitList result";
fi
EOF
chmod +x /root/scripts/torblock.sh
You should run it every 3 hours via cron.
0 */3 * * * /root/scripts/torblock.sh
@reboot sleep 60 && /root/scripts/torblock.sh
Write a Reply or Comment