Impostare un firewall con uno script iptables

Da Guide@Debianizzati.Org.

Debian-swirl.png Versioni Compatibili
Tutte le versioni supportate di Debian

Indice

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

# 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


###############################################################
# 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

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

Strumenti personali
Namespace
Varianti
Azioni
Navigazione
Risorse
Strumenti