This wiki is archived and useful information is being migrated to the main bzflag.org website
Iptables
This is a collection of notes about modifying your iptables packet filter to add blocking of specific IPs and systems on the Tor network.
Original source: http://doc.norang.ca/iptables.html Copied to wiki with permission from content author.
Contents
Basic Setup[edit]
The following is a basic firewall script that you can load with
iptables-restore <iptables
It allows access to
Port | Service | Notes |
25 | SMTP | Incoming email |
110 | POP3 | POP3 service for email |
53 | DNS | Name server requests |
22 | SSH | Incoming SSH requests |
80 | HTTP | Webserver requests |
443 | HTTPS | Secure HTTP |
4000:5200 | BZFlag Servers | BZFlag server ports |
6000:6200 | BZFlag Servers | More server ports |
Anything else is logged and dropped at the firewall.
The logwatch
package makes nice daily summaries of the firewall logs.
Here is the iptables
file:
# Generated by iptables-save v1.3.6 on Mon Oct 20 14:37:02 2008 *filter :INPUT DROP [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [8574312917:611260898475] -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT -A INPUT -p tcp -m tcp --dport 110 -j ACCEPT -A INPUT -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT -A INPUT -p tcp -m tcp --dport 53 -m state --state NEW -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -m state --state NEW -j ACCEPT -A INPUT -p tcp -m tcp --dport 443 -m state --state NEW -j ACCEPT -A INPUT -p tcp -m tcp --dport 4000:5200 -m state --state NEW -j ACCEPT -A INPUT -p udp -m udp --dport 4000:5200 -m state --state NEW -j ACCEPT -A INPUT -p tcp -m tcp --dport 6000:6200 -m state --state NEW -j ACCEPT -A INPUT -p udp -m udp --dport 6000:6200 -m state --state NEW -j ACCEPT -A INPUT -j LOG -A INPUT -j DROP -A OUTPUT -o lo -j ACCEPT COMMIT # Completed on Mon Oct 20 14:37:02 2008 # Generated by iptables-save v1.3.6 on Mon Oct 20 14:37:02 2008 *mangle :PREROUTING ACCEPT [2345559699:169138998026] :INPUT ACCEPT [2345528243:169135560350] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [9525683538:678126408324] :POSTROUTING ACCEPT [9525683538:678126408324] COMMIT # Completed on Mon Oct 20 14:37:02 2008 # Generated by iptables-save v1.3.6 on Mon Oct 20 14:37:02 2008 *nat :PREROUTING ACCEPT [8235419:506261976] :POSTROUTING ACCEPT [1475984:91496805] :OUTPUT ACCEPT [1475984:91496805] COMMIT # Completed on Mon Oct 20 14:37:02 2008
Tie the rules to the network interface[edit]
In Debian you can automatically run scripts when interfaces are started and stopped. We keep the firewall rules in /etc/iptables
and have the following lines in /etc/network/interfaces
to save and restore the current set of rules across reboots.
/etc/network/interfaces
# The loopback network interface auto lo iface lo inet loopback # The primary network interface iface eth0 inet static address 1.2.3.4 netmask 255.255.255.255 gateway 1.2.3.1 # # iptables up /sbin/iptables-restore -c </etc/iptables down /sbin/iptables-save -c >/etc/iptables #
Custom Chains[edit]
Add custom chains to hold your custom firewall rules. Here we use two new chains TOR_BLOCK
and BLOCK
to keep two separate lists of IPs to be blocked at the firewall.
Adding Chains[edit]
Chains are where you keep your rules. You can add new chains with
iptables -N NEWCHAIN
Blocking Tor Systems[edit]
Here we use a new chain (TOR_BLOCK
) and a script to populate the chain. This automatically keeps the list of IPs to block from the Tor network up to date hourly.
Adding TOR_BLOCK chain to the INPUT chain[edit]
Create your new chain to hold Tor network node IPs to block with
iptables -N TOR_BLOCK
and tie this chain to your input rules with
iptables -I INPUT -j TOR_BLOCK
This jumps from the INPUT
chain to the TOR_BLOCK
chain and then returns to the next rule in the INPUT
after hitting the RETURN
at the end of the TOR_BLOCK
chain.
Populating the TOR_BLOCK chain[edit]
We will populate the TOR_BLOCK
chain automatically using the torblock.fw
script below.
This will empty the TOR_BLOCK chain, add a RETURN to the end of the chain so we can process it like a subroutine and enter each listed Tor network IP into the list.
You can run the torblock.fw
script manually to wipe and populate the TOR_BLOCK
chain. After you're happy with it I add a crontab
entry that updates the list once an hour.
/usr/local/sbin/torblock.fw Script[edit]
#!/bin/bash # A simple bash script to block IP traffic from TOR exit nodes. # written by Andrew Vetlugin (antrew at gmail com) wget='/usr/bin/wget' iptables='/sbin/iptables' #url='https://torstat.xenobite.eu/export/tor_exitnodes.csv' url='http://torstatus.kgprog.com/ip_list_exit.php/Tor_ip_list_EXIT.csv' iptables_target='DROP' #iptables_target='REJECT' # Quick guide: # 1. add a separate chain for a list of TOR exit nodes # (this should be done by hand once) # iptables -N TOR_BLOCK # 2. add a rule to INPUT chain # Note: if you want to be able to connect to any TOR exit node yourself # (e.g., if $url is a exit node you should be able to fetch a list of exit # nodes from it) then you should add this rule AFTER accepting established # and related connections) # iptables -A INPUT -j TOR_BLOCK # 3. add this script to crontab (I think 10-20 minutes interval should be OK) # flush chain $iptables -F TOR_BLOCK # return to parent chain if the source is not TOR exit node $iptables -I TOR_BLOCK -j RETURN # add TOR exit nodes to TOR_BLOCK chain with $iptables_target rule for node in `$wget -q --no-check-certificate -O - $url | sort | uniq`; do $iptables -I TOR_BLOCK -s $node -j $iptables_target done
Crontab Entry[edit]
The following crontab
entry runs the torblock.fw
script. This effectively erases all the Tor network nodes and re-populates the TOR_BLOCK
list hourly.
00 * * * * root /usr/local/sbin/torblock.fw
Manual Blocking Chains[edit]
Now to deal with other problem systems we keep a separate BLOCK
list which we can manually add, list, and remove entries from. The following scripts can be provided to trusted users via sudo
so they can view and manipulate the firewall rules.
Add BLOCK chain[edit]
Add the new chain to hold the IPs to block.
iptables -N BLOCK
Add a single rule to return from the end of the list to the calling chain.
iptables -I BLOCK -j RETURN
and tie this chain to to your input rules.
iptables -I INPUT -j BLOCK
This jumps from the INPUT
chain to the BLOCK
chain and then returns to the next rule in the INPUT
chain after hitting the RETURN
at the end of the BLOCK
chain.
Blocking IPs[edit]
Blocking IPs using the new BLOCK
chain is pretty simple.
usage: sudo block IP sudo block IP/nn sudo block IP 'comment goes here' sudo block IP/nn 'comment goes here'
e.g. sudo block 1.2.3.4 # Adds 1.2.3.4 as the IP to block sudo block 1.2.3.4 'reason for block' # Adds 1.2.3.4 with a comment sudo block 1.2.3.4/24 'block subnet' # Blocks all ips matching 1.2.3.*
Comments are kept in the iptables
chain and are displayed by the blocklist
script below.
Block Script - /usr/local/sbin/block[edit]
#!/bin/sh INPUT="$(echo $1 | sed 's/[^.0-9/]//g')" COMMENT="$2" if [ "x$COMMENT" == "x" ] then iptables -I BLOCK -s $INPUT -j DROP else iptables -I BLOCK -s $INPUT -m comment --comment "$COMMENT" -j DROP fi /usr/local/sbin/blocklist
Unblocking IPs[edit]
To unblock an IP (removing it from the BLOCK
chain) just pass the IP as parameter 1 and the comment (if any) exactly as it was entered when blocking the IP.
usage: sudo unblock IP sudo unblock IP 'comment goes here'
Unblock Script - /usr/local/sbin/unblock[edit]
#!/bin/sh INPUT="$(echo $1 | sed 's/[^.0-9/]//g')" COMMENT="$2" if [ "x$COMMENT" == "x" ] then iptables -D BLOCK -s $INPUT -j DROP else iptables -D BLOCK -s $INPUT -m comment --comment "$COMMENT" -j DROP fi /usr/local/sbin/blocklist
Listing Blocked IPs[edit]
The following script simply displays the entries in the blocklist.
Usage: sudo blocklist
Block List script - /usr/local/sbin/blocklist[edit]
#!/bin/sh iptables -L BLOCK -n
Rate Limiting Connections[edit]
To effectively block script-kiddies that try dictionary attacks on the SSH server port I have the two following rules before the rule that accepts SSH connections
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
This allows up to 3 connections from the same IP in a 60 second period. Any more than that are blocked (and not logged).
Waiting 60 seconds before retrying the connection attempt makes it work again.
Saving and Restoring tables[edit]
I save the current iptables
firewall rules with
/sbin/iptables-save -c >/etc/iptables
These can be restored with the following command
/sbin/iptables-restore -c </etc/iptables
These are normally added to my /etc/network/interfaces
file on Debian when the appropriate network interface is brought up or down.
# Example /etc/network/interfaces entries # The primary network interface iface eth0 inet static address 1.2.3.4 netmask 255.255.255.0 gateway 1.2.3.1 up /sbin/iptables-restore -c </etc/iptables down /sbin/iptables-save -c >/etc/iptables