Impostare un firewall iptables per proteggere il traffico tra server

20 agosto 2015 Firewall Ubuntu

Introduzione

La distribuzione delle componenti discrete [i singoli componenti, NdT] nella configurazione della vostra applicazione su nodi differenti è un modo comune per ridurre il carico e per iniziare a fare uno scaling orizzontale [rispetto a quello verticale ottenuto su multicore, NdT]. Un tipico esempio è la configurazione di un database su un server separato dalla sua applicazione. Sebbene ci siano un gran numero di vantaggi usando tale configurazione, la connessione in rete comporta un’altra serie di questioni sulla sicurezza.

In questa guida verrà mostrato come impostare un semplice firewall su ogni server in una configurazione distribuita. Configureremo la nostra policy per consentire il traffico legittimo tra le componenti, negando altro traffico.

Come dimostrazione, in questa guida useremo due Ubuntu server 14.04. Uno avrà una istanza di WordPress con webserver Nginx e l’altro ospiterà il database MySQL per WordPress. Anche se useremo questa configurazione come esempio, dovreste essere in grado di estrapolare le tecniche usate per soddisfare le esigenze del vostro server.

Requisiti

Per iniziare, dovrete avere due nuovi Ubuntu server 14.04 . Aggiungete un classico account utente con privilegi sudo su ciascuno. Per informazioni su come farlo correttamente, leggete la Guida alla configurazione iniziale del server per Ubuntu 14.04.

L’installazione dell’applicazione che andremo a rendere sicura è basata su questa guida. Se la si desidera seguire, configurate i server dell’applicazione e del database come indicato in questo tutorial.

Impostare un firewall di base

Inizieremo con l’implementazione di una configurazione del firewall di base per ciascuno dei nostri server. La politica che metteremo in atto richiede un approccio orientato alla sicurezza. Bloccheremo quasi tutto il traffico che non sia SSH e poi bucherelleremo il firewall per la nostra specifica applicazione.

Il firewall di questa guida fornisce la configurazione di base di cui abbiamo bisogno. Installate il pacchetto iptables-persistent ed incollate le regole di base nel file /etc/iptables/rules.v4:

$ sudo apt-get update
$ sudo apt-get install iptables-persistent
$ sudo nano /etc/iptables/rules.v4
                       /etc/iptables/rules.v4

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Commit the changes
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

Se fate tutto ciò in un ambiente di produzione non ricaricate ancora le regole del firewall. Il caricamento dell’insieme delle regole di base qui illustrato interromperà immediatamente la connessione tra l’applicazione e il database server. Prima di ricaricare dovremo adeguare le regole in modo che rispecchino le nostre esigenze operative.

Trovare le porte usate dai servizi

Per aggiungere le eccezioni che consentano la comunicazione tra i nostri componenti, abbiamo bisogno di conoscere le porte di rete utilizzate. Siamo riusciti a trovare le porte di rete corrette esaminando i nostri file di configurazione, ma un metodo per trovare le porte corrette a prescindere dall’applicazione è semplicemente quello di verificare quali servizi accettano connessioni su ciascuna delle nostre macchine.

Per scoprirlo possiamo usare lo strumento netstat. Dato che la nostra applicazione sta comunicando solo su IPv4 aggiungeremo l’argomento -4 ma se state usando anche IPV6 potete pure toglierlo. Gli altri argomenti di cui abbiamo bisogno per trovare i nostri servizi in esecuzione sono -plunt.

Sul web server dovremmo avere qualcosa di simile a questo:

sudo netstat -4plunt

Output:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1058/sshd
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      4187/nginx

La prima colonna evidenziata mostra l’indirizzo IP e la porta sulla quale il servizio evidenziato verso la fine della linea è in ascolto. Lo speciale indirizzo 0.0.0.0 vuol dire che il servizio in questione è in ascolto su tutti gli indirizzi disponibili.

Sul nostro database server dovremmo vedere qualcosa di simile a questo:

sudo netstat -4plunt

Output:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1097/sshd
tcp        0      0 192.0.2.30:3306     0.0.0.0:*               LISTEN      3112/mysqld

Queste colonne si possono leggere esattamente allo stesso modo. Nell’esempio precedente l’indirizzo 192.0.2.30 rappresenta l’indirizzo IP privato del database server. Per motivi di sicurezza, nella configurazione dell’applicazione abbiamo bloccato MySQL per l’interfaccia privata.

Prendete nota dei valori che trovate in questa fase. Questi sono i dati di rete di cui abbiamo bisogno al fine di modificare la configurazione del nostro firewall.

Nel nostro esempio possiamo notare che, sul nostro web server, dobbiamo fare in modo che siano accessibili le seguenti porte:

  • La porta 80 su tutti gli indirizzi
  • La porta 22 su tutti gli indirizzi (già prevista nelle regole del firewall)

Il nostro database server dovrà garantire che siano accessibili le seguenti porte:

  • La porta 3306 sull’indirizzo 192.0.2.30 (o l’interfaccia ad esso associata)
  • La porta 22 su tutti gli indirizzi (già prevista nelle regole del firewall)

Cambiare le regole del firewall sul web server

Ora che abbiamo le informazioni che ci servono sulle porte, modificheremo le regole del firewall del nostro web server. Aprite il file delle regole nel vostro editor con i privilegi di sudo:

sudo nano /etc/iptables/rules.v4

Sul web server abbiamo bisogno di aggiungere la porta 80 alla nostra lista del traffico ricevibile. Dal momento che il server è in ascolto su tutti gli indirizzi disponibili, non limiteremo la regola per interfaccia o per indirizzo di destinazione.

I nostri visitatori web, per connettersi, useranno il protocollo TCP. La nostra struttura di base ha già una chain custom denominata TCP che gestisce le eccezioni delle applicazioni TCP. Possiamo aggiungere la porta 80 a tale chain proprio sotto l’eccezione per la nostra porta SSH:

                        /etc/iptables/rules.v4

*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT

. . .

Il nostro web server avvierà la connessione con il nostro database server. Il nostro traffico in uscita non è limitato dal firewall ed il traffico in entrata, associato alle connessioni già stabilite è consentito. Dunque al fine di permettere la connessione, su questo server non ci sarà bisogno di aprire alcuna porta aggiuntiva.

Quando avete finito salvate e chiudete il file. Il web server ha ora una politica del firewall che autorizza tutto il traffico legittimo, bloccando tutto il resto.

Testate il file delle regole per gli errori di sintassi:

sudo iptables-restore -t < /etc/iptables/rules.v4

Se non vengono visualizzati errori di sintassi, ricaricate il firewall per rendere attivo il nuovo insieme di regole:

sudo service iptables-persistent reload

Cambiare le regole del firewall sul database server

Sul server che ospita il database è necessario consentire l’accesso alla porta 3306 all’indirizzo IP privato del nostro server. Nel nostro caso l’indirizzo era 192.0.2.30. Siamo in grado di limitare l’accesso destinato a questo indirizzo specifico oppure possiamo limitare l’accesso confrontando l’interfaccia che viene assegnata a quell’indirizzo.

Per trovare l’interfaccia di rete associata a tale indirizzo digitate:

ip -4 addr show scope global

Output:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1
       valid_lft forever preferred_lft forever

Le aree evidenziate mostrano che l’interfaccia eth1 è associata a tale indirizzo.

Successivamente registreremo le regole del firewall sul database server. Su tale server aprite il file delle regole con i privilegi sudo:

sudo nano /etc/iptables/rules.v4

Anche in questo caso ci sarà l’aggiunta di una regola alla nostra chain TCP al fine di creare un’eccezione per poter collegare tra loro il web server e il database server.

Se si desidera limitare l’accesso in base all’effettivo indirizzo in questione, dovrete aggiungere la regola in questo modo:

                       /etc/iptables/rules.v4

*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT

. . .

Se si preferisce consentire l’eccezione basata sull’interfaccia che ospita tale indirizzo, è invece possibile aggiungere una regola simile a questa:

                       /etc/iptables/rules.v4

*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT

. . .

Quando avete finito salvate e chiudete il file.

Verificate la presenza di errori di sintassi con questo comando:

db_server$ sudo iptables-restore -t < /etc/iptables/rules.v4

Quando siete pronti ricaricate le regole del firewall:

db_server$ sudo service iptables-persistent reload

Ora entrambi i server dovrebbero essere protetti senza che tra loro venga limitato il flusso di dati di cui vi è necessità.

Conclusioni

Nel momento in cui si realizza un’applicazione, la realizzazione di un buon firewall dovrebbe sempre far parte del piano di sviluppo. Anche se abbiamo usato questa configurazione utilizzando i due server con Nginx e MySQL per fornire un esempio con WordPress, le tecniche mostrate sopra sono applicabili indipendentemente dalle specifiche delle tecnologie scelte.

Per ulteriori informazioni sui firewall e su iptables in particolare, date un’occhiata alle seguenti guide:

 

Autore: Justin Ellingwood

Traduzione dell’articolo: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-iptables-firewall-to-protect-traffic-between-your-servers Copyright © 2016 DigitalOcean™ Inc.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*