Impostare un firewall con uno script iptables

Da Guide@Debianizzati.Org.
Vai alla navigazione Vai alla ricerca
Debian-swirl.png Versioni Compatibili

Tutte le versioni supportate di Debian

Introduzione

Questa guida non vuole essere il solito howto dove si spiega che in iptables ci sono le catene, le policy di default, quali sono e come funzionano, ma vuole essere un promemoria per ricordare velocemente come configurare un firewall per linux con le seguenti caratteristiche:

  1. policy di default: drop di tutti i pacchetti
  2. permettere solo ai servizi che ci interessano di essere accessibili dall’esterno
  3. permettere a certi servizi di essere accessibili solo dalla LAN

Lo script

Creiamo quindi un nuovo file:

# nano /etc/iptables-firewall.sh

e diamogli questo contenuto, che sarà analizzato nel paragrafo successivo:

#!/bin/sh

###########################
# Imposto alcune variabili
###########################

# Il path di iptables
IPT="/sbin/iptables"

# Interfaccia di rete esterna
IFACE=bond0


########################
# Un messaggio di avvio
########################

echo -n " Loading iptables rules..."


#####################################
# Pulisco la configurazione corrente
#####################################

# Cancellazione delle regole presenti nelle chains
$IPT -F
$IPT -F -t nat

# Eliminazione delle chains non standard vuote
$IPT -X

# Inizializzazione dei contatori (utile per il debugging)
$IPT -Z


###################################################
# Blocco tutto il traffico tranne quello in uscita.
# NOTA: per ragioni di sicurezza sarebbe opportuno
# bloccare anche il traffico in uscita e stabilire
# poi delle regole selettive
###################################################

$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT


##############################
# Abilito il traffico locale
##############################

$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT


#####################################################
# Imposto alcune regole per i pacchetti ICMP di ping
#####################################################

$IPT -A INPUT -p icmp --icmp-type echo-reply -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -m state --state NEW -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type destination-unreachable -m state --state NEW -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type time-exceeded -m state --state NEW -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type timestamp-request -m state --state NEW -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type timestamp-reply -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
$IPT -A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT


###############################################
# Mi difendo dallo spoofing
###############################################

$IPT -A INPUT -s 10.0.0.0/8 -j DROP 
$IPT -A INPUT -s 169.254.0.0/16 -j DROP
$IPT -A INPUT -s 172.16.0.0/12 -j DROP
$IPT -A INPUT -s 127.0.0.0/8 -j DROP
$IPT -A INPUT -s 192.168.0.0/24 -j DROP
$IPT -A INPUT -s 192.168.1.0/24 -j DROP
$IPT -A INPUT -s 192.168.10.0/24 -j DROP
$IPT -A INPUT -s 224.0.0.0/4 -j DROP
$IPT -A INPUT -d 224.0.0.0/4 -j DROP
$IPT -A INPUT -s 240.0.0.0/5 -j DROP
$IPT -A INPUT -d 240.0.0.0/5 -j DROP
$IPT -A INPUT -s 0.0.0.0/8 -j DROP
$IPT -A INPUT -d 0.0.0.0/8 -j DROP
$IPT -A INPUT -d 239.255.255.0/24 -j DROP
$IPT -A INPUT -d 255.255.255.255 -j DROP


########################################
# Mi proteggo da attacchi SMURF
########################################

$IPT -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
$IPT -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
$IPT -A INPUT -p icmp -m icmp -m limit --limit 1/second -j ACCEPT
$IPT -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT


#####################################
# Elimino pacchetti non validi
#####################################

$IPT -A INPUT -m state --state INVALID -j DROP
$IPT -A FORWARD -m state --state INVALID -j DROP
$IPT -A OUTPUT -m state --state INVALID -j DROP


##############################################
# Impedisco i port scan e loggo i tentativi
# Gli IP sono bloccati per 24 ore
##############################################

$IPT -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
$IPT -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP
$IPT -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "portscan:"
$IPT -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP


###############################################
# Blocco le nuove connessioni senza SYN e
# mi proteggo dagli attacchi Denial of Service
###############################################

$IPT -N syn-flood
$IPT -A INPUT -i $IFACE -p tcp --syn -j syn-flood
$IPT -A syn-flood -m limit --limit 1/s --limit-burst 4 -j RETURN
$IPT -A syn-flood -j DROP
$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP


#########################################################
# Consento il traffico delle connessioni gia' stabilite
#########################################################

$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT


#########################################################
# Regole sulle porte. Da modificare secondo le esigenze
# Per ogni regola nel commento viene indicato:
# 1) il numero della porta
# 2) il nome del servizio
# 3) il protocollo
# 4) il livello di accesso
#    - pubblico = accesso permesso a tutti
#    - LAN = accesso permesso solo ai client della LAN
#########################################################

# 21 - ProFTPD - FTP - pubblico
$IPT -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT
# Abilito le porte dinamiche. Configurare correttamente la
# direttiva PassivePorts in /etc/proftpd/proftpd.conf
$IPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 60000:65000 -j ACCEPT

# 25 - Postfix - SMTP - pubblico
$IPT -A INPUT -p tcp --dport 25 -m state --state NEW -j ACCEPT

# 80/443 - Apache - HTTP - pubblico
$IPT -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

# 110 - Dovecot - POP3 - pubblico
$IPT -A INPUT -p tcp --dport 110 -m state --state NEW -j ACCEPT

# 111 - Ulogd - Syslog Server - LAN
$IPT -A INPUT -p tcp --dport 111 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 111 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 111 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 111 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 143 - Dovecot - IMAP - pubblico
$IPT -A INPUT -p tcp --dport 143 -m state --state NEW -j ACCEPT

# 667 - Darkstat - Statistiche - LAN
$IPT -A INPUT -p tcp --dport 667 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 667 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 993 - Dovecot - IMAPs - pubblico
$IPT -A INPUT -p tcp --dport 993 -m state --state NEW -j ACCEPT

# 995 - Dovecot - POP3s - pubblico
$IPT -A INPUT -p tcp --dport 995 -m state --state NEW -j ACCEPT

# 1050/1051 - Zabbix - Monitor - LAN
$IPT -A INPUT -p tcp --dport 1050 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 1050 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 1051 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 1051 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 1194 - OpenVPN - pubblico
$IPT -A INPUT -p tcp --dport 1194 -m state --state NEW -j ACCEPT
echo 1 > /proc/sys/net/ipv4/ip_forward

# 2000 - Sieve - Spam filter - localhost
# Non ha bisogno di configurazione

# 2293 - OpenSSH - SSH - pubblico
$IPT -A INPUT -p tcp --dport 2293 -m state --state NEW -j ACCEPT

# 2605 - BitMeter - Monitor - LAN
$IPT -A INPUT -p tcp --dport 2605 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 2605 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 2812 - Monit - Monitor - LAN
$IPT -A INPUT -p tcp --dport 2812 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 3000 - ntop - Monitor - LAN
$IPT -A INPUT -p tcp --dport 3000 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 3306 - MySQL - localhost
# Non ha bisogno di configurazione

# 10000  Webmin - Monitor - LAN
$IPT -A INPUT -p tcp --dport 10000 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 10000 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 10024/10025 - Amavis - localhost
# Non ha bisogno di configurazione

# 8980 - OpenNMS - Server Monitor - LAN
$IPT -A INPUT -p tcp --dport 8980 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 8980 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 9000 - 9200 - 9300 - 8514 - GrayLOG - LOG Monitor - LAN
$IPT -A INPUT -p tcp --dport 9000 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 9200 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 9300 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 8514 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 9000 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 9200 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 9300 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 8514 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 5353 mDNS - LAN
$IPT -A INPUT -p udp -m udp --dport 5353 --sport 5353 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 67-68 DHCP - LAN
$IPT -A INPUT -p udp -m udp --dport 67 --sport 68 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 4200 - Shell in a Box - LAN
$IPT -A INPUT -p tcp --dport 4200 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 4200 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT

# 173 - 138 - 139 - 445 - 389 - 901 - Samba - LAN
$IPT -A INPUT -p tcp --dport 137 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 137 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 138 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 138 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 139 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 139 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 445 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 445 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 389 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 389 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p tcp --dport 901 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT
$IPT -A INPUT -p udp --dport 901 -m state --state NEW -s 10.0.0.0/24 -j ACCEPT


###############################################################
# Regole di sicurezza
# Block fragments and Xmas tree as well as SYN,FIN and SYN,RST
###############################################################

$IPT -A INPUT -p ip -f -j DROP
$IPT -A INPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
$IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPT -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP


###############################
# Concludo lo script firewall
###############################

# echo -n "Iptables successfully configured."

Descrizione delle regole precedenti

Dopo aver dichiarato alcune variabili passiamo alla pulizia delle chains e alla reinizializzazione dei contatori:

iptables -F #Cancellazione delle regole presenti nelle chains
iptables -X #Eliminazione delle chains non standard vuote
iptables -Z #Inizializzazione dei contatori (utile per il debugging)

Definiamo in seguito le policy di default per le 3 chains predefinite, settando tutto a DROP (in questo modo, tutto ciò che non è esplicitamente permesso è di fatto proibito!):

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

Le 2 policy built-in sono ACCEPT (che accetta tutti i pacchetti su una data chain) e DROP, che abbiamo già visto. Sono inoltre presenti 2 estensioni: LOG (relativa al modulo che si occupa del logging dell'attività del firewall) e REJECT (che ha fondamentalmente lo stesso effetto di DROP, ma risponde ai tentativi di connessione con un ICMP "port unreachable").
Infine, è possibile utilizzare altri due target speciali, RETURN e QUEUE, che però non approfondiremo.
Siamo finalmente giunti alle regole vere e proprie. Cominciamo accettando esplicitamente tutto il traffico, in uscita ed in entrata, sull'interfaccia di loopback. Si tratta di una scelta consigliata e assolutamente sicura, poiché il loopback non rappresenta un collegamento alla rete, ma viene utilizzato da alcune applicazioni per il loro corretto funzionamento:

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Come vediamo abbiamo specificato le due chains su cui agire (INPUT e OUTPUT), l'interfaccia relativa (lo) ed il target, ovvero la policy da seguire per i pacchetti che matchano la regola.
A questo punto vediamo all'opera una delle nuove funzionalità di iptables, il Rate Limiting, che ci permette di proteggerci dai SYN flood. Creando una nuova chain user-defined dove inviare TCP SYN, infatti, possiamo limitare il ratio di arrivo dei pacchetti ed evitare così attacchi di tipo Denial of Service (DoS), che mirano ad esaurire le risorse dei sistemi bersaglio:

iptables -N syn-flood
iptables -A INPUT -i $IFACE -p tcp syn -j syn-flood
iptables -A syn-flood -m limit limit 1/s limit-burst 4 -j RETURN
iptables -A syn-flood -j DROP

Quello che abbiamo fatto è creare una nuova chain user-defined chiamata "syn-flood", attraverso l'opzione -N. A questo punto abbiamo comunicato al Packet Filter di inviare tutti i pacchetti TCP con flag SYN settato (-p tcp syn) a tale chain e di limitare il ratio di arrivo di tali pacchetti.
Ora utilizziamo la Stateful Inspection per assicurarci che le nuove connessioni TCP siano dei pacchetti SYN e per rifiutare di conseguenza tutte quelle che non lo sono (possibili FIN scan o pacchetti malformati):

iptables -A INPUT -i $IFACE -p tcp syn -m state state NEW -j DROP

Infine passiamo a impostare le regole sui servizi offerti dal nostro server:

  1. Accesso pubblico al servizio
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT
  1. Accesso al servizio solo dalla nostra LAN
iptables -A INPUT -p tcp --dport 2605 -m state --state NEW -s 192.168.90.0/24 -j ACCEPT

Avviare il firewall

Arrivati a questo punto non ci resta che proteggere il file e renderlo eseguibile:

# chmod 700 /etc/iptables-firewall.sh
# chown root:root /etc/iptables-firewall.sh

Per avviare lo script direttamente al boot del nostro server sarà sufficiente modificare il file di configurazione delle impostazioni di rete:

# nano /etc/network/interfaces

aggiungendo una riga pre-up alla configurazione dell'interfaccia di rete pubblica:

auto eth1
iface eth1 inet static
             address 192.168.0.111
             netmask 255.255.255.0
             gateway 192.168.0.1
             dns-search somedomain.org
             dns-nameservers 195.238.2.21 195.238.2.22
             broadcast 192.168.0.0
             pre-up /etc/iptables-firewall.sh

Impostare il ban di IP ostili

Per impostare il blocco di un IP è sempre possibile agire manualmente, in questo modo:

# iptables -I INPUT -s 192.168.1.100 -j DROP

ma l'amministrazione e la gestione manuale dei ban agli indirizzi IP ostili non è praticabile.
A questo scopo ci può venire in aiuto uno strumento disponibile nei repository ufficiali di Debian:

# apt-get install ipset

Una volta installato, occorre creare la lista, che chiameremo blacklist:

# ipset create blacklist hash:net maxelem 1000000

Con il comando:

# ipset list

possiamo vedere l'elenco delle liste già create.
A questo punto è possibile aggiungere a mano il primo IP da bannare:

# ipset add blacklist 1.1.2.0/24
# ipset add blacklist 1.1.3.0/24

Controlliamo se i due IP sono stati aggiunti alla lista di ban:

# ipset list
Name: blacklist
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 1000000
Size in memory: 472
References: 0
Number of entries: 2
Members:
1.1.3.0/24
1.1.2.0/24

Aggiungere a mano tutti gli IP da bannare è un'impresa titanica; meglio affidarsi a liste già costruite, come quelle utilizzate qui di seguito, disponibili sotto licenza GPL.
Per prima cosa installiamo un tool per convertire le liste di iBlockList nel formato accettato da Ipset.

# apt-get install python-pip curl

Quindi recuperiamo uno script che ci permetterà di mantenere aggiornata la nostra lista di IP ostili:

# wget -O /usr/local/sbin/update-blacklist.sh https://raw.githubusercontent.com/trick77/ipset-blacklist/master/update-blacklist.sh
# chmod +x /usr/local/sbin/update-blacklist.sh
# mkdir -p /etc/ipset-blacklist
# wget -O /etc/ipset-blacklist/ipset-blacklist.conf https://raw.githubusercontent.com/trick77/ipset-blacklist/master/ipset-blacklist.conf

Quindi salviamo l'attuale configurazione di ipset:

# ipset save > /etc/ipset-blacklist/ip-blacklist.restore

Modifichiamo il file di configurazione adattandolo alle nostre necessità:

# nano /etc/ipset-blacklist/ipset-blacklist.conf

Impostiamo un cronjob che ogni domenica a mezzanotte aggiornerà le nostre liste:

crontab -e
0 0 * * 7 /usr/local/sbin/update-blacklist.sh /etc/ipset-blacklist/ipset-blacklist.conf

Aggiungiamo la nuova regola al nostro script iptables:

# nano /etc/iptables-firewall.sh

# Imposto le regole ipset
iptables -I INPUT -m set --match-set blacklist src -j DROP
iptables -I FORWARD -m set --match-set blacklist src -j DROP

e facciamo in modo che ipset sia impostato correttamente dopo un riavvio, aggiungendo la direttiva:

pre-up  ipset restore -! < /etc/ipset-blacklist/ip-blacklist.restore

alla sezione della scheda di rete principale nel file /etc/network/interfaces, stando attenti a inserirla prima della direttiva pre up impostata in precedenza per l'avvio dello script di iptables.



Sitografia

http://www.sitepoint.com/secure-server-iptables/
http://news.dediserve.com/2009/09/23/configuring-iptables-on-your-vps/
http://www.temporini.net/configurare-un-firewall-con-iptables
http://www.commedia.it/ccontavalli/docs-it/iptables/iptables4dummies/




Guida scritta da: Ferdybassi 16:02, 17 apr 2011 (CEST) Swirl-auth20.png Debianized 20%
Estesa da:
Verificata da:

Verificare ed estendere la guida | Cos'è una guida Debianized