In rete ci sono molte guide relative ad iptables, il firewall incluso in tutte le ultime distribuzioni Linux, ma per parlare di iptables bisogna anche comprendere Netfilter.
Netfilter è un componente del kernel del sistema operativo Linux, che permette l’intercettazione e manipolazione dei pacchetti che attraversano il computer. Netfilter permette di realizzare alcune funzionalità di rete avanzate come la realizzazione di firewall basata sul filtraggio stateful dei pacchetti o configurazioni anche complesse di NAT, un sistema di traduzione automatica degli indirizzi IP, tra cui la condivisione di un’unica connessione Internet tra diversi computer di una rete locale, o ancora la manipolazione dei pacchetti in transito.
Per configurare netfilter si usa il programma iptables, che permette di definire le regole per i filtri di rete e il reindirizzamento NAT. Spesso con il termine iptables ci si riferisce all’intera infrastruttura, incluso netfilter.
Per una guida base di iptables vi suggerisco l’ottima guida di Ubuntu: https://help.ubuntu.com/community/IptablesHowTo
In questo articolo proverò a mostravi qualche utilizzo unusuale del comando.
Compito 1 bloccare host compromessi dal raggiungere la vostra macchina
wget -qO - http://infiltrated.net/blacklisted|awk '!/#|[a-z]/&&/./{print "iptables -A INPUT -s "$1" -j DROP"}'
Blacklisted è un elenco compilato di tutti gli host compromessi noti (botnet, spammer, bruteforcers, ecc) che viene aggiornato su base oraria. Questo comando ottiene l’elenco e creare le regole per te, se vuoi li blocca automaticamente, aggiungendo un |sh alla fine della riga di comando. Una soluzione più pratica è quella di bloccare tutti gli host e consentire solo quelli noti, ci sono molti che non hanno o non possono fare questo, e per loro questo script sarà utile.
Compito 2 sbloccare una certa porto dopo che si è bussato
knock < host > 3000 4000 5000 && ssh -p
user@host && knock < host > 5000 4000 3000
In questo esempio non si vede l’utilizzo diretto di iptables, ma iptables si utilizza nel file di configurazione di knockd.
Il requisito è quindi quello di installare knockd.
Ecco un file di configurazione di esempio per sshd (porta 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
Compito 3 Fare una redirezione da una porta alta alla porta 80
iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 9001
Questo è veramente utile quando si vuole dare ad un normale utente la possibilità di eseguire un demone su una porta alta, ma mostrando il servizio su una porta standard. In questo esempio si può dare a un utente normale la possibilità di fare avvio/arresto di un apache che ascolto sulla porta 9.001, mostrando il sito web relativo sulla porta 80.
Compito 4 usare il proxy solo per IP non nella propria rete privata
iptables -t nat -A OUTPUT -d ! 10.0.0.0/8 -p tcp --dport 80 -j DNAT --to-destination 10.1.1.123:3128
Rimpiazzate 10.0.0.0/8 con la vostra rete privata. Rimpiazzate 10.1.1.123:3128 con l’ip del vostro proxy. Attenzione, questo funziona solo per proxy configurati per funzionare con un setup passivo.
Adesso il vostro firefox andrà in maniera trasparente sul vostro proxy, per oggetti fuori dalla vostra rete privata, mentre non lo utilizzerà per tutto ciò che è nella vosta intranet.
Compito 5 – Limitare a 10 il numero di connessioni SSH
/sbin/iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 10 -j REJECT
Con questo codice potete limitare il numero di accessi ad una determinata porta, può essere utile anche per limitare il numero di connessioni verso una certa porta di apache con :
/sbin/iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset
Compito 6 – Limitare ad 1 connessione ogni 15 secondi ssh
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
Queste due regole di iptables richiedono 15 secondi tra le nuove connessioni dallo stesso IP sulla porta 22 (la porta di SSH). Usate ACCEPT se si utilizza un firewall che ha la propria regola per accettare le connessioni ssh.
Compito 7 Dare più direttive con un unico comando
iptables -A INPUT -p tcp -m multiport --dports 22,80,143,6000:6003 -j ACCEPT
Il modulo multiport di iptables vi permette di indicare con un unico comando più porte di destinazione a cui applicare una regola.
Questo permette di avere una manutenzione molto più facile delle nostre configurazioni e meno consumo di CPU.
Popular Posts:
- None Found
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.
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.
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
[…] 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. […]
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" \\
"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" "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
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 😉