Skip to content


iptables, rapida guida per chiudersi fuori da un server

1
2
3
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP

Fatto, vi siete chiusi fuori dal server e anche molti software ora non stanno più funzionando.

Voi ( e i cattivi) non potete più entrare perchè iptables è un firewall (porta tagliafuoco) e quindi sta scartando (-j DROP) tutte le richieste che arrivano al server e i software non funzionano più perchè iptables elimina anche i messaggi che passano per l’interfaccia di loopback (lo) che viene usata dai programmi per comunicare tra loro.

Iptables divide le sue regole in 3 tabelle (tables), ognuna dedicata ad un utilizzo diverso:

  • nat
  • mangle
  • filter

Ogni tabella ha delle chains (elenchi di regole) predefinite.
Per un utilizzo minimo ci basta la tabella mangle e 3 delle sue chains:

  • INPUT: dedicata hai pacchetti destinati all’host locale
  • OUTPUT: per i pacchetti uscenti
  • FORWARD: pacchetti destinati ad altri host

.
Naturalmente per mettere in produzione un firewall è meglio (molto meglio, essenziale) capire come funziona iptables e come i pacchetti attraversano tabelle e chains, non mi dilungo, leggetelo qui o in un qualunque altro sito dell’elenco che propone google.

Per farla breve, comunque, un pacchetto entra in una chain e si scorre l’elenco di regole contenute dalla prima all’ultima,applicandole immediatamente.
Di conseguenza un pacchetto che incontra un DROP viene scartato ed esce dalla chain.

Prima cosa da imparare: l’ordine delle regole conta.
Nel cattivo esempio di cui sopra non serve a niente aggiungere altre regole, siamo fuori e ci rimarremo.

Cancelliamo quindi le regole inserite sopra.
Abbiamo 3 sintassi possibili:

  1. Le regole non sono ancora persistenti, vanno esplicitamente salvate, quindi riavviare la macchina.
    Questo ci manda a ramengo l’uptime, ma noi perfortuna non ne siamo schiavi.
  2. Eliminarle tutte insieme
    1
    
    iptables -F
  3. Cancelliamo una regola alla volta:
    1
    2
    
    iptables -D {regola}
    iptables -D [CHAIN] [numero di riga(partendo da 1)]

    iptables -D si può usare inserendo il numero di riga in cui appare la regola oppure riscrivendo la regola con la sintassi usata per aggiungerla (-A oppure -I)

Verifichiamo di esserci liberati delle regole chiedendone la lista (-L):

  • una elenco semplice
    1
    
    iptables -L
  • più informazioni

    1
    
    iptables -L -v
  • con numeri di linea (così magari usiamo con più tranquillità l’opzione -D)
    1
    
    iptables -L --line-numbers

A questo punto possiamo prendere il tablet (non un iPad per favore) su cui abbiamo segnato i servizi offerti e le porte che usano per iniziare ad appendere le regole.
Per semplicità userò negli esempi solo le chain INPUT e OUTPUT.

La nostra priorità è di consentire tutto il traffico sull’interfaccia di loopback (lo), quindi:

1
2
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -i lo -j ACCEPT

spiegazione:

iptables, appendi (-A) alla chain INPUT la regola che tutti i pacchetti che passano per l’interfaccia (-i lo) sono accettati (-j ACCEPT)

Al primo posto dei servizi permessi c’è sicuramente ssh quindi vogliamo che siano possibili connessioni entranti e uscenti sulla porta 22 (default).

1
iptables -A INPUT --dport 22 -j ACCEPT

Questa regola dice ad iptables di accettare le connessioni entranti dirette alla porta 22.
Questa regola base può (e deve) essere migliorata con ulteriori vincoli:

  • accettare solo uno specifico protocollo, nel caso specifico tcp
    1
    
    -p tcp
  • verificare lo stato della connessione. Nel caso di connessioni entranti dobbiamo accettare sia comunicazioni nuove che già attive (NEW ed ESTABLISHED)
    1
    
    -m state --state NEW,ESTABLISHED

    attenzione, non di devono essere spazi intorno alla virgola.

  • potremmo poi voler accettare solo le connessioni dirette ad un solo IP
    1
    
    -d [indirizzo ip]
  • oppure consentire l’accesso solo ad uno specifico IP/rete
    1
    
    -s [indirizzo ip]/[netmask]

    per lasciare libera la connessione si può non specificare nulla oppure usare

    1
    
    -s 0/0
  • eventualmente si può anche specificare da che porta deve partire la connessione affinchè sia accettata
    1
    
    --sport [numero di porta]

    per consentire un intervallo

    1
    2
    3
    
    --sport [porta partenza]:[porta base]
    es.
    --sport 1024:65535

Una regola ragionevolmente restrittiva da cui partire diventa quindi:

1
iptables -A INPUT -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

Siccome dopo diremo al firewall di scartare tutti i pacchetti entranti e uscenti che non siano altrimenti regolati dobbiamo anche dire ad iptables cosa fare delle risposte che richiede il client ssh:

1
iptables -A OUTPUT -p tcp -m state --state ESTABLISHED -j ACCEPT

La sintassi è identica, cambia solo la chain a cui appenderlo e non sono specificate le porte della connessione.

A questo punto non rimane che reiterare la logica applicata per ssh per ogni servizio a cui vogliamo consentire l’accesso.

Finito l’elenco dei servizi blocchiamo tutto di nuovo:

1
2
3
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP

A questo punto un port scanner tipo nmap vi segnalerà solo la porta ssh disponibile e l’output di iptables -L dovrebbe essere:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW,ESTABLISHED 
DROP       all  --  anywhere             anywhere            
 
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
 
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere            tcp spt:ssh dpts:login:65535 state ESTABLISHED 
DROP       all  --  anywhere             anywhere

Il parametro -A appende una regola in fondo alla chain selezionata, volendo inserire una regola in una posizione specifica si usa:

1
iptables -I INPUT 3 {regola}

Che ci consente di appendere {regola} alla terza posizione della chain (sempre partendo da 1).

Lavorando con i firewall è purtroppo molto facile fare errori che poi richiedono di loggarsi in locale sulla macchina per essere riparati.
Siccome più spesso che no il server è a qualche chilometro dalla tastiera su cui stiamo lavorando la seconda semplice precauzione da prendere è di spegnere il firewall ogni 5 minuti

1
2
3
4
crontab -e
  */5 * * * * /sbin/service iptables stop (centos)
  */5 * * * * /etc/init.d/iptables stop (debian-like)
  */5 * * * * /sbin/iptables -F (per tutte le stagioni)

Ovviamente la prima precauzione da prendere è provare la configurazione sul server di test.

Riassunto dei comandi

  • visualizzare le regole
    1
    
    iptables -L -v --line-number
  • eliminare tutte le regole
    1
    
    iptables -F
  • eliminare una regola
    1
    2
    
    iptables -D [chain] [numero regola]
    iptables -D [chain] {sintassi regola}
  • appendere una] regola in fondo alla chain
    1
    2
    3
    
    iptables -A [chain] {sintassi regola}
    es.
    iptables -A INPUT -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT (per ssh)
  • appendere una regola in posizione specifica
    1
    
    iptables -I [chain] [numero riga] {sintassi regola}

Iptables ha molti più parametri di così.
Per un firewall sicuro ci vuole molto più studio di questo semplice tutorial, si possono creare nuove chains e modificare i pacchetti prima del routing e dopo il routing; genericamente si può gestire ogni aspetto dei flussi entranti e uscenti.

Posted in system administration.

Tagged with , , , , , .


0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.



Some HTML is OK

or, reply to this post via trackback.