General Firewall Information
Maybe you don’t really need to use iptables which is very fancy and can be somewhat complex. Maybe you need TCPWrappers which is a lot easier to do simple things like banning certain services or certain hosts on a specific machine.
DenyHosts
More Automatic blacklist via DenyHosts. This helps cut down attempts from known ranges without even giving them the chance even at a slow rate. DenyHost website.
Professor Killian’s Rate Limiting Iptables Rules
So this is my [Chip’s] basic setup:
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 --source 137.0.0.0/8 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -m limit --limit 20/h --limit-burst 5 -j ACCEPT -A INPUT -i lo -j ACCEPT
So I rate-limit the new ssh connections to 20/hour, with a burst of 5. To make sure I can get in during an attack, I whitelist some addresses. Packets on established connections are accepted by the first rule.
Other ssh brute force blocking ideas
Limit incoming SSH attempts to a low number. In my case I limit to 2 connections in 60 seconds. I can tighten it even more but this did a lot to kill brute force attempts.
iptables -I INPUT -p tcp -i vlan1 --dport 2242 -j DROP iptables -I INPUT -p tcp -i vlan1 --dport 2242 -m state --state NEW -m limit --limit 2/min -j ACCEPT iptables -I INPUT -p tcp -i vlan1 --dport 2242 -m state --state RELATED,ESTABLISHED -j ACCEPT
-
Explore "TARPIT" instead of "DROP"
Xed’s Firewall Clearing Script
This script basically takes out any firewall rules and resets network access to be completely unrestricted. One use of this is to put this in a cron job every so often so that while you’re working on sketchy rule changes, you don’t lock yourself out.
#!/bin/bash #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # Written by Chris X Edwards 11.07.28 # Script to clear firewall rules. Use this in a cron job to ensure you # don't lock yourself out while working on rule changes. #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VERBOSE=1 IPTABLES="/sbin/iptables" # iptables path and command function rule_setup { message $FUNCNAME # Try global flush/delete to clear anything already here. $IPTABLES --table filter --flush # Try to get any $IPTABLES --table filter --delete-chain # Try to get any user-def'd # flush any existing rules in built-in chains $IPTABLES --table filter --flush INPUT $IPTABLES --table filter --flush OUTPUT # set default policies $IPTABLES --policy INPUT ACCEPT $IPTABLES --policy OUTPUT ACCEPT $IPTABLES --policy FORWARD ACCEPT return } # end function rule_setup function message { if [ $VERBOSE ]; then echo " + Xed Custom Firewall: Executing $1"; fi } # end function message rule_setup
Deleting A Firewall Rule
To get rid of a rule that is mistakenly added, you can run the same command that added the rule but change the -I to -D. This is useful if you just inserted a rule that, in immediate retrospect, doesn’t make sense.
Added:
iptables -I OUTPUT -m state --state NEW -p tcp -d 10.0.0.111 --dport 636 -j ACCEPT
Ooops:
iptables -D OUTPUT -m state --state NEW -p tcp -d 10.0.0.111 --dport 636 -j ACCEPT
Now it’s gone.
A tougher problem is if there is a rule there that you didn’t put there and you need to weed it out. In this case, it’s often easiest to just delete it by it’s rule number. That brings up the next question of how do you know the rule number. Do this:
iptables -vnL --line-numbers
Then delete the offending rule with something like this:
iptables -D INPUT 1
Careful to get the right rule in the right chain because if you don’t, you can lock yourself out. Ahem…
Xed’s Simple Firewall Rules For Hosts
Here is a template for a simple set of rules that can be deployed to do the normal things done by iptables on a single machine. This includes blocking certain services, rate limiting connection attempts, logging, etc.
#!/bin/bash #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # Simple Single Machine Firewall # Written by Chris X Edwards 11.07.28 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #==========================DEFINITIONS========================== IPTABLES="echo /sbin/iptables" # iptables path and command # ---- DNS DNS1="132.239.0.252" # ns.ucsd.edu DNS2="132.239.1.51" # ns0.ucsd.edu DNS3="128.54.16.2" # ns1.ucsd.edu DNS="${DNS1} ${DNS2} ${DNS3}" # ---- FRIENDS #SSPPS [u-720]skaggs-abagyan-lab VLAN 890 VLAN890="137.110.138.160/27 172.19.138.160/27" # SDSC Abagyan Office VLAN 796 VLAN796="137.110.243.96/27" # SDSC Machine Room VLAN 3252 VLAN3252="169.228.63.60 169.228.63.61 169.228.63.62 169.228.63.63 169.228.63.64" FRIENDS="${VLAN890} ${VLAN796} ${VLAN3252}" function rule_setup { message $FUNCNAME # Try global flush/delete to clear anything already here. $IPTABLES --table filter --flush # Try to get any $IPTABLES --table filter --delete-chain # Try to get any user-def'd # flush any existing rules in built-in chains $IPTABLES --table filter --flush INPUT $IPTABLES --table filter --flush OUTPUT # set default policies $IPTABLES --policy INPUT DROP $IPTABLES --policy OUTPUT DROP return } # end function rule_setup # This controls packets sent to and from firewall itself. function core_rules { # Rules that are a good idea in most cases. message $FUNCNAME # Always allow loopback $IPTABLES -A INPUT --in-interface lo -j ACCEPT $IPTABLES -A OUTPUT --out-interface lo -j ACCEPT # Allow all firewall pings for the moment $IPTABLES -A INPUT --protocol icmp -j ACCEPT $IPTABLES -A OUTPUT --protocol icmp -j ACCEPT # Allow machine to get portage cache with rsync $IPTABLES -A OUTPUT --protocol tcp --dport 873 -j ACCEPT $IPTABLES -A INPUT --protocol tcp ! --syn --sport 873 -j ACCEPT # Allow machine to get and receive DNS for D in DNS do $IPTABLES -A INPUT --protocol tcp ! --syn --src $D --sport domain -j ACCEPT $IPTABLES -A OUTPUT --protocol tcp ! --syn --dst $D --dport domain -j ACCEPT $IPTABLES -A INPUT --protocol udp --src $D --sport domain -j ACCEPT $IPTABLES -A OUTPUT --protocol udp --dst $D --dport domain -j ACCEPT done return } # end function core_rules
Xed’s Firewall Machine Template
Here’s a simple firewall script that will serve as a template for creating a dedicated firewall machine which can arbitrate connections for other machines. The nice thing about this format is that it can be scaled to complex applications in an organized way..
#!/bin/bash #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # Simple Custom Firewall Server Rules # Written by Chris X Edwards 08.12.17 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #==========================DEFINITIONS========================== VERBOSE=1 # Comment this out to hide debugging information IPTABLES="/sbin/iptables" # iptables path and command # ---- DNS DNS1="132.239.0.252" # ns0.ucsd.edu DNS2="128.54.16.2" # ns1.ucsd.edu # ---- FRIENDS XED="10.0.243.108" PRO="10.0.50.3 10.0.50.2 10.0.50.1" FRIENDS="${PRO} ${XED}" function rule_setup { message $FUNCNAME # Try global flush/delete to clear anything already here. $IPTABLES --table filter --flush # Try to get any $IPTABLES --table filter --delete-chain # Try to get any user-def'd # flush any existing rules in built-in chains $IPTABLES --table filter --flush INPUT $IPTABLES --table filter --flush OUTPUT # set default policies $IPTABLES --policy INPUT DROP $IPTABLES --policy OUTPUT DROP return } # end function rule_setup # This controls packets sent to and from firewall itself. function core_rules { # Rules that are a good idea in most cases. message $FUNCNAME # Always allow loopback $IPTABLES -A INPUT --in-interface lo -j ACCEPT $IPTABLES -A OUTPUT --out-interface lo -j ACCEPT # Allow all firewall pings for the moment $IPTABLES -A INPUT --protocol icmp -j ACCEPT $IPTABLES -A OUTPUT --protocol icmp -j ACCEPT # Allow machine to get portage cache with rsync $IPTABLES -A OUTPUT --protocol tcp --dport 873 -j ACCEPT $IPTABLES -A INPUT --protocol tcp ! --syn --sport 873 -j ACCEPT # Allow machine to get and receive DNS $IPTABLES -A INPUT --protocol tcp ! --syn --src $DNS1 --sport domain -j ACCEPT $IPTABLES -A INPUT --protocol tcp ! --syn --src $DNS2 --sport domain -j ACCEPT $IPTABLES -A INPUT --protocol udp --src $DNS1 --sport domain -j ACCEPT $IPTABLES -A INPUT --protocol udp --src $DNS2 --sport domain -j ACCEPT $IPTABLES -A OUTPUT --protocol tcp ! --syn --dst $DNS1 --dport domain -j ACCEPT $IPTABLES -A OUTPUT --protocol tcp ! --syn --dst $DNS2 --dport domain -j ACCEPT $IPTABLES -A OUTPUT --protocol udp --dst $DNS1 --dport domain -j ACCEPT $IPTABLES -A OUTPUT --protocol udp --dst $DNS2 --dport domain -j ACCEPT return } # end function core_rules function special_rules { # Rules that are specific to the mission of this host. message $FUNCNAME # Allow httpd proxy server to access the web ##$IPTABLES -A OUTPUT --protocol tcp --dport 80 -j ACCEPT ##$IPTABLES -A INPUT --protocol tcp ! --syn --sport 80 -j ACCEPT ##$IPTABLES -A OUTPUT --protocol tcp --dport 443 -j ACCEPT ##$IPTABLES -A INPUT --protocol tcp ! --syn --sport 443 -j ACCEPT #Allow a connection to Xed's personal machine for external testing. # Uncomment if other protocols besides ssh are needed. #$IPTABLES -A INPUT --protocol tcp --src $XED -j ACCEPT #$IPTABLES -A OUTPUT --protocol tcp --dst $XED -j ACCEPT #$IPTABLES -A INPUT --protocol udp --src $XED -j ACCEPT #$IPTABLES -A OUTPUT --protocol udp --dst $XED -j ACCEPT return } # end function special_rules function rules_for_friends { if [ $1 ]; then local MACHINE=$1; fi message "$FUNCNAME on $MACHINE" # Allow ssh connections from the machine $IPTABLES -A INPUT --protocol tcp --src ${MACHINE} --dport ssh -j ACCEPT $IPTABLES -A OUTPUT --protocol tcp --dst ${MACHINE} --sport ssh -j ACCEPT $IPTABLES -A INPUT --protocol udp --src ${MACHINE} --dport ssh -j ACCEPT $IPTABLES -A OUTPUT --protocol udp --dst ${MACHINE} --sport ssh -j ACCEPT # Allow this host to ssh to the machine $IPTABLES -A OUTPUT --protocol tcp --dst ${MACHINE} --dport ssh -j ACCEPT $IPTABLES -A INPUT --protocol tcp ! --syn --src ${MACHINE} --sport ssh -j ACCEPT # Allow httpd proxy server access from this machine $IPTABLES -A INPUT --protocol tcp --src ${MACHINE} --dport 8080 -j ACCEPT $IPTABLES -A OUTPUT --protocol tcp ! --syn --dst ${MACHINE} --sport 8080 -j ACCEPT return } # end rules_for_friends # This is a super simple test of basic firewall functionality. # This can be used to troubleshoot firewall problems and to assist # in initial configuration. Once everything proves that it works, # make sure this is disabled by making it false: TEST=false #TEST=true function simple_test_of_rules { message $FUNCNAME # For a simple test, reset the policies to be very permissive $IPTABLES --policy INPUT ACCEPT $IPTABLES --policy OUTPUT ACCEPT #$IPTABLES --policy FORWARD ACCEPT # Test the logging. Ping packets should be logged. #$IPTABLES -A FORWARD --protocol all -j LOG --log-prefix "| FORWARD |" #$IPTABLES -A INPUT --protocol all -j LOG --log-prefix "| I |" #$IPTABLES -A OUTPUT --protocol all -j LOG --log-prefix "| O |" # These test rules exclude SSH so you can test stuff over SSH without # filling up the logs with your own connection. $IPTABLES -A INPUT --protocol tcp --dport ! 22 -j LOG --log-prefix "| I |" $IPTABLES -A OUTPUT --protocol tcp --sport ! 22 -j LOG --log-prefix "| O |" $IPTABLES -A INPUT --protocol udp --dport ! 22 -j LOG --log-prefix "| I |" $IPTABLES -A OUTPUT --protocol udp --sport ! 22 -j LOG --log-prefix "| O |" return } # end function simple_test_of_rules function message { if [ $VERBOSE ]; then echo " + Xed Custom Firewall: Executing $1"; fi } # end function message #==========================MAIN SCRIPT========================== # Clean up built-in rules and set policy rule_setup # Provide a function to do basic testing of iptables functionality if $TEST ; then simple_test_of_rules; exit; fi # Establish rules for this host core_rules special_rules # Set up rules for each FRIEND who needs access for X in $FRIENDS do rules_for_friends $X; done