Nov 032010
 

Firewall

On the web there are plenty of guides related to iptables, the firewall included in all the latest Linux distributions.

iptables is a user space application program that allows a system administrator to configure the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores. Different kernel modules and programs are currently used for different protocols; iptables applies to IPv4, ip6tables to IPv6, arptables to ARP, and ebtables as a special for Ethernet frames.



Iptables requires elevated privileges to operate and must be executed by user root, otherwise it fails to function. On most Linux systems, iptables is installed as /usr/sbin/iptables and documented in its man page, which can be opened using `man iptables` when installed.

For a basic guide to iptables, I suggest the excellent Ubuntu guide: https://help.ubuntu.com/community/IptablesHowTo

In this article I will try to show some unusual use of the command.

Task 1 Block known dirty hosts from reaching your machine

wget -qO - http://infiltrated.net/blacklisted|awk '!/#|[a-z]/&&/./{print "iptables -A INPUT -s "$1" -j DROP"}'

Blacklisted is a compiled list of all known dirty hosts (botnets, spammers, bruteforcers, etc.) which is updated on an hourly basis. This command will get the list and create the rules for you, if you want them automatically blocked, append |sh to the end of the command line. It’s a more practical solution to block all and allow in specifics however, there are many who don’t or can’t do this which is where this script will come in handy.

Task 2 unlock a determined port, once someone “knock”

knock < host > 3000 4000 5000 && ssh -p

user@host && knock < host > 5000 4000 3000

In this example, you do not see the direct use of iptables, but iptables is used in the configuration file of knockd, You have to install knockd.

See example config file below for sshd (port 22).

[options]

logfile = /var/log/knockd.log

[openSSH]

sequence = 3000,4000,5000

seq_timeout = 5

command = /sbin/iptables -A INPUT -i eth0 -s %IP% -p tcp --dport 22 -j ACCEPT

tcpflags = syn

[closeSSH]

sequence = 5000,4000,3000

seq_timeout = 5

command = /sbin/iptables -D INPUT -i eth0 -s %IP% -p tcp --dport 22 -j ACCEPT

tcpflags = syn

Task 3 Redirect an high port to port 80

iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 9001

This is really useful when you want to give to a normal user the possibility to run a daemon on an high port, but show that service on a standard port. In this example you can give to a normal user the start/stop of an apache that listen to port 9001 and show his website on port 80.

Task 4 use your proxy only for IP not in the local LAN

iptables -t nat -A OUTPUT -d ! 10.0.0.0/8 -p tcp --dport 80 -j DNAT --to-destination 10.1.1.123:3128

Replace 10.0.0.0/8 with your largest local subnet. replace 10.1.1.123:3128 with your proxy information.. Note this only works with a proxy server configured for passive setup..

Now your firefox transparently proxy’s stuff destined outside your network.. and Doesn’t proxy stuff inside your network. as well as all your other favorite web applications. curl, wget.

Task 5 – Limit to 10 the number of ssh connections

/sbin/iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 10 -j REJECT

With this command you can limit the number of access to a determinate port, it can be useful also to limit the number of connections toward a port of Apache:

Task 6 – Limit ssh to have just 1 session every 15 seconds

iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP

iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT

These two rules makes iptables require 15 seconds between new connections from the same IP on port 22 (the SSH port). Use ACCEPT instead if you are using a firewall that has it’s own rule for accepting ssh.

Task 7 – Give multiple directive with 1 command

iptables -A INPUT -p tcp -m multiport --dports 22,80,143,6000:6003 -j ACCEPT

The Multiport extension allows you to specify multiple ports and ranges and makes it possible to create complex rules in one line
The multiport directive saves you a lot of lines to maintain and requires less system processing.

Popular Posts:

flattr this!

  8 Responses to “7 Uncommon uses of Iptables”

  1. The black list isn’t that comprehensive, because most of the spam still gets through. Having a script that puts each IP address in its own command, instead of using the comma separator makes iptables unnecessarily long. Analyzing a month worth of data only provides 2 unique matches against this list on port 25. Checking all incoming traffic only has about 18 unique matches in a month.
    iptables –list
    now takes a crazy amount of time because we didn’t list at least 5 ip’s per line
    iptables.save is now 30000+ lines long because of above.

    script doesn’t integrate well with an existing rules set.
    If this could be worked into an integrated script/process and then use cron to download it once an hour that would be awesome.

  2. the firewall starting using 100% of the cpu and my bandwidth dropped in half with 3ghz of cpu processing power. Doesn’t anybody verify these tips are good idea before sharing them with others.

  3. The listed usages are not “uncommon”.

    • Thanks forr the visit,
      And well the “common” use it’s, for me, the plain firewall usage that most of the people do of Iptables…wait no, most of the people don’t even use it ;)

      Bye

  4. […] Have you ever wanted to block brute force attacks, blacklist IP addresses, send “knocks” to open secret ports on your server, reroute port 9001 to 80, limit the number of connections to a port, or limit the amount of time a port is open? Iptables can do all of this and more. […]

  5. I was really motivated by your blacklist example. ipset(8) is really fast in comparison to blocking individual IP CIDRs or IP addresses. Here are my iptables rules for working with the ipset:
    iptables –new-chain BLACKLISTLOG
    # create the ipset so the below iptables rules work
    ipset create -exist BLACKLIST_DROP hash:ip 2>/dev/null
    # ensure no incoming packets are in the hash:ip space
    iptables –append INPUT –in-interface $IN –match set –match-set BLACKLIST_DROP src –jump BLACKLISTLOG
    iptables –append BLACKLISTLOG –match limit –limit 1/s –jump LOG –log-prefix “[BLACKLIST] ”
    iptables –append BLACKLISTLOG –jump DROP
    Here is my cron script to create the BLACKLIST_DROP ipset … it installs the blacklist above in about 60 seconds
    on my firewall:
    // —- start installIpsetFromNet.sh
    #!/bin/bash
    ###############################################################################
    # File:
    #
    # Description:
    #
    # History:
    # Brian Micek – March 2012
    ###############################################################################

    readonly ME=$( basename $0 )

    # —————————————————————————–
    # – help() – prints help
    # —————————————————————————–
    function help() {
    cat – <<EOF
    $ME $ME
    NAME
    $ME – Installs an ipset(8) address space in your kernel for iptables(8)

    SYNOPSIS
    $ME list-URL kernel-list-name [hash:net|hash:ip]

    TYPICAL USAGE
    $ME "http://www.ipdeny.com/ipblocks/data/countries/us.zone&quot; \\
    "us_cidrs" hash:net

    DESCRIPTION
    This bash script installs an ipset(8) IP address space in your kernel. The
    purpose of an ipset address space is to discriminate (typically incoming)
    IP packets against the list for ACCEPT, REJECT or DROP dispositions

    OPTIONS
    None

    NOTES:
    Logging by this program is sent to syslog(8) and also stderr.
    $ME $ME
    EOF
    }
    # —————————————————————————–
    # – log() – delivers log messages to stderr and syslogd
    # —————————————————————————–
    function log() { #<– variable arguments for logging
    logger -s -t $ME $@
    }

    # —————————————————————————–
    # – getList() – gets an IP or CIDR list from the net
    # —————————————————————————–
    function getList() { #<– 1 argument of URL
    log Fetching and parsing $@
    wget -qO – $@ |
    awk -F "." '/^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/ {
    if ( NF == 4 ) {
    for ( i = 1; i = 1 ) {
    if ( ar[ 1 ] 255 ) {
    next
    }
    }
    if ( n >= 2 ) {
    if ( ar[ 2 ] 32 ) {
    next
    }
    }
    }
    print
    }
    }’
    }

    # —————————————————————————–
    # – appendList() – Inserts rules into the custom chain to accept and log
    # – the candidate IP address
    # —————————————————————————–
    function appendList() { #<– 2 arguments, list-name, cidr
    local listname=$1
    local cidr=$2
    ipset add -exist $listname $cidr
    return $?
    }
    # —————————————————————————–
    # – addList() – Reads records from stdin and add them to the ipset IP space
    # —————————————————————————–
    function addList() { #<– 2 args, type and name
    local type=$1
    local name=$2

    readonly TEMP_SET=TEMP_$2
    log Creating temporary ipset $TEMP_SET
    ipset create -exist $TEMP_SET $type
    # in case it already existed, flush it
    ipset flush $TEMP_SET

    local c=0
    # Insert each successful CIDR into iptables. W
    while read cidr
    do
    c=$[ $c + 1 ]
    local v=$[ c % 1000 ]
    if [ $v -eq 0 ]
    then
    log Installed $c rules on $TEMP_SET
    fi
    appendList $TEMP_SET $cidr
    if [ $? -ne 0 ]
    then
    log List append error
    break
    fi
    done
    if [ $c -gt 1 ]
    then
    log Finished, installed $c CIDRs on $TEMP_SET
    log Swapping new list $TEMP_SET with $name
    ipset swap $TEMP_SET $name
    if [ $? -ne 0 ]
    then
    # Probably this is the first time this program was run
    # and the destination does not exist yet.
    log IP set doesnt apprear to exist, renaming
    ipset rename $TEMP_SET $name
    if [ $? -ne 0 ]
    then
    log ERROR ERROR ERROR issuing ipset swap $TEMP_SET $name $type
    # I'm not quite sure what to do here, most likely the
    # new set was created with a differing type
    exit 1
    fi
    else
    # else the swap worked and TEMP_SET now holds old data
    log Flushing old data in $TEMP_SET
    ipset flush $TEMP_SET
    log Deleting old data in $TEMP_SET
    ipset destroy $TEMP_SET
    fi
    else
    # Else we were not able to install any darn rules
    log ERROR did not install any rules destined for $name
    # Leave the old chain intact and flush and delete TEMP_SET
    log Flushing old data in $TEMP_SET
    ipset flush $TEMP_SET
    log Deleting old data in $TEMP_SET
    ipset destroy $TEMP_SET
    fi
    log $( ipset list -terse $name )
    }
    # —————————————————————————–
    # MAIN
    # —————————————————————————–
    # installChain "http://www.ipdeny.com/ipblocks/data/countries/us.zone&quot; "us_cidrs" hash:net
    #
    if [ $# -lt 2 ]
    then
    help
    exit 1
    elif [ $# -eq 2 ]
    then
    type="hash:net"
    else
    type=$3
    fi
    case "$type" in
    "hash:net") ;;
    "hash:ip") ;;
    *) help ;;
    esac
    url="$1"
    name="$2"
    start=$( date +%s )
    installChain $type $url $name
    stop=$( date +%s )
    delta=$[ $stop – $start ]
    log Finished, took $delta seconds for $name

    // —- end installIpsetFromNet.sh

    Now in /etc/cron.daily, something like this will update the blacklist every night
    installIpsetFromNet.sh http://infiltrated.net/blacklisted BLACKLIST_DROP hash:ip

  6. I’m sorry about the indentation, whitespace was stripped from my upload

    • No problem.
      And thanks for the feedback, i’m thinking to use it for anothet article ;-)

 Leave a Reply

(required)

(required)


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>