Archivi tag: firewall

CentOS 6: realizzare un network intrusion detection system open source – Parte 1

Premessa

A differenza delle numerose guide cooked e dei vari howto che si possono trovare in rete, questo post (primo di una serie di 3), ha come scopo quello di illustrare in modo esaustivo i vari passi necessari per la realizzazione di una sistema NIDS.

Un po’ di teoria

Esistono diverse metodologie per difendere l’infrastruttura IT dai cyber attacchi, e, tutto sommato, le si può riassumere in 2 macro categorie, ovvero quelle attive e quelli passive. Per strategia difensiva attiva basti pensare ad un firewall, ad un antivirus oppure ad un IPS (Intrusion Preventetion System). Per contro, un tipico esempio di strategia difensiva di tipo passivo è rappresentato dai sistemi IDS (Intrusion Detection System), i quali possono agire localmente sulla macchina interessata (in tal caso parliamo di HIDS, ovvero Host IDS), oppure a livello di rete (in questo caso parliamo di NIDS, ovvero Network IDS).

I sistemi NIDS (detti anche sonde o sensori), non fanno altro che analizzare il traffico del segmento di rete a cui sono collegati (DMZ, LAN, Outside), alla ricerca di eventuali tentativi di attacco.

Solitamente, essi non vengono posizionati inline (come invece avviene per i sistemi IPS), ma sono collegati ad una porta dello switch configurata in mirror (monitor/span), sulla quale viene inoltrata una replica esatta di tutto il traffico passante per lo switch in questione. In questo modo un eventuale sovraccarico del sensore non comporterà automaticamente un rallentamento della rete in termini di throughput.

Topoligia

Poichè la rete sulla quale ho configurato il sistema NIDS è dotata di un firewall *nix che filtra tutto il traffico in ingresso ed in uscita, per questioni di budget e di praticità, ho ritenuto opportuno installare la sonda sulla macchina in questione. Va da se che l’analisi preventiva del carico computazionale a cui era soggetto il firewall ha restituito valori di overhead davvero irrisori, dunque l’installazione della sonda non ha comportato grossi cambiamenti in termini prestazionali.

NIDS

Ingredienti

Il software che fungerà da sensore prende il nome di snort. Inoltre, per aggiornare in modo automatico le signature/pattern degli attacchi verrà utilizzato pulledpork (a tutti gli effetti il successore di oinkmaster), mentre per convertire in formato SQL e salvare gli alert generati da snort all’interno di un DB (MySQL) verrà utilizzato barnyard2. Infine, verrà installata sulla macchina ospite un’interfaccia Web (GUI) scritta in Ruby ed accessibile tramite Apache, dalla quale poter estrapolare gli allarmi con le relative statistiche,  il cui nome è snorby (SNORt ruBY).

Occorre precisare che MySQL (DBMS) ed Apache (server Web) sono già installati sulla macchina ospite.

Installazione e configurazione di snort

Tale attività si divide in 3 step:

1) l’installazione dei software prerequisiti;

2) l’installazione delle librerie daq;

3) l’installazione e la configurazione di snort.

I software prerequisiti sono bison, flex, libpcap e libdnet e li si può installare utilizzando il packet manager di casa CentOS/Red Hat, ovvero yum:

yum install bison flex libpcap libpcap-devel libdnet libdnet-devel

Posizioniamoci nella directory /usr/local/src per poi scaricare, compilare ed installare le librerie daq (le quali servono a reindirizzare il network I/O ai software di “cattura” veri e propri, quali, ad esempio, PCAP, AFPACKET e simili):

wget https://www.snort.org/downloads/snort/daq-2.0.6.tar.gz
tar -xvf daq-2.0.6.tar.gz
cd daq-2.0.6
./configure
make
make install
ldconfig
cd ..

A questo punto possiamo scaricare ed installare snort:

wget https://www.snort.org/downloads/snort/snort-2.9.7.5.tar.gz
tar -xvf snort-2.9.7.5.tar.gz
cd snort-2.9.7.5
./configure
make
make install

Ad installazione completata creiamo utente e gruppo per il suddetto applicativo:

groupadd snort
useradd snort -g snort -s /sbin/nologin

per poi creare la directory su cui salvare i file di configurazione e le regole per la rilevazione delle intrusioni:

mkdir -p /etc/snort
mkdir -p /etc/snort/rules
cd etc
cp -R * /etc/snort
cd ..

Inoltre, scarichiamo le regole vere e proprie e salviamole all’interno della dir /etc/snort/rules:

wget https://www.snort.org/downloads/community/community-rules.tar.gz
tar -xvf community-rules.tar.gz
cd community-rules
cp * /etc/snort/rules
wget https://www.snort.org/downloads/registered/snortrules-snapshot-2975.tar.gz?oinkcode=<vostro oinkcode ricavabile dalla pagina Web di snort, previa registrazione>
tar -xvf nortrules-snapshot-2975.tar.gz
cd snortrules-snapshot-2975
cp -R preproc_rules/ /etc/snort/rules
cp -R so_rules/ /etc/snort/rules
cd rules
cp * /etc/snort/rules

Assegniamo il giusto owner alla directory /etc/snort:

chown snort:snort -R /etc/snort

e concentriamoci sulle dynamic rules (con relative librerie):

mkdir -p /usr/local/lib/snort_dynamicrules
chown -R snort:snort /usr/local/lib/snort_dynamicrules
cp /usr/local/src/so_rules/precompiled/RHEL-6-0/x86-64/2.9.7.5 /usr/local/lib/snort_dynamicrules
chmod -R 700 /usr/local/lib/snort_dynamicrules

Ora passiamo alla configurazione di snort:

nano /etc/snort/snort.conf

nella quale occorre definire le reti locali (HOME_NET), le reti esterne (EXTERNAL_NET), il pathname delle regole utilizzate da snort e quello delle whitelist/blacklist (basate sulla reputazione). Inoltre, bisogna definire il tipo di output generato da snort (il quale dovrà essere interpretabile da barnyard2).

Ecco uno stralcio delle modifiche apportate al file di configurazione di snort:

ipvar HOME_NET [192.168.1.0,192.168.12.0]
ipvar EXTERNAL_NET !$HOME_NET

var RULE_PATH /etc/snort/rules
var SO_RULE_PATH /etc/snort/rules/so_rules
var PREPROC_RULE_PATH /etc/snort/rules/preproc_rules

var WHITE_LIST_PATH /etc/snort/rules
var BLACK_LIST_PATH /etc/snort/rules

# Reputation preprocessor. For more information see README.reputation
preprocessor reputation: \
   memcap 500, \
   priority whitelist, \
   nested_ip inner, \
#   whitelist $WHITE_LIST_PATH/white_list.rules, \
   blacklist $BLACK_LIST_PATH/black_list.rules

output unified2: filename snort.log, limit 128

Creiamo la directory in cui snort dovrà salvare i log e gli allarmi, assegnandole il giusto owner:

mkdir -p /var/log/snort/
chown snort:snort /var/log/snort/

Infine, testiamo la configurazione di snort, lanciando il comando:

snort -T -i <interface-name> -u snort -g snort -c /etc/snort/snort.conf

il cui output (se non vi sono errori) dovrà contenere la seguente stringa:

Snort successfully validated the configuration!

Eseguire snort come demone

Per fare in modo che snort venga eseguito sulla macchina ospite come demone, occorre, prima di tutto, configurare le opzioni di avvio (definendole all’interno del file /etc/sysconfig/snort):

nano /etc/sysconfig/snort

il cui contenuto dovrà essere simile al seguente:

# /etc/sysconfig/snort
# $Id$

# All of these options with the exception of -c, which tells Snort where
# the configuration file is, may be specified in that configuration file as
# well as the command line. Both the command line and config file options
# are listed here for reference.

#### General Configuration

# What interface should snort listen on?  [Pick only 1 of the next 3!]
# This is -i {interface} on the command line
# This is the snort.conf config interface: {interface} directive
#INTERFACE=eth0
#
# The following two options are not directly supported on the command line
# or in the conf file and assume the same Snort configuration for all
# instances
#
# To listen on all interfaces use this:
INTERFACE=ALL
#
# To listen only on given interfaces use this:
#INTERFACE="eth1 eth2 eth3 eth4 eth5"

# Where is Snort's configuration file?
# -c {/path/to/snort.conf}
CONF=/etc/snort/snort.conf

# What user and group should Snort drop to after starting? This user and
# group should have very few privileges.
# -u {user} -g {group}
# config set_uid: user
# config set_gid: group
USER=snort
GROUP=snort

# Should Snort change the order in which the rules are applied to packets.
# Instead of being applied in the standard Alert->Pass->Log order, this will
# apply them in Pass->Alert->Log order.
# -o
# config order: {actions in order}
# e.g. config order: log alert pass activation dynamic suspicious redalert
PASS_FIRST=0

#### Logging & Alerting

# NOTE: NO_PACKET_LOG and BINARY_LOG, ALERTMODE, etc. are mutually
# exclusive. Use either NO_PACKET_LOG or any/all of the other logging
# options. But the more logging options use you, the slower Snort will run.

# Where should Snort log?
#
#-l {/path/to/logdir}
# config logdir: {/path/to/logdir}
LOGDIR=/var/log/snort

# config basename:
BASENAME=snort.log

# How should Snort alert? Valid alert modes include fast, full, none, and
# unsock.  Fast writes alerts to the default "alert" file in a single-line,
# syslog style alert message.  Full writes the alert to the "alert" file
# with the full decoded header as well as the alert message.  None turns off
# alerting. Unsock is an experimental mode that sends the alert information
# out over a UNIX socket to another process that attaches to that socket.
# -A {alert-mode}
# output alert_{type}: {options}
#ALERTMODE=full

# Should Snort dump the application layer data when displaying packets in
# verbose or packet logging mode.
# -d
# config dump_payload
DUMP_APP=1

# Should Snort keep binary (AKA pcap, AKA tcpdump) logs also? This is
# recommended as it provides very useful information for investigations.
# -b
# output log_tcpdump: {log name}
#BINARY_LOG=1

# Should Snort turn off packet logging?  The program still generates
# alerts normally.
# -N
# config nolog
NO_PACKET_LOG=0

# Print out the receiving interface name in alerts.
# -I
# config alert_with_interface_name
PRINT_INTERFACE=0

# When dumping the stats, what log file should we look in
SYSLOG=/var/log/messages

# When dumping the stats, how long to wait to make sure that syslog can
# flush data to disk
SECS=5

# To add a BPF filter to the command line uncomment the following variable
# syntax corresponds to tcpdump(8)
#BPF="not host 192.168.1.1"

# To use an external BPF filter file uncomment the following variable
# syntax corresponds to tcpdump(8)
# -F {/path/to/bpf_file}
# config bpf_file: /path/to/bpf_file
#BPFFILE=/etc/snort/bpf_file

a tal proposito, occorre precisare che è necessario commentare le direttive ALERTMODE e BINARY_LOG, altrimenti barnyard2 non sarà in grado di inserire gli allarmi all’interno del database.

Inoltre, poichè il sensore è posizionato inline, esso si trova in ascolto su tutte le interfacce della macchina (INTERFACE=ALL).

Di seguito riporto lo script che consente di demonizzare l’applicativo in questione:

#!/bin/sh
# $Id$
#
# snortd         Start/Stop the snort IDS daemon.
#
# chkconfig: 2345 40 60
# description:  snort is a lightweight network intrusion detection tool that \
#                currently detects more than 1100 host and network \
#                vulnerabilities, portscans, backdoors, and more.
#

# Source function library.
. /etc/rc.d/init.d/functions

# Source the local configuration file
. /etc/sysconfig/snort

#PID file location
PID=/var/run/snort

# Convert the /etc/sysconfig/snort settings to something snort can
# use on the startup line.
if [ "$ALERTMODE"X = "X" ]; then
   ALERTMODE=""
else
   ALERTMODE="-A $ALERTMODE"
fi

if [ "$USER"X = "X" ]; then
   USER="snort"
fi

if [ "$GROUP"X = "X" ]; then
   GROUP="snort"
fi

if [ "$BINARY_LOG"X = "1X" ]; then
   BINARY_LOG="-b"
else
   BINARY_LOG=""
fi

if [ "$CONF"X = "X" ]; then
   CONF="-c /etc/snort/snort.conf"
else
   CONF="-c $CONF"
fi

if [ "$INTERFACE"X = "X" ]; then
   INTERFACE="-i eth0"
else
   INTERFACE="-i $INTERFACE"
fi

if [ "$DUMP_APP"X = "1X" ]; then
   DUMP_APP="-d"
else
   DUMP_APP=""
fi

if [ "$NO_PACKET_LOG"X = "1X" ]; then
   NO_PACKET_LOG="-N"
else
   NO_PACKET_LOG=""
fi

if [ "$PRINT_INTERFACE"X = "1X" ]; then
   PRINT_INTERFACE="-I"
else
   PRINT_INTERFACE=""
fi

if [ "$PASS_FIRST"X = "1X" ]; then
   PASS_FIRST="-o"
else
   PASS_FIRST=""
fi

if [ "$LOGDIR"X = "X" ]; then
   LOGDIR=/var/log/snort
fi

# These are used by the 'stats' option
if [ "$SYSLOG"X = "X" ]; then
   SYSLOG=/var/log/messages
fi

if [ "$SECS"X = "X" ]; then
   SECS=5
fi

if [ ! "$BPFFILE"X = "X" ]; then
   BPFFILE="-F $BPFFILE"
fi

######################################
# Now to the real heart of the matter:

# See how we were called.
case "$1" in
  start)
        echo -n "Starting snort: "
        cd $LOGDIR
        if [ "$INTERFACE" = "-i ALL" ]; then
           for i in `cat /proc/net/dev|grep eth|awk -F ":" '{ print $1; }'`
           do
                mkdir -p "$LOGDIR/$i"
                chown -R $USER:$GROUP $LOGDIR
                daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE -i $i -u $USER -g $GROUP $CONF -l $LOGDIR/$i 

$PASS_FIRST $BPFFILE $BPF
           done
        else
           # check if more than one interface is given
           if [ `echo $INTERFACE|wc -w` -gt 2 ]; then
              for i in `echo $INTERFACE | sed s/"-i "//`
                do
                  mkdir -p "$LOGDIR/$i"
                  chown -R $USER:$GROUP $LOGDIR
                  daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE -i $i -u $USER -g $GROUP $CONF -l $LOGDIR/$i 

$PASS_FIRST $BPFFILE $BPF
             done
           else
              # Run with a single interface (default)
              daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE $INTERFACE -u $USER -g $GROUP $CONF -l $LOGDIR 

$PASS_FIRST $BPFFILE $BPF --pid-path $PID
           fi
        fi
        touch /var/lock/subsys/snort
        echo
        ;;
  stop)
        echo -n "Stopping snort: "
        killproc snort
        rm -f /var/lock/subsys/snort
        echo
        ;;
  reload)
        echo "Sorry, not implemented yet"
        ;;
  restart)
        $0 stop
        $0 start
        ;;
  condrestart)
        [ -e /var/lock/subsys/snort ] && $0 restart
        ;;
  status)
        status snort
        ;;
  stats)
        TC=125                          # Trailing context to grep
        SNORTNAME='snort'               # Process name to look for

        if [ ! -x "/sbin/pidof" ]; then
           echo "/sbin/pidof not present, sorry, I cannot go on like this!"
           exit 1
        fi

        #Grab Snort's PID
        PID=`pidof -o $$ -o $PPID -o %PPID -x ${SNORTNAME}`

        if [ ! -n "$PID" ]; then        # if we got no PID then:
           echo "No PID found: ${SNORTNAME} must not running."
           exit 2
        fi

        echo ""
        echo "*******"
        echo "WARNING:  This feature is EXPERIMENTAL - please report errors!"
        echo "*******"
        echo ""
        echo "You can also run: $0 stats [long | opt]"
        echo ""
        echo "Dumping ${SNORTNAME}'s ($PID) statistics"
        echo "please wait..."

        # Get the date and tell Snort to dump stats as close together in
        # time as possible--not 100%, but it seems to work.
        startdate=`date '+%b %e %H:%M:%S'`

        # This causes the stats to be dumped to syslog
        kill -USR1 $PID

        # Sleep for $SECS secs to give syslog a chance to catch up
        # May need to be adjusted for slow/busy systems
        sleep $SECS

        if [ "$2" = "long" ]; then              # Long format
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                grep snort.*:
        elif [ "$2" = "opt" ]; then             # OPTimize format
           # Just show stuff useful for optimizing Snort
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                egrep "snort.*: Snort analyzed |snort.*: dropping|emory .aults:"
        else                                    # Default format
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                grep snort.*: | cut -d: -f4-
        fi
        ;;
  *)
        echo "Usage: $0 {start|stop|reload|restart|condrestart|status|stats (long|opt)}"
        exit 2
esac

exit 0

Copiamo il binario di snort nella dir /usr/sbin:

cp /usr/local/bin/snort /usr/sbin/

e rendiamo il suddetto scrip eseguibile, per poi avviarlo e fare in modo che venga eseguito automaticamente dopo ogni riavvio della macchina:

chmod +x /etc/init.d/snortd
chkconfig --add snortd
chkconfig snortd on

Per ora abbiamo finito. Nel prossimo post vedremo come installare e configurare pulledpork e barnyard2.

A presto.

Cisco 2811: utilizzare le route-map per creare delle regole di destination NAT basate su IP sorgente

Scenario

Supponiamo che si abbia a che fare con un ufficio centrale (main office) a cui sono collegati N uffici periferici (branch office) tramite dei tunnel VPN IPsec Site-to-Site dedicati (che concorrono a formare la classica topologia a stella). Supponiamo, inoltre, che i suddetti uffici periferici, per questioni di failover, debbano essere in grado di raggiungere i servizi presenti nell’ufficio centrale anche nel caso in cui i tunnel VPN non siano disponibili (passando quindi  direttamente per Internet).

vpn-ipsec1Utilizzando delle regole di destination NAT classiche, del tipo:

ip nat inside source static tcp 192.168.2.4 80 interface fastethernet0/0 80

(dove 192.168.4.2 è l’IP locale del server Web esposto su Internet), i branch office non saranno in grado di raggiungere il server in questione tramite il tunnel VPN (utilizzando il protocollo HTTP).

Ergo, il fatto che un determinato servizio sia pubblicato su Internet, implica automaticamente l’impossibilità di raggiungerlo anche tramite il tunnel VPN.

Per ovviare a tale problematica esistono 2 soluzioni: la prima, meno impegnativa (ma che richiede la modifica della URL lato client in caso di failover), consiste nel modificare la configurazione del server in modo tale che rimanga in ascolto su 2 porte distinte, ad esempio la TCP 80 per Internet e la TCP 81 per la VPN;  la seconda, più impegnativa (ma anche molto più scalabile), consiste nel creare sul nostro router Cisco 2811 (main office) delle route-map (che si avvalgono di opportune ACL) in grado di filtrare gli indirizzi IP sorgenti dei client che vogliono collegarsi al server Web. In questo modo, se la richiesta di connessione proviene da un determinato IP privato tipico di una VPN Site-to-Site (ad esempio 192.168.3.1), per essa non viene applicato il destination NAT; viceversa, nel caso in cui la richiesta di connessione provenga da Internet, verrà applicato il destination NAT come di consueto.

Ho definito la seconda soluzione come la più scalabile delle 2 per un semplice motivo: impostando la route-map sul router del main office e modificando sul nameserver locale il record di tipo A che punta all’IP del server Web, si può fare in modo che quest’ultimo possa essere contattato tramite tunnel VPN o tramite Internet a seconda dei casi senza dover modificare la URL lato browser (passando, ad esempio, da http://www.vostrodominio.com a http://www.vostrodominio.com:81).

Vediamo adesso come mettere in pratica la soluzione #2.

Configurazione del router Cisco 2811 (main office)

Per prima cosa occorre creare l’ACL in grado di “riconoscere” gli IP locali e di negare il destination NAT:

Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.3.0 0.0.0.255
Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.4.0 0.0.0.255
Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.5.0 0.0.0.255
Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.6.0 0.0.0.255
Router(config)# access-list 150 permit ip host 192.168.2.4 any

Successivamente creiamo la route-map vera e propria:

Router(config)# route-map nonat
Router(config-route-map)# match ip address 150

dove 150 è il numero dell’ACL estesa precedentemente definita.

Infine, associamo la route-map appena creata alla regola di destination NAT:

Router(config)# ip nat inside source static tcp 192.168.2.4 <IP Pubblico> 80 route-map nonat extendable

Ovviamente, affinchè la suddetta soluzione sia realmente scalabile, è necessario che il vostro collegamento ad Internet sia dotato di indirizzo IP pubblico statico.

Salviamo adesso la configurazione del nostro router:

Router# copy run start

e passiamo al vaglio alcune soluzioni alternative alle route-map.

1) Utilizzo dei record DNS di tipo SRV (vedi qui per ulteriori dettagli). Essi ci consentono non solo di specificare il protocollo di comunicazione ma anche la porta su cui è in ascolto il server, definendo una priorità per ciascuna entry che li compone:

_http._tcp.vostrodominio.com. 86400 IN SRV 0 5 81 www.vostrodominio.com.
_http._tcp.vostrodominio.com. 86400 IN SRV 1 5 80 www1.vostrodominio.com.

dove 0 e 1 sono le priorità, 81 e 80 le porte su cui è in ascolto il server. In caso di timeout sulla porta 81 e l’IP di www (raggiungibile via VPN) il browser “dovrebbe” switchtare automaticamente sulla 80 e l’IP di www1. Ho utilizzato il condizionale poichè non tutti i broswer supportano tale meccanismo ed un workaround (applicato però solo da alcuni di essi), consiste nel definire record A con il medesimo hostname ma indirizzi IP differenti: nel caso in cui la connessione al primo IP della lista vada in timeout, il broswer tenterà automaticamente di connettersi al secondo IP (e così via).

2) Utilizzo di un firewall interno per filtrare le connessioni in uscita (outbound). ln questo caso, grazie ad esso, potremmo creare delle regole ad hoc (source NAT) per il mapping delle porte di destinazione, ad esempio (utilizzando iptables):

[root@firewall ~]# iptables -t nat -A OUTPUT -p tcp -d www.vostrodominio.com --dport 80 -j DNAT --to-destination www.vostrodominio.com:81

Anche in questo caso, prima di applicare la suddetta regola di firewalling, sarà necessario modificare sul nameserver il record A per l’hostname www.

E’ tutto. Alla prossima.

PIX 501: configurazione del protocollo TACACS+

Premessa

Più volte, nell’ambito dei miei ultimi post, ho discusso della configurazione del protocollo TACACS+ per i Router/Switch di casa Cisco.

Adesso vedremo come configurare il suddetto protocollo su un Cisco PIX 501.

pixPrima di iniziare, occorre precisare che le uniche feature che abiliteremo saranno l’autenticazione e l’accounting (tralasciando quindi la parte di autorizzazione).

Configurazione generale

Dopo aver effettuato il login sul firewall in questione, entriamo in modalità enable e digitiamo il comando:

PIX# conf t

per poi creare una nuova istanza TACACS+:

PIX(config)# aaa-server AuthInbound protocol tacacs+

A questo punto possiamo specificare l’IP del server AAA, l’interfaccia attraverso cui è possibile raggiungerlo, la chiave TACACS+ ed il timeout:

PIX(config)# aaa-server AuthInbound (inside) host <IP> <key> timeout <secondi>

Authentication

Ora possiamo definire i protocolli che dovranno interfacciarsi col server per l’autenticazione dell’utente:

PIX(config)# aaa authentication telnet console AuthInbound LOCAL

Accounting

Infine, facciamo in modo che tutte le sessioni provenienti dall’esterno (Internet) vengano loggate dal nostro server:

PIX(config)# aaa accounting any inbound 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 AuthInbound

Creazione delle utenze locali

Per una questione di fallback, prima di salvare la suddetta configurazione, conviene creare delle utenze locali utilizzando il comando:

PIX(config)# username <user> password <pass>

ed abbiamo finito.

Alla prossima.

Firewall Cisco ASA ed attacchi DDoS/DoS

Ultimamente mi è capitato di dover far fronte a tutta una serie di attacchi DDoS, per lo più basati sul protocollo HTTP (connessioni half-open/embryonic, in cui manca il l’ACK finale poichè l’indirizzo IP sorgente del SYN è falso o soggetto a spoofing), mitigati senza troppe difficoltà da un cluster di Firewall Cisco ASA.

ddosLa configurazione che ho utilizzato per mitigare tale tipologia di attacchi è simile alla seguente:

ASA(config)# class-map mpf-policy
ASA(config-cmap)# match access-list outside_access_in
ASA(config-cmap)# exit
ASA(config)# policy-map mpf-policy-map
ASA(config-pmap)# class mpf-policy
ASA(config-pmap-c)# set connection conn-max 11500
ASA(config-pmap-c)# set connection embryonic-conn-max 3000
ASA(config-pmap-c)# set connection per-client-embryonic-max 200
ASA(config-pmap-c)# set connection per-client-max 95
ASA(config-pmap-c)# exit
ASA(config-pmap)# exit
ASA(config)# service-policy mpf-policy-map interface outside
ASA(config)# exit

Tutto è filato liscio per un po’ di tempo, fino a quando l’attaccante non ha deciso di cambiare strategia, passando da un attacco DDoS ad uno DoS (dunque con un solo IP sorgente) e dal protocollo TCP a quello UDP (molto più adatto a questa tipologia di attacco poichè connection-less).

La VPS utilizzata come sorgente di traffico, dotata di ampia banda (si trovava in una farm tedesca) è stata in grado, in un lasso di tempo brevissimo, di far collassare i firewall. Una volta identificato il suo IP ho creato un’ACL del tipo:

ASA(config)#deny ip host <IP attaccante> any

che però si è rivelata essere un’arma a doppio taglio visto che il firewall si è visto costretto a “maneggiare” e “bloccare” una mole di traffico tale per cui la sua CPU ha raggiunto livelli di carico assurdi (la dashboard di ASDM indicava un picco di oltre il 300% a fronte di un rate di pacchetti droppati superiore ai 100k  – vedi immagine sottostante).

dropped_ratedropped_rate

Fondamentalmente ciò è dovuto al fatto che ciascun modello di ASA può gestire solo una determinata mole di traffico (sessioni concorrenti, nuove connessioni/secondo, pacchetti/secondo, ecc – per ulteriori dettagli vedi qui), limite imposto soprattutto dalle caratteristiche hardware di cui è dotato (CPU, RAM, ecc.). Inoltre, per ciascun pacchetto scartato, è necessario un certo overhead, ragion per cui la suddetta ACL ha prodotto effetti collaterali che hanno portato ad un peggioramento della situazione.

Dopo qualche minuto di smarrimento, ho deciso di modificare la mia strategia (sulla falsariga di quella dell’attaccante), consentendo sul firewall tutto il traffico in ingresso dall’IP della VPS incriminata, demandando ai server la sua gestione. Nella fattispecie, ho configurato dei blackhole (aka null route) a livello 3, mediante il seguente comando:

route add -net <IP attaccante> gw 127.0.0.1 lo

Ho scelto questa strategia per 2 motivi:

1) I server sono dotati di maggiori risorse hardware rispetto ai firewall, quindi più “propensi” a gestire una tale mole di traffico in ingresso;

2) Lavorare a livello 3 anzichè a livello 4 implica un minor overhead.

Alla fine tale strategia si è rivelata vincente e l’attaccante ha deposto le armi.

E’ tutto, alla prossima.

Reboot script per i router Draytek Vigor

Premesso che giornalmente devo “scontrarmi” con un Draytek Vigor 3300V, sono pian piano giunto alla conclusione che tale aggeggio abbia più difetti che pregi.

vigor3300.jpg

Ad esempio, il content filtering consente di bloccare al massimo 8 (e dico 8!) keyword e non ne vuole sapere di gestire l’HTTPS; la pagina relativa ai DDNS, nonostante la presenza delle credenziali per aggiornare l’associazione IP – FQDN, non inoltra alcuna richiesta al sito del provider e quindi i record A scadono; il server DHCP integrato non consente di settare delle normalissime exclusion su alcuni IP che rientrano nel pool ma che non devono essere assegnati a nessun utente.

Ora, potrei continuare quasi all’infinito, ma l’ultima bega che mi son dovuto accollare riguarda la gestione delle VPN. Si, esatto, questo fantastico router funge anche da VPN concentrator, riuscendo (per modo di dire) a gestire VPN IPSec, L2TP e PPTP. Peccato che ogni “tot” si incarti miseramente, lasciando fuori alcuni utenti che cercano di atterrare sulla LAN via VPN, mentre altri riescono tranquillamente ad accedere alla rete interna.

Ho provato a cercare una soluzione un pò più pulita rispetto al classico riavvio, ma credetemi se vi dico che non c’è (forse si potrebbe procedere con la disattivazione/riattivazione della VPN ma non sono sicuro che una cosa del genere non preveda comunque un reboot).

In definitiva, ecco lo scrip expect che mi permette di riavviare il router ogni notte:

#!/usr/bin/expect

set password1 "password"

exec date
spawn ssh -l draytek 10.1.10.1
expect "?"
send "yr"
expect "*?assword:*"
send "$password1r"
expect ">"
send "sys rebootr"
expect "?"
send "yr"
expect eof

Ovviamente l’esecuzione di tale scrip avviene mediante cron e non fa altro che connettersi al router, lanciare un sys/reboot ed uscire.

Attenzione però: dopo ogni riavvio il router cambia il proprio fingerprint SSH (non chiedetemi il perchè), quindi il suddetto scrip, dopo il primo riavvio, fallirebbe miseramente in quanto il client SSH, vedendosi cambiare di punto in bianco il fingerprint dell’host a cui sta provando a connettersi, penserebbe in un attacco MITM.

Per evitarè ciò è necessario editare il file /etc/ssh/ssh_config aggiungendo in testa le seguenti direttive:

Host 10.1.10.1
     StrictHostKeyChecking no
     UserKnownHostsFile=/dev/null

Infine, voglio precisare che il router è comunque dotato di un comando in grado di definire il reboot automatico (mi sa che gli stessi costruttori fossero a conoscenza del fatto che tale aggeggio tende ad incartarsi di continuo). Nonostante questo comando bundle, chiamato appunto autoreboot, ho preferito operare come indicato in precedenza per un semplice motivo:

DrayTek> sys autoreboot ?
 Full Name:
    auto reboot function
 Description:
 Syntax:
    autoreboot -s                                (Show status)
    autoreboot -e <Enable>
    autoreboot -t <Hours>
 Parameters:
    <Enable>                                         (0: Disable, 1: Enable)
    <Hours>                                          (Number of hours)

Si, avete capito bene, se volessi riavviare il router ogni mattina alle 3 (quindi esattamente ogni 24 ore) dovrei lanciare i comandi:

DrayTek> sys autoreboot -e 1

DrayTek> sys autoreboot -t 24

indovinate a che ora? ALLE 3 DEL MATTINO. No comment.

Alla prossima.

Abilitare ASDM su Cisco ASA/PIX

Per i non addetti ai lavori, lavorare da linea di comando per configurare i dispositivi di rete (soprattutto se si tratta di Security Appliance) può risultare a dir poco traumatico.

Ecco allora che ho deciso di scrivere questa semplice guida per l’abilitazione dell’interfaccia grafica (denominata ASDM) sui firewall di casa Cisco (PIX/ASA).

cisco-asa-firewall-frontview.jpg

Per prima cosa occorre verificare che il *.bin di ASDM sia presente nella flash. Per fare ciò possiamo eseguire il comando (dalla modalità enable):

fw1# sh flash | i asdm

il cui output dovrebbe essere simile al seguente:

fw1# sh flash | i asdm
  105  17902288    Apr 30 2012 21:42:34  asdm-64**.bin

Bene, a questo punto possiamo dire al nostro firewall dove trovare il suddetto bin:

fw1# conf t

fw1(config)# asdm image flash:/asdm-64**.bin

Ora dobbiamo abilitare il server http presente sul dispositivo in questione, mediante il comando:

fw1(config)# http server enable

Ciò si rende necessario poichè ASDM utilizza il protocollo https.

Infine, occorre definire su quale interfaccia e da quali IP accettare le richieste di connessione:

http 0.0.0.0 0.0.0.0 outside

in questo modo stiamo imponendo al nostro firewall di accettare le connessioni provenienti da un qualunque indirizzo IP pubblico e dirette all’interfaccia outside (ovvero quella esposta direttamente su Internet).

Il nome dell’interfaccia (outside) è in realtà un alias che può essere definito mediante il comando nameif:

fw1(config-if)# nameif outside

Ovviamente, è opportuno che per accedere al suddetto tool vengano fornite le giuste credenziali. Per definirle basta usare il comando:

fw1(config)# username <nomeutente> password <pass>

A questo punto sarete in grado di amministrare il vostri firewall mediante ASDM.

Alla prossima.

Controllare lo stato di iptables mediante Nagios

Recentemente su uno dei miei server ho lanciato il comando:

nightfly@nightbox:~$ sudo iptables -L

e con mio enorme disappunto mi sono accorto che le regole di firewalling che il server avrebbe dovuto caricare all’avvio erano praticamente assenti (eccezion fatta per fail2ban), indi per cui ho deciso di monitorare lo stato di iptables mediante Nagios.

iptables.jpg

Lo scrip che ho utilizzato per i check potete scaricarlo da qui. Inoltre, poichè tale scrip è piuttosto bacato, ho deciso di apportare qualche piccola correzione. Di seguito la versione originale dello scrip:

#!/bin/bash

PARAM1=$1
TABLE=$2
MINRULES=$3
PARAM4=$4
LOG=/var/log/iptables/iptables.log
CHKIPTBLS=`/sbin/iptables -n -t filter -L |wc -l`

#
# Parameter Validation
##

if [ "$PARAM1" != "-T" -o "$TABLE" == "" -o "$MINRULES" != "-r" -o "$PARAM4" == "" ]; then
        echo "Usage: $0 -T <table> -r <min rules>"
        echo ""
        exit 3
                # Nagios exit code 3 = status UNKNOWN = orange

if [ "$PARAM1" == "-h" ]; then
        echo ""
        echo "         -h = Display's this Help"
        echo "         -T = Table to check"
        echo "                 Available Tables:"
        echo "                    nat"
        echo "                    mangle"
        echo "                    filter"       
        echo "         -r = Minimun quantity of rules"
        echo ""
        # Nagios exit code 3 = status UNKNOWN = orange
                exit 3
   fi
fi

##
#    DO NOT MODIFY ANYTHING BELOW THIS
##

$CHKIPTBLS >/dev/null 2>/dev/null

if [ "$CHKIPTBLS" == 0 ]; then
    TOTRULES=$CHKIPTBLS
else
    TOTRULES=$[$CHKIPTBLS-8]
fi

if [ "$TOTRULES" -gt "$PARAM4" ]; then
                    echo "OK - Iptables are OK the table $TABLE has $TOTRULES rules configured"
                    # Nagios exit code 0 = status OK = green
                    exit 0
else
                    echo " CRITICAL - Iptables are CRITICAL the table $TABLE has $TOTRULES rules configured"
                    for i in `w  -h | cut -f1 -d" " | sort | uniq`
                    do

                        echo "`date '+%d/%m/%Y - %H:%M:%S'` - CRITICAL - $i is logged in and there are only $TOTRULES loaded" >> $LOG
                    done
                    # Nagios exit code 2 = status CRITICAL = red
                    exit 2               
fi

Punto primo: la seconda condizione dell’if non ha praticamente senso, in quanto la prima è sempre verificata.
E’ bastato invertire le due condizioni e trattarle separatamente:

#
# Parameter Validation
##

if [ "$PARAM1" == "-h" ]; then
        echo ""
        echo "          -h = Display's this Help"
        echo "          -T = Table to check"
        echo "          Available Tables:"
        echo "          nat"
        echo "          mangle"
        echo "          filter"
        echo "          -r = Minimun quantity of rules"
        echo ""
        # Nagios exit code 3 = status UNKNOWN = orange
        exit 3
fi

if [ "$PARAM1" != "-T" -o "$TABLE" == "" -o "$MINRULES" != "-r" -o "$PARAM4" ==                                                                                         "" ]; then
        echo "Usage: $0 -T <table> -r <min rules>"
        echo ""
        exit 3
        # Nagios exit code 3 = status UNKNOWN = orange
fi

Punto secondo: la variabile CHKIPTBLS utilizza sempre e comunque la tabella filter, dunque il parametro -T non ha senso di esistere. Possiamo però ovviare a tale mancanza, permettendo all’utente di scegliere su quale tabella (tra filter, mangle e nat) effettuare i controlli, modificando la variabile citata in precedenza nel seguente modo:

CHKIPTBLS=`sudo /sbin/iptables -n -t "$TABLE" -L |wc -l`

Punto terzo: la condizione

if [ "$TOTRULES" -gt "$PARAM4" ]; then

controlla che il numero di regole caricate sia strettamente maggiore di quello definito mediante il parametro -r. Questo però cozza con quanto dichiarato dall’autore dello scrip, ovvero:

OK - The number of Iprules equal o more than the minimun that we setup on the -r variable

Per ovviare a tale errore, occorre sostituire la condizione riportata in precedenza con questa:

if [ "$TOTRULES" -ge "$PARAM4" ]; then

Punto quarto: nagios non ha i permessi per lanciare iptables, ergo dobbiamo effettuare delle modifiche al file /etc/sudoers, inserendo la entry:

nagios   ALL = NOPASSWD: /sbin/iptables

alla fine del file. 

In definitiva, lo scrip per controllare lo stato di iptables dovrà essere il seguente:

#!/bin/bash

PARAM1=$1
TABLE=$2
MINRULES=$3
PARAM4=$4
LOG=/var/log/check_iptables.log
CHKIPTBLS=`sudo /sbin/iptables -n -t "$TABLE" -L |wc -l`

#
# Parameter Validation
##

if [ "$PARAM1" == "-h" ]; then
        echo ""
        echo "          -h = Display's this Help"
        echo "          -T = Table to check"
        echo "          Available Tables:"
        echo "          nat"
        echo "          mangle"
        echo "          filter"
        echo "          -r = Minimun quantity of rules"
        echo ""
        # Nagios exit code 3 = status UNKNOWN = orange
        exit 3
fi

if [ "$PARAM1" != "-T" -o "$TABLE" == "" -o "$MINRULES" != "-r" -o "$PARAM4" == "" ]; then
        echo "Usage: $0 -T <table> -r <min rules>"
        echo ""
        exit 3
        # Nagios exit code 3 = status UNKNOWN = orange
fi

##
#       DO NOT MODIFY ANYTHING BELOW THIS
##

$CHKIPTBLS >/dev/null 2>/dev/null

if [ "$CHKIPTBLS" == 0 ]; then
        TOTRULES=$CHKIPTBLS
else
        TOTRULES=$[$CHKIPTBLS-8]
fi

if [ "$TOTRULES" -ge "$PARAM4" ]; then
                    echo "OK - Iptables is OK The Table $TABLE has $TOTRULES rules configured"
                    # Nagios exit code 0 = status OK = green
                    exit 0
else
                    echo " CRITICAL - Iptables is CRITICAL The Table $TABLE has $TOTRULES rules configured"
                                        for i in `w  -h | cut -f1 -d" " | sort | uniq`
                                        do
                                                echo "`date '+%d/%m/%Y - %H:%M:%S'` - CRITICAL - $i is logged in and there are only $TOTRULES loaded" >> $LOG
                                        done
                    # Nagios exit code 2 = status CRITICAL = red
                    exit 2
fi

Se il file /var/log/check_iptables.log non esiste, dovrete crearlo mediante il comando:

nightfly@nightbox:~$ sudo touch /var/log/check_iptables.log

A questo punto possiamo rinominare lo scrip:

nightfly@nightbox:~$ mv check_iptables_status.sh check_iptables_status

rendondolo successivamente eseguibile:

nightfly@nightbox:~$ chmod +x check_iptables_status

Spostiamolo nella directory /usr/lib/nagios/plugins:

nightfly@nightbox:~$ sudo mv check_iptables_status /usr/lib/nagios/plugins

Creiamo il file iptables.cfg nella directory /etc/nagios-plugins/config:

nightfly@nightbox:/etc/nagios-plugins/config$ sudo nano iptables.cfg

il cui contenuto dovrà essere il seguente:

# 'check_iptables_status' command definition
define command{
        command_name    check_iptables_status
        command_line    /usr/lib/nagios/plugins/check_iptables_status -T '$ARG1$' -r '$ARG2$'
        }

infine aggiungiamo la seguente direttiva al file dell’host su cui vogliamo monitorare lo stato di iptables (tale file è presente nella directory /etc/nagios3/conf.d):

define service{
        use                             generic-service         ; Name of service template to use
        host_name                       localhost
        service_description             iptables
                check_command                   check_iptables_status!filter!84
}

Dove 84 è il numero minimo di regole di firewalling attive.

Infine, riavviamo nagios:

nightfly@nightbox:~$ sudo service nagios3 restart

ed abbiamo finito.

Alla prossima.

Script per il backup automatico della configurazione di un firewall Cisco PIX 501

In questo post ho riportato uno scrip da me creato il cui scopo è quello di eseguire un backup della configurazione di un router Cisco SOHO 77. Inoltre, sempre nell’ambito del post in questione, ho descritto la procedura per installare e configurare correttamente un server TFTP sulla nostra linux box. Dando per scontato che il server TFTP sia già attivo e che il file vuoto firewall.cfg sia già presente nella directory /tftpboot, vediamo come configurare il nostro firewall affinchè possa comunicare con il server in ascolto.

pix501

Una volta effettuato il login sul PIX 501 lanciamo un conf t e successivamente digitiamo il comando:

PIX501(config)# tftp-server inside <IP del server TFTP> /tftpboot/firewall.cfg

In questo modo stiamo dicendo al PIX qual è l’indirizzo del server ed il pathname del file su cui salvare la configurazione. Lanciamo un write mem per salvare le modifiche relative alla configurazione del firewall e successivamente accediamo alla nostra linux box. Fattò ciò creiamo il file backup_conf_pix501 il cui contenuto dovrà essere il seguente:

 #!/usr/bin/expect

 set password1 "<pass1>"
 set password2 "<pass2>

 spawn telnet <IP del firewall>
 expect "Password:"
 send "$password1\r"
 expect "Password:"
 send "$password2\r"
 expect ">"
 send "ena\r"
 expect "Password:"
 send "$password\r"
 expect "#"
 send "write net\r"
 expect "#"
 send "exit\r"
 expect eof

Rendiamo il file eseguibile digitando:

nightfly@nightbox:~$ sudo chmod +x backup_conf_pix501

spostiamolo in /usr/bin e successivamente editiamo il file /etc/crontab aggiungendo la entry:

00 00   * * * root backup_conf_pix501

Riavviamo cron:

nightfly@nightbox:~$ sudo /etc/init.d/cron restart

ed il gioco è fatto. See ya.

Sincronizzare data ed ora dei dispositivi di rete mediante un server NTP

L’uso di un buon timeserver rappresenta la prima regola per ottenere dei log affidabili e soprattutto privi di eventuali inconsistenze. Inoltre, grazie ad esso, è possibile sincronizzare la data e l’ora sui vari dispositivi di rete, in modo da non dover necessariamente ricorrere ad un settaggio manuale di tali parametri.

synchronize-internet-time-server.jpg

Vediamo adesso come definire un timeserver su di un router Cisco SOHO 77, su di un firewall Cisco PIX 501 e su una macchina linux.

NTP su Cisco SOHO 77

Entriamo nella modalità di configurazione del nostro router:

SOHO77# conf t

e successivamente digitiamo il comando:

SOHO77(config)# sntp server <IP del server NTP>

In questo caso ho utilizzato come server NTP ntp.ubuntu.com, il cui indirizzo IP è 91.189.94.4

Adesso definiamo la timezone:

SOHO77(config)# clock timezone UTC +1

Come potete notare dal comando precedente, ho utilizzato la timezone UTC+1 poichè attualmente in Italia è in vigore l’ora legale.

Controlliamo che tutto sia andato a buon fine digitando il comando:

SOHO77(config)# sh clock

ed infine salviamo la configurazione:

SOHO77(config)# copy run start

NTP su Linux

Passiamo adesso all’installazione di un timeserver sulla nostra macchina linux.

Per fare ciò è sufficiente digitare:

nightfly@nightbox:~$ sudo apt-get install ntp

Ad installazione completata editiamo il file di configurazione relativo ad ntpd, ovvero il demone che funge da timeserver:

nightfly@nightbox:~$ sudo nano /etc/ntp.conf

Inseriamo i seguenti hostname:

# You do need to talk to an NTP server or two (or three).
 server ntp.ubuntu.com
 server ntp1.inrim.it
 server ntp2.inrim.it

Salviamo il file e riavviamo ntpd:

nightfly@nightbox:~$ sudo service ntp restart

NTP su Cisco PIX 501

Bene, ora non ci resta che configurare un server NTP sul nostro firewall. Per fare ciò occorre seguire questi step:

PIX501# conf t

PIX501(config)# ntp server <IP della nostra macchina linux su cui gira ntpd> source inside

PIX501(config)# clock timezone UTC +1

Inoltre, è necessario definire un’ACL apposita sul firewall in questione in modo da consentire il traffico udp sulla porta 123. Ciò si rende necessario poichè il server NTP interno (presente sulla macchina linux) deve poter ricevere gli aggiornamenti da quello esterno.

PIX501(config)# access-list inbound permit udp host 91.189.94.4 host <IP del server NTP interno> eq 123

Controlliamo che tutto sia andato a buon fine digitando:

PIX501# sh clock

ed anche:

PIX501# sh ntp status

il cui output dovrebbe essere simile al seguente:

Clock is synchronized, stratum 4, reference is <IP del server NTP interno>
 nominal freq is 99.9967 Hz, actual freq is 99.9966 Hz, precision is 2**6
 reference time is d1161f31.f0ef3448 (14:18:41.941 UTC Mon Feb 28 2011)
 clock offset is 3.5382 msec, root delay is 78.16 msec
 root dispersion is 1386.23 msec, peer dispersion is 880.07 msec

ed infine salviamo la configurazione con un write mem.

Adesso i nostri dispositivi dovrebbero essere sincronizzati alla perfezione con i server NTP di riferimento.

A presto.

Logging del traffico droppato da iptables

Qualsiasi firewall che si rispetti, oltre a dover filtrare il traffico secondo le regole definite dall’utente, deve mettere a disposizione un buon meccanismo di logging. In tal senso, iptables rientra a pieno titolo tra i firewall degni nota.

In particolare, il firewall in questione consente di loggare il traffico mediante rsyslogd, variante del celeberrimo syslogd, ovvero il demone *nix che si occupa del salvataggio dei log. Ma vediamo come realizzare il logging attraverso iptables.

Per prima cosa, dobbiamo decidere cosa loggare. Potremmo infatti “registrare” tutto il traffico che attraversa il firewall, oppure concentrarci esclusivamente sul traffico droppato. Personalmente ritengo che, per le reti di piccola dimensione, la seconda scelta sia sicuramente la migliore.

Ora, poichè iptables interpreta le regole seguendo una logica top-down, affinchè il traffico possa essere loggato è necessario fare in modo che i pacchetti vengano registrati immediatamente prima di essere scartati.

Quindi, il giusto ordine delle rule dovrebbe essere il seguente:

iptables -A INPUT -s 10.0.0.0/8 -i eth1 -j LOG --log-prefix "Spoofed traffic detected: " --log-level 4
iptables -A FORWARD -s 10.0.0.0/8 -i eth1 -j LOG --log-prefix "Spoofed traffic detected: " --log-level 4

iptables -A INPUT -s 10.0.0.0/8 -i eth1 -j DROP
iptables -A FORWARD -s 10.0.0.0/8 -i eth1 -j DROP

Come potete notare, prima ho loggato il traffico spoofato e solo dopo ho scartato i pacchetti incriminati. Inoltre, alcuni parametri interessanti per il logging che ho utilizzato nelle regole precedenti sono:

–log-prefix, che ci permette di identificare più facilmente i log relativi ai pacchetti droppati dal firewall (il prefisso può essere costituito da un massimo di 29 caratteri);

–log-level, che ci consente di definire la “pericolosità” degli eventi registrati dal firewall.

Nella fattispecie, i log level utilizzati da rsyslogd sono i seguenti:

level    verbose     explanation
 0         emerg       system is unusable
 1         alert          action must be taken immediately
 2         crit            the system is in a critical condition
 3         err            there is an error condition
 4         warning    there is a warning condition
 5         notice       a normal but significant condition
 6         info          a purely informational message
 7        debug       messages generated to debug the application

Detto ciò, per il logging dei pacchetti droppati da iptables ho utilizzato un livello 4, ovvero warning.

Creiamo ora il file di log vero e proprio, in cui verranno salvati gli eventi intercettati dal firewall:

nightfly@nightbox:~$ sudo touch /var/log/iptables.log

Infine, modifichiamo il file di configurazione di rsyslogd:

nightfly@nightbox:~$ sudo nano /etc/rsyslog.d/50-default.conf

ed inseriamo la seguente stringa:

kern.warning                 /var/log/iptables.log

da posizionare subito prima di

kern.*                          -/var/log/kern.log

Riavviamo rsyslogd digitando:

nightfly@nightbox:~$ sudo service rsyslog restart

ed il gioco è fatto.

A presto.