%% firewall.tex
%%
%% Copyright (C) 2003-2018 Simone Piccardi and Truelite Srl.
%%
%% This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
%% International License. To view a copy of this license, visit
%% \url{http://creativecommons.org/licenses/by-sa/4.0/} or send a letter to
%% Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
%%
%% Corso Linux : Dispense dei corsi GNU/Linux di Truelite
%%
%% S. Piccardi Oct. 2003
%% 
%% firewall.tex: sezione su firewall e VPN
%%

%
% To avoid these definition when included from outside
%
\providecommand{\setflag}{\newif \ifwhole \wholefalse} \setflag

\ifwhole\else
\documentclass[10pt,twoside]{book} 
\usepackage[paperwidth=18.91cm,paperheight=24.589cm,
inner=2.5cm,outer=1.8cm,bottom=3.3cm,top=2.3cm]{geometry}

\newcommand{\BookFullTitle}{Sicurezza con GNU/Linux}
\newcommand{\BookEdition}{Prima edizione}

\input{../commons/packages2}
\input{../commons/front2}

\makeindex

\begin{document}

\pagenumbering{roman} 

\begin{titlepage}
    \centering
    \phantom{}
    \vfill
    {\Huge \textbf{\textsf{Firewall e VPN con GNU/Linux}}}
    \vfill
    {\huge \textsf{Simone Piccardi}}

    {\large \textsf{piccardi@truelite.it}}

    \vspace{2.5cm} {\textsf{Truelite Srl \hfill http://www.truelite.it \hfill
      info@truelite.it}}
\end{titlepage}

\ClearShipoutPicture

\newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}
\cleardoublepage}}

\newcommand{\CopyrightRange}{2003-2014}
\newcommand{\BookFullTitle}{Firewall e VPN con GNU/Linux}
\newcommand{\BookEdition}{Prima edizione}
\input{../commons/seconda}

\clearemptydoublepage
%\ifx\hcode\undefined\else
\tableofcontents
%\fi

\clearemptydoublepage
%\include{macro}
%\include{pref}
\clearemptydoublepage
\mainmatter

\fi


\chapter{Firewall}
\label{cha:firewall}


\section{Cenni di teoria dei firewall}
\label{sec:fw_theory}

In questa sezione prenderemo in esame le basi teoriche ed i criteri generali
che si applicano alla realizzazione di un firewall; in particolare
introdurremo alcuni concetti essenziali di sicurezza delle reti, definiremo il
ruolo dei firewall in questo ambito e prenderemo in esame i criteri per la
loro dislocazione.


\subsection{Un'introduzione alla sicurezza delle reti}
\label{sec:fw_net_security}

Prima di passare alla descrizione dei firewall e dei relativi criteri di
impiego è opportuno fare una breve introduzione alle tematiche della sicurezza
delle reti, la cui comprensione è necessaria per poter realizzare un uso
efficace dei firewall.

In un mondo ideale infatti i firewall sono completamente inutili. Se tutto il
software che si pone in uso non presentasse problemi di sicurezza, se tutte le
configurazioni utilizzate fossero corrette e se tutti i meccanismi di
controllo non fossero eludibili, sarebbe impossibile avere accessi non
autorizzati e pertanto i firewall non servirebbero a nulla.

Nel mondo reale però tutti i programmi hanno errori e presentano
vulnerabilità, le configurazioni vengono sbagliate, il software viene
installato male, i controlli vengono elusi, il che comporta la possibilità
che, nelle forme più varie, diventino possibili accessi non autorizzati.

In genere comunque i problemi di sicurezza più comuni sono relativi ad errori
di programmazione. Il caso più comune è quello di un mancato (o incompleto)
controllo dei dati che vengono inviati al programma nella supposizione,
sbagliata, che questi abbiano una certa forma. Per cui inviando dati in una
forma non prevista si può bloccare il funzionamento dello stesso, o anche
fargli eseguire del codice estraneo (si ricordi quanto visto in
sez.~\ref{sec:security_risk}).

Buona parte di questi problemi possono essere superati in maniera molto
efficace anche senza ricorrere all'uso di un firewall. La riduzione
all'essenziale dei programmi da installare (parafrasando Ford un servizio non
installato non si può violare), scelta di programmi stabili e realizzati con
attenzione ai problemi di sicurezza, la costanza nell'eseguire gli
aggiornamenti (si stima che bel oltre il 90\% delle violazioni di sicurezza
sia dovuta all'uso versioni vulnerabili non aggiornate) l'attenzione a tutti
gli aspetti delle configurazioni (ed in particolare l'uso delle funzionalità
di controllo degli accessi che tutti i principali programmi mettono a
disposizione) bastano da soli a rendere ragionevolmente sicura una macchina.

Detto questo uno potrebbe allora chiedersi a che pro installare un firewall,
visto che almeno in teoria se ne potrebbe fare a meno. In realtà uno dei
criteri fondamentali nella sicurezza è sempre quello della ridondanza, per cui
anche la semplice duplicazione con un meccanismo indipendente dei controlli di
accesso sarebbe di per sé una buona ragione. A questo poi si può aggiungere il
fatto che un firewall permette di costruire un punto di accesso unificato per
il traffico di rete, permettendone un controllo generale e non limitato alle
funzionalità (che potrebbero non esistere neanche) dei singoli programmi o
delle singole macchine.


\subsection{Cosa è un firewall}
\label{sec:fw_what_fw}

Il primo passo per addentrarsi nella pratica delle tecnologia di protezione
basate su firewall è allora quello di capire cos'è un firewall, cosa fa e a
cosa serve. Troppo spesso infatti il firewall è ritenuto un po' come la
panacea di tutti i mali, e si pensa che basti installarne uno per risolvere
tutti i problemi di sicurezza di una rete.

Un firewall, come la parola suggerisce, è una sorta di porta blindata che
permette di bloccare i tentativi di accesso ad una rete, anche se in realtà la
parola inglese fa più propriamente riferimento alle porte tagliafuoco usate
per bloccare la propagazione degli incendi.  Ma come una porta blindata serve
a poco se le finestre sono senza inferriate, ancora meno se la chiave della
serratura è sotto lo zerbino, e per niente se i ladri li fate entrare voi, lo
stesso vale per un firewall.

Un firewall posto fra voi ed Internet cioè non sarà mai in grado di
proteggervi da attacchi provenienti da altri accessi meno controllati della
vostra rete, ad esempio perché qualcuno ha attaccato un modem al suo PC e apre
una connessione da lì, o c'è una rete wireless vulnerabile e qualcuno ci si
aggancia. E un firewall non è in grado di proteggervi dalle vulnerabilità
delle applicazioni cui dovete accedere da remoto (se ad esempio un servizio
aperto è vulnerabile, il firewall non vi sarà di nessun aiuto), né tantomeno
dagli attacchi portati da utenti interni alla rete protetta.

Un firewall dunque non è affatto il sostituto di una buona politica di
sicurezza, di cui costituisce solo uno (per quanto importante) degli
strumenti.  Lo scopo specifico di un firewall è in realtà solo quello di
permettervi di suddividere opportunamente la vostra rete, in modo da potervi
applicare politiche di sicurezza diverse (più o meno restrittive) a seconda
delle differenti esigenze di ciascuna parte.

Un altro aspetto dei firewall che è bene comprendere è che benché questi
possano essere usati per filtrare il traffico di rete, il livello a cui
possono farlo spesso è molto superficiale. Un firewall infatti potrà bloccare
il traffico proveniente da certi indirizzi o diretto a certi servizi, ma di
norma un firewall non è assolutamente in grado di riconoscere il contenuto del
traffico di rete.

Se pertanto si vuole fare del \itindex{content~filtering} \textit{content
  filtering} (ad esempio filtrare le pagine web in base al loro contenuto o la
posta per eliminare dei virus) occorrerà utilizzare uno strumento dedicato in
grado di esaminare e classificare il contenuto dei protocolli di livello
superiore e questo non è di norma un firewall, e anche se ci sono programmi
chiamati ``firewall'' che hanno di queste funzionalità, tecnicamente non sono
qualificabili come tali.

Un firewall infatti agisce ai livelli più bassi dei protocolli di rete e non è
in grado di analizzare il contenuto dei pacchetti che riceve,\footnote{ci sono
  strumenti dedicati a questo, come gli IDS, che tratteremo nel
  cap.~\ref{cha:ids}.} e nelle forme più elementari esso è in grado di operare
solo in base ad alcuni dati presenti nel singolo pacchetto, andando ad
osservare i valori contenuti nelle intestazioni dei vari protocolli di rete. I
firewall più elementari di questo tipo sono detti \textit{stateless}.

Con l'evolversi della tecnologia ci è resi conto che la sola selezione in base
al contenuto delle intestazioni dei pacchetti non sempre è sufficiente ed
esistono situazioni in cui può essere necessario identificare del traffico che
non è riconoscibile solo in base al contenuto del singolo pacchetto. I
firewall più evoluti in grado di superare questo limite sono allora detti
\textit{stateful} in quanto sono in grado di classificare, osservando il
traffico nel suo insieme, i vari pacchetti in un insieme di
stati,\footnote{classicamente si intendeva indicare con \textit{stateful} un
  firewall che riproduce la macchina a stati del protocollo TCP, in realtà il
  concetto è stato esteso per coprire anche \textsl{stati} di protocolli che
  non supportano neanche il concetto di connessione (cui di solito lo stato fa
  riferimento) e non è comunque detto che la macchina degli stati debba essere
  riprodotta interamente.}  permettendo la selezione in base a questi ultimi.

Si tenga presente che questo non ha comunque nulla a che fare con il
\textit{content filtering}, e gli stati non vengono definiti in termini del
contenuto dei dati dei pacchetti, quanto piuttosto in termini di relazioni fra
gli stessi, come ad esempio tutti i pacchetti che fanno parte di una certa 
connessione di rete.


\subsection{Principi di dislocamento dei firewall}
\label{sec:fw_deploy}

Il primo passo da fare per installare un firewall è quello di prendere carta e
penna (o l'equivalente strumento preferito) per fare un bello schema della
rete che si vuole proteggere, evidenziando come le varie parti sono connesse
fra di loro, dove viene effettuata la connessione verso l'esterno, e decidere
quali sono le macchine che devono essere raggiunte dall'esterno e quali no.
Inoltre dovranno essere determinate quali sono le interrelazioni fra le varie
parti della rete, ad esempio se è proprio necessario che l'amministrazione
abbia accesso anche alle macchine del reparto ricerca/sviluppo e viceversa.

Per quanto possa sembrare banale, la decisione sulla \textsl{dislocazione} di
un firewall è in realtà il cuore del problema, e spesso anche nella più
semplice delle configurazioni (quella con un solo accesso alla rete esterna)
si rischiano di fare degli errori che possono compromettere la sicurezza; ad
esempio ci si può dimenticare di bloccare le connessioni dalle macchine sulla
DMZ (vedremo a breve di che si tratta) alla rete interna, aprendo la
possibilità di un attacco a partire da quest'ultime.

La forma più elementare di dislocazione di un firewall è quella mostrata in
fig.~\ref{fig:simple_net}, dove il firewall serve soltanto a proteggere la
rete interna rispetto all'accesso ad internet. Nel caso di Linux se si ha un
modem invece che un router esterno, si può fare eseguire anche la condivisione
della connessione attraverso la stessa macchina.

\begin{figure}[htb]
  \centering
  \includegraphics[width=10cm]{images/simplenet}
  \caption{Disposizione elementare di un firewall posto a protezione di una
    rete con un singolo punto di accesso all'esterno che non necessita di
    accesso da remoto.}
  \label{fig:simple_net}
\end{figure}

Il compito del firewall in questo caso sarà quello di consentire alle
connessioni provenienti dalla rete interna di uscire verso internet (ricevendo
indietro le relative risposte), ma di bloccare invece le connessioni
provenienti dall'esterno e dirette verso l'interno.

Questa è la forma più elementare di firewall, a parte forse il cosiddetto
\textit{personal firewall}, in cui si usa un programma di firewall per
proteggere una macchina singola da tutte le connessioni entranti.  In questa
configurazione di rete non c'è molto da dire, in quanto le direzioni dei
flussi dei dati sono univoche, e la topologia della rete è elementare; la
gestione della sicurezza pertanto è molto semplice e richiede solo di non
consentire dall'esterno nessun accesso all'interno.

Una situazione del genere però è anche di scarsa utilità, se non nel caso di
un ufficio che condivide una connessione ad internet, proprio in quanto non
consente l'accesso dall'esterno a nessuna macchina interna. Il solo introdurre
questo requisito rende la configurazione di fig.~\ref{fig:simple_net}
inadeguata allo scopo. Infatti se anche si usasse il firewall per consentire
l'accesso ad una ed una sola delle macchine all'interno della rete, questo già
porterebbe ad una forte diminuzione della sicurezza della rete, dovendosi a
questo punto tenere in conto la possibilità di un attacco a partire dalla
macchina raggiungibile dall'esterno, attacco prima impossibile, adesso
subordinato al fatto che il servizio raggiungibile dall'esterno non sia
vulnerabile.

\begin{figure}[htb]
  \centering
  \includegraphics[width=10cm]{images/dmznet}
  \caption{Disposizione standard di un firewall messo a protezione di una
    singola rete con un solo punto di accesso all'esterno e macchine
    accessibili da remoto.}
  \label{fig:DMZ_net}
\end{figure}

Per questo, quando si devono fornire servizi raggiungibili dall'esterno che
possono introdurre dei rischi di compromissione (i servizi web sono l'esempio
più comune), si deve usare una disposizione della rete diversa, introducendo
quella che viene chiamata in gergo una \itindex{De-Militarized~Zone~(DMZ)}
\textsl{zona demilitarizzata}, o più comunemente DMZ (sigla dell'inglese
\textit{De-Militarized Zone}), secondo lo schema di fig.~\ref{fig:DMZ_net}.

In questo caso i servizi che devono essere raggiungibili dall'esterno devono
essere messi su un tratto di rete a parte, separato dalla rete interna. Le
connessioni dalla rete interna devono poter raggiungere sia internet che la
zona smilitarizzata, mentre questa deve poter solo raggiungere internet, ma
non la rete interna. In questo modo anche in caso di vulnerabilità di un
servizio sulla DMZ la rete interna resta protetta.

Nel caso specifico si è considerato che dietro al firewall ci sia una unica
rete locale, ma non è detto che debba essere così; si possono avere situazioni
più complesse, con più reti separate. Di nuovo in questo caso occorre prima
capire quali sono le interrelazioni fra le varie reti, e quali eventuali altri
livelli di protezione si vogliono raggiungere. 



\section{Il \textit{netfilter} di Linux}
\label{sec:fw_netfilter}

In questa sezione prenderemo in esame direttamente il funzionamento del
cosiddetto \textit{netfilter} di Linux, il sistema di manipolazione e
filtraggio dei pacchetti implementato dal kernel, che consente, fra le altre
cose, di costruire router e firewall estremamente potenti e flessibili.


\subsection{La struttura del \textit{netfilter}}
\label{sec:fw_netfilter_structure}

Il \textit{netfilter} è quella parte del kernel che si occupa del filtraggio e
della manipolazione dei pacchetti della rete. Per poterla utilizzare deve
essere stato abilitato il relativo supporto nel kernel, cosa che avviene
normalmente per quelli installati da tutte le principali distribuzioni.

In fig.~\ref{fig:netfilter_scheme} è riportato lo schema di funzionamento del
cuore del \textit{netfilter} di Linux. Esso consiste in una infrastruttura che
consente di inserire all'interno della parte del kernel che gestisce i
protocolli di rete una serie di \textsl{punti di aggancio} (detti
\textit{hooks}, ed identificati in figura dagli ovali) in cui i vari pacchetti
che arrivano sullo stack dei protocolli di rete possono essere esaminati e
manipolati.

\begin{figure}[htb]
  \centering
  \includegraphics[width=10cm]{images/netfilter}
  \caption{Lo schema del \textit{netfilter} di Linux.}
  \label{fig:netfilter_scheme}
\end{figure}

Vedremo più avanti che ciascun punto di aggancio corrisponde ad una delle
cosiddette \textsl{catene predefinite} del comando \texttt{iptables}; a questo
livello però il concetto di catena non esiste ancora, si tratta solo della
possibilità di far eseguire, attraverso le funzioni che grazie al
\textit{netfilter} si possono agganciare a ciascun punto, una serie di
elaborazioni sui pacchetti che stanno transitando, potendo decidere la sorte
di questi ultimi.

L'infrastruttura del \textit{netfilter} infatti consente alle varie funzioni
poste nei punti di aggancio di decidere il destino dei pacchetti, facendoli
procedere all'interno del \textit{netfilter}, oppure scartandoli, rinviandoli
sul punto di accesso (così che possano essere analizzati da altre funzioni),
trattenendoli per ulteriori elaborazioni o inviandoli su una coda da cui
possono essere letti da processi in user space.

Questo rende il funzionamento del \textit{netfilter} completamente modulare,
in quanto con gli opportuni moduli diventa possibile inserire nel kernel
l'infrastruttura per tutte le funzionalità avanzate come il \textit{connection
  tracking} e quelle relative a qualunque criterio di selezione e filtraggio
dei pacchetti, fino al limite, non molto pratico, di potersi scrivere il
proprio firewall direttamente in C, come un modulo del kernel.

Vediamo allora in maggior dettaglio il funzionamento del meccanismo illustrato
in fig.~\ref{fig:netfilter_scheme}; i pacchetti in arrivo da una interfaccia
di rete, così come emergono dal relativo dispositivo (fisico o virtuale che
sia), arrivano, dopo aver passato dei controlli elementari di integrità
(pacchetti troncati, corrotti, o con il valore delle \textit{checksum} di IP
non corrispondente vengono scartati a questo livello, prima di entrare nel
\textit{netfilter}) al primo punto di aggancio, indicato nello schema di
fig.~\ref{fig:netfilter_scheme} con l'ovale \texttt{PREROUTING}.

Una volta attraversato il \texttt{PREROUTING} i pacchetti vengono passati al
codice di gestione dell'instradamento (indicato in
fig.~\ref{fig:netfilter_scheme} dal riquadro marcato \textit{routing
  decision}), che deve decidere se il pacchetto è destinato ad un indirizzo
locale della macchina o deve essere reinviato verso un'altra rete, passando
per un'altra interfaccia. Per questo è sempre sul \texttt{PREROUTING} che
vengono effettuate alcune di quelle operazioni di \textsl{traslazione degli
  indirizzi} (il cosiddetto NAT, \itindex{Network~Address~Translation~(NAT)}
acromino di \textit{Network Address Translation}) che sono una delle
caratteristiche più interessanti dei firewall contemporanei.

In particolare è qui, prima che i pacchetti entrino nel meccanismo della
\textit{routing decision} che ne stabilisce la destinazione finale, che si
devono eseguire le manipolazioni sui pacchetti che permettono di cambiarla con
il cosiddetto \itindex{Destination~NAT~(DNAT)} DNAT (acronimo di
\textit{Destination Network Address Translation}). Si tratta in questo caso di
modificare l'indirizzo di destinazione dei pacchetti in arrivo, in modo da
cambiare, in maniera trasparente per chi lo ha iniziato, la destinazione di un
certo flusso di dati.\footnote{questo comporta, grazie all'uso del
  \textit{connection tracking} che vedremo in sez.~\ref{sec:fw_conntrack},
  anche la corrispondente modifica degli indirizzi sorgente delle relative
  risposte, che però viene effettuata automaticamente sui pacchetti in uscita
  senza dover scrivere ulteriori regole.}

Se il pacchetto è destinato ad un indirizzo locale esso proseguirà il suo
percorso nel \textit{netfilter} attraversando un secondo punto di aggancio,
indicato in fig.~\ref{fig:netfilter_scheme} con l'ovale \texttt{INPUT}, prima
di poter essere recapitato al processo a cui è diretto, se esso esiste, o
generare un opportuno messaggio di errore, qualora questo sia
previsto.\footnote{si tenga presente che un tale messaggio, qualora emesso,
  seguirà lo stesso percorso di tutti i pacchetti che escono dalla nostra
  macchina; non ha alcun senso pensare che possa tornare indietro secondo il
  percorso fatto dal pacchetto di andata.} È sull'\texttt{INPUT} che in genere
si esegue il filtraggio dei pacchetti destinati alla nostra macchina.

Se invece il pacchetto deve essere reinviato ad un indirizzo su una rete
accessibile attraverso un'altra interfaccia dovrà prima attraversare un
secondo punto di aggancio, indicato in fig.~\ref{fig:netfilter_scheme} con
l'ovale \texttt{FORWARD}, ed infine l'ultimo punto, indicato con l'ovale
\texttt{POSTROUTING}, prima di arrivare sull'interfaccia di uscita.

La ragione di questo doppio passaggio è che il filtraggio dei pacchetti che
attraversano soltanto la nostra macchina per un'altra destinazione viene
effettuato nel \texttt{FORWARD}, dato che attraverso il \texttt{POSTROUTING}
oltre ai pacchetti in transito dalla nostra macchina, possono passare anche i
pacchetti generati direttamente su di essa.

Infatti, tutti i pacchetti generati localmente, compresi anche i pacchetti
generati in risposta a quelli ricevuti in ingresso attraverso
l'\texttt{INPUT}, devono passare per un altro punto di aggancio, indicato in
fig.~\ref{fig:netfilter_scheme} con l'ovale \texttt{OUTPUT}, prima di
raggiungere anch'essi il \texttt{POSTROUTING}. Pertanto è su \texttt{OUTPUT}
che è possibile filtrare quanto viene inviato verso l'esterno a partire da
processi locali o direttamente dal kernel (ad esempi messaggi di errore) in
risposta a pacchetti arrivati in ingresso.

Infine è sul \texttt{POSTROUTING} che si possono compiere altre operazioni di
NAT, ed in particolare le manipolazioni sugli indirizzi sorgente dei pacchetti
per il cosiddetto \itindex{Source~Network~Address~Translation~(SNAT)} SNAT
(acronimo di \textit{Source Network Address Translation}) in cui si modifica
l'indirizzo sorgente dei pacchetti in uscita in modo da poter cambiare, in
maniera trasparente per chi lo riceve, l'origine di un certo flusso di
dati.\footnote{ed in questo caso grazie al \textit{connection tracking},
  verranno modificati automaticamente gli indirizzi di destinazione dei
  pacchetti in ingresso ottenuti come risposta.}  In questo modo ad esempio si
effettua il cosiddetto \textit{masquerading}, in cui si fa figurare un
router/firewall come origine delle connessioni, anche se queste originano da
computer posti in una rete interna.


\subsection{Il sistema di \textit{IP Tables}}
\label{sec:fw_tables_chains}

Lo schema illustrato in sez.~\ref{sec:fw_netfilter_structure} riguarda la
struttura di basso livello del kernel, su di esso però è stato costruita tutta
una infrastruttura di più alto livello per la gestione dei pacchetti chiamata
\textit{IP Tables}, che è quella che consente di far eseguire delle operazioni
sui pacchetti nei cinque punti di aggancio del \textit{netfilter} illustrati
in precedenza, senza doversi scrivere un modulo del kernel.

Questa infrastruttura è basata sulla presenza varie ``\textsl{tabelle}'',
ciascuna delle quali è dedicata ad ospitare le operazioni relative ad un
compito specifico. All'interno delle tabelle sono definite delle
\textsl{catene predefinite}, che corrispondono agli effettivi punti di
aggancio del \textit{netfilter} di fig.~\ref{fig:netfilter_scheme} su cui
arrivano i pacchetti, e che hanno lo stesso nome per tutte le tabelle.

Le tabelle non sono altro che dei contenitori per le ``\textsl{catene}'' che a
loro volta sono semplicemente dei contenitori per le regole di filtraggio. Una
regola è costituita da un criterio di selezione (detto \textit{match}) che
permette di scegliere i pacchetti in base alle loro caratteristiche, e da un
criterio di destinazione (detto \textit{target}) che permette di stabilire il
destino dei pacchetti che soddisfano il criterio di selezione.

I pacchetti che attraversano una catena vengono sottoposti in sequenza a
ciascuna delle regole che essa contiene, e se corrispondono al criterio di
selezione viene applicato loro il criterio di destinazione scelta.  Per
semplificare la gestione il sistema permette di creare, oltre a quelle
predefinite, su cui comunque transitano i pacchetti, delle nuove catene, da
identificare con un nome fornito dall'utente, su cui inserire un qualunque
insieme di regole che si vogliono raggruppare.

Una nuova catena così definita può costituire la \textsl{destinazione} (il
\textit{target}) di una regola e tutti i pacchetti che corrispondono al
criterio di selezione di detta regola verranno inviati sulla nuova catena e
con questo sottoposti alla serie di regole ivi definite. In questo modo una
catena definita dall'utente viene a costituire una specie di
``\textit{subroutine}'' che permette di trattare gruppi di pacchetti con lo
stesso insieme di regole in maniera compatta.

Ciascuna delle tabelle su cui sono presenti le varie catene viene realizzata
attraverso un opportuno modulo del kernel. Ognuna di esse prevede la presenza
di una o più catene predefinite, a seconda dello scopo della tabella.  Al
momento esistono solo quattro tabelle:
\begin{basedescript}{\desclabelwidth{1.8cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{filter}] è la tabella principale, quella utilizzata, come indica
  il nome, per le regole per il filtraggio dei pacchetti. Benché in teoria sia
  possibile filtrare i pacchetti anche sulle altre tabelle, essa costituisce
  il luogo naturale su cui operare per la creazione di firewall.  Contiene tre
  catene predefinite: \texttt{INPUT}, su cui filtrare i pacchetti in ingresso
  sulla macchina stessa; \texttt{FORWARD}, su cui filtrare i pacchetti che
  vengono instradati attraverso la macchina da una interfaccia ad un'altra, e
  \texttt{OUTPUT} su cui filtrare i pacchetti generati localmente che escono
  verso l'esterno.
 
\item[\texttt{nat}] questa tabella viene utilizzata, come suggerisce il nome,
  per inserire le regole relativo al \textit{Network Address Translation} (sia
  SNAT che DNAT) che permettono di manipolare gli indirizzi. Ha la
  caratteristica che solo il primo pacchetto di una connessione raggiunge
  questa tabella, mentre a tutti i restanti pacchetti nella stessa connessione
  verrà automaticamente applicata la stessa regola presa per il primo
  pacchetto. L'uso di questa tabella presuppone quindi l'impiego del sistema
  del \textit{conntrack} che vedremo in sez.~\ref{sec:fw_conntrack}. La
  tabella contiene tre catene: \texttt{PREROUTING}, per modificare gli
  indirizzi dei pacchetti che arrivano sulla macchina (in genere usata per
  alterarne la destinazione); \texttt{OUTPUT}, per modificare i pacchetti
  generati localmente prima che essi arrivano all'instradamento finale;
  \texttt{POSTROUTING}, per modificare i pacchetti immediatamente prima che
  questi escano dall'interfaccia (in genere usata per alterarne l'indirizzo
  sorgente).
  
\item[\texttt{mangle}] questa tabella viene utilizzata, come suggerisce il
  nome, per manipolazioni speciali dei pacchetti; è assolutamente sconsigliato
  usarla per filtrare i pacchetti o alterarne gli indirizzi. Fino al kernel
  2.4.17 essa conteneva solo due catene: \texttt{PREROUTING}, per modificare i
  pacchetti prima dell'instradamento; \texttt{OUTPUT}, per modificare i
  pacchetti generati localmente prima dell'instradamento. A partire dal kernel
  2.4.18 sono state inserite anche le tre altre catene: \texttt{INPUT}, su cui
  modificare i pacchetti in ingresso sulla macchina locale; \texttt{FORWARD},
  su cui modificare i pacchetti che vengono instradati attraverso la macchina
  da una interfaccia ad un altra; \texttt{POSTROUTING}, per modificare i
  pacchetti immediatamente prima che questi escano dall'interfaccia.

\item[\texttt{raw}] una tabella speciale usata per gestire le eccezioni alle
  regole del sistema del \textit{connection tracking} (che vedremo in
  sez.~\ref{sec:fw_conntrack}), principalmente per selezionare i pacchetti per
  cui disabilitarlo con il target speciale \texttt{NOTRACK}. E' posta al
  livello più alto e viene utilizzata prima di tutte le altre, e prima che
  vengano eseguite le operazioni del \textit{connection tracking} a cui tutte
  le altre sono invece sottoposte. Contiene solo le catene \texttt{PREROUTING}
  ed \texttt{OUTPUT}.
\end{basedescript}

% La lista delle tabelle effettivamente utilizzate, che nel caso di kernel
% modulare dipende ovviamente dal caricamento dei relativi moduli, è riportata
% nel filesystem \texttt{proc} nel file \texttt{/proc/net/ip\_tables\_names}. Se
% non le si usano i relativi moduli non saranno presenti e non verranno
% riportati nel file citato.

In sez.~\ref{sec:fw_netfilter_structure} abbiamo visto come i pacchetti
attraversano il \textit{netfilter} all'interno del kernel, ed in precedenza
abbiamo anche accennato a come le varie catene predefinite delle tabelle di
\textit{IP Tables} corrispondano in sostanza ai cinque punti di aggancio
all'interno del \textit{netfilter}; la manipolazione dei pacchetti però viene
eseguita attraverso le regole inserite nelle omonime catene presenti nelle
varie tabelle.

\begin{figure}[htb]
  \centering
  \includegraphics[width=10cm]{images/packetflux}
  \caption{Lo schema del flussi dei pacchetti attraverso le tabelle e le
  catene predefinite di \texttt{iptables}.}
  \label{fig:iptable_flux_scheme}
\end{figure}

Per questo con \texttt{iptables} il diagramma di
fig.~\ref{fig:netfilter_scheme} deve essere rivisto per illustrare l'ordine in
cui i pacchetti attraversano le catene predefinite all'interno delle varie
tabelle, dato che da quest'ordine dipende il risultato finale dell'azione
delle varie regole che si sono inserite. In fig.~\ref{fig:iptable_flux_scheme}
si è allora riportato il nuovo schema che illustra l'ordine di attraversamento
dei pacchetti delle varie catene nelle varie tabelle.

Si noti come la tabella \texttt{raw} abbia un ruolo speciale, rimanendo
esterna al sistema \textit{connection tracking} che invece è attivo per tutte
le altre.  Siccome l'uso della tabella attiene ai pacchetti che
\textsl{entrano} nel \textit{netfilter} essa prevede solo le catene di
\texttt{PREROUTING} ed \texttt{OUTPUT} che sono i due soli punti di ingresso
dello stesso. In entrambi i casi le regole della tabella saranno processate
per prime e prima dell'attivazione del \textit{connection tracking}.

Se un pacchetto è destinato ad un processo locale questo passerà prima per le
catene di \texttt{PREROUTING} prima nella tabella di \texttt{mangle} e poi
nella tabella di \texttt{nat}, poi passerà per il meccanismo di decisione
dell'instradamento che invierà il pacchetto alle catene di \texttt{INPUT},
prima nella tabella di \texttt{mangle} e poi in quella di \texttt{filter}, per
poi essere ricevuto dal processo locale cui è destinato.

Se invece il pacchetto è in transito attraverso la nostra macchina per essere
reinviato su un'altra interfaccia di nuovo passerà per le catene di
\texttt{PREROUTING} prima nella tabella di \texttt{mangle} e poi nella tabella
di \texttt{nat}, ma dopo la decisione sull'instradamento proseguirà sulle
catene di \texttt{FORWARD}, prima della tabella di \texttt{mangle} e poi di
quella di \texttt{filter}, infine proseguirà verso l'interfaccia di uscita
passando per le catene di \texttt{POSTROUTING}, prima nella tabella di
\texttt{mangle} e poi in quella di \texttt{nat}.

Infine se un pacchetto è generato da un processo locale per essere inviato
all'esterno prima passerà per le catene di \texttt{OUTPUT}, a partire dalla
tabella di \texttt{mangle}, per proseguire in quella di \texttt{nat} ed infine
in quella di \texttt{filter}, da qui poi passerà alle catene di
\texttt{POSTROUTING} nello stesso ordine usato dai pacchetti in transito.


\subsection{Il meccanismo del \textit{connection tracking}}
\label{sec:fw_conntrack}

Una delle principali caratteristiche del \textit{netfilter} di Linux è stata
quella di aver introdotto una infrastruttura complessa, ma estremamente
flessibile, chiamata \textit{connection tracking} (in breve
\textit{conntrack}), che permette di analizzare il flusso dei pacchetti,
ricostruire lo stato delle connessioni presenti, ricondurre ad esse e
classificare i vari pacchetti. É grazie a questo meccanismo che è possibile la
realizzazione del filtro degli stati illustrato in
sez.~\ref{sec:fw_state_filter}.

L'infrastruttura del \textit{connection tracking} va ben oltre l'uso fattone
dal filtro degli stati per realizzare un firewall \textit{stateful}; essa
infatti è anche la base su cui è costruito il funzionamento delle capacità di
NAT che permettono al \textit{netfilter} di modificare al volo gli indirizzi
dei pacchetti, e per poterli redirigere opportunamente, in modo da gestire
compiti come il \textit{masquerading}\footnote{si chiama così l'uso dello SNAT
  per \textit{mascherare} una (o più) reti dietro un singolo indirizzo IP
  (quello usato in genere dal firewall per uscire su internet).} o il
\textit{transparent proxing}.\footnote{si chiama così l'uso del DNAT per
  redirigere, in maniera trasparente per i client, il traffico destinato a
  certi servizi (il caso classico è il web) su una macchina che faccia da
  \textit{proxy}.}

Lo scopo principale del motore del \textit{conntrack} è quello di analizzare
il traffico per identificare ogni connessione presente, determinarne lo stato,
e poi classificare i pacchetti associandoli a ciascuna di esse. Dato che il
concetto di \textit{stato} e di \textit{connessione} è definito nativamente
solo per alcuni protocolli (in sostanza solo per il TCP), il meccanismo è
stato esteso per permettere di identificare e classificare ogni flusso di dati
anche per gli altri protocolli che non supportano le connessioni, come UDP e
ICMP. Ad esempio come vedremo più avanti si potrà definire una forma di
connessione anche per UDP, identificando univocamente un flusso di pacchetti
in base ai relativi indirizzi e porte di origine e destinazione.

L'infrastruttura del \textit{conntrack} è stata introdotta nei kernel
della serie 2.4; nei kernel precedenti non esisteva nessun meccanismo
che potesse eseguire questo compito e pertanto non era possibile
creare dei firewall stateful. Inizialmente disponibile solo per il
protocollo IPv4 è stato esteso anche ad IPv6. L'uso del sistema ha
però portato anche ad un cambiamento delle regole che gestiscono la
frammentazione dei pacchetti IP.

La frammentazione è una caratteristica di IPv4 che prevede che i pacchetti che
debbano essere inoltrati su una linea la cui
\itindex{Maximum~Transfer~Unit~(MTU)} MTU\footnote{la \textit{Maximum Transfer
    Unit} o MTU è la dimensione massima di un pacchetto di dati che può essere
  trasferita su un segmento fisico di una rete.} eccede le dimensioni del
pacchetto vengano ``\textsl{frammentati}'' dal router che li riceve per poter
essere trasmessi sulla linea stessa. Questo significa che un singolo pacchetto
IP verrà spezzato in più parti, che poi verranno riassemblate solo alla
destinazione finale, con la ricezione di tutti i pezzi. Nei kernel precedenti
la serie 2.4.x c'era la possibilità di attivare o meno la deframmentazione dei
pacchetti prima di procedere al loro filtraggio, attraverso l'opzione
\texttt{ip\_always\_defrag}. Dato che il \textit{connection tracking} non può
funzionare con i pacchetti frammentati, questa opzione non esiste più, il
codice per la deframmentazione è stato incluso nel \textit{conntrack} ed i
pacchetti vengono sempre riassemblati prima di tracciarne lo stato.

Tutte le operazioni relative al \textit{connection tracking} vengono eseguite
nella catena di \texttt{PREROUTING} eccetto per i pacchetti che vengono
generati localmente, che invece sono analizzati nella catena di
\texttt{OUTPUT}.  Questo significa che tutte le operazioni per il calcolo
degli stati e la classificazione dei pacchetti vengono eseguite non appena
questi arrivano alla catena di \texttt{PREROUTING}. La sola eccezione è per i
pacchetti generati localmente che creano una nuova connessione, che vengono
identificati su \texttt{OUTPUT}, ma non appena al pacchetto inviato per la
creazione di una connessione arriva una risposta la successiva classificazione
dei pacchetti avviene comunque sulla catena di \texttt{PREROUTING}. Come
accennato l'unico modo di impostare delle regole con \texttt{iptables} prima
che il \textit{connection tracking} entri in azione è quello di usare la
speciale tabella di \texttt{raw}.

Il \textit{conntrack} mantiene nel kernel una tabella con tutte le connessioni
presenti ed il relativo stato; la dimensione della tabella, e pertanto il
limite massimo al numero di connessioni contemporanee che possono esistere, è
un parametro configurabile che può essere impostato usando l'interfaccia del
filesystem \texttt{proc} attraverso il file
\texttt{/proc/sys/net/nf\_conntrack\_max}. Il valore di default è calcolato
automaticamente sulla base della memoria disponibile, e nel caso di una
macchina con 8Gb di RAM otteniamo:
\begin{Console}
# \textbf{cat /proc/sys/net/nf_conntrack_max}
65536
\end{Console}
detto valore può essere comunque modificato al volo scrivendo un diverso
valore nel file.

Si può inoltre accedere direttamente al contenuto della tabella delle
connessioni attraverso il filesystem \texttt{proc}, usando il file
\texttt{/proc/net/ip\_conntrack} se interessa solo IPv4 oppure il file
\texttt{/proc/net/nf\_conntrack} per tutti i protocolli del livello di
rete. Nel seguito esamineremo solo il caso di IPv4, che resta comunque
l'ambito di maggiore applicazione del sistema, e faremo riferimento al primo
dei due file, che manca nei dati del campo della informazione iniziale
relativa al protocollo di rete cui fa riferimento la voce (in genere
\texttt{ipv4} o \texttt{ipv6}).

Esaminando \texttt{/proc/net/ip\_conntrack} si otterranno le informazioni
mantenute dal kernel relative a ciascuna connessione; ogni riga corrisponde ad
una connessione, un esempio di voce contenuta nel file è:
\begin{Example}
tcp      6 119 SYN_SENT src=192.168.1.1 dst=192.168.1.141 sport=35552 \
      dport=22 [UNREPLIED] src=192.168.1.141 dst=192.168.1.1 sport=22 \
      dport=35552 use=1
\end{Example}

Il primo campo è sempre quello del protocollo, espresso per nome, e ripetuto
per numero (in esadecimale, anche se nell'esempio non lo si nota) nel secondo
campo. Il terzo campo indica il tempo di vita restante per la voce nella
tabella, nel caso 119 secondi. Il campo viene decrementato progressivamente
fintanto che non si riceve traffico sulla connessione, nel qual caso viene
riportato al valore predefinito (che varia a seconda del protocollo).

I primi tre campi sono sempre questi, i campi successivi dipendono dal
protocollo, nel caso specifico il quarto campo, avendo a che fare con il TCP,
indica lo stato della connessione, che è \texttt{SYN\_SENT}: si è cioè inviato
un segmento SYN in una direzione. Seguono i campi con indirizzo sorgente e
destinazione, e porta sorgente e destinazione. Segue poi una parola chiave
\texttt{[UNREPLIED]} che ci informa che non si è ricevuta risposta, e gli
indirizzi sorgente e destinazione, e le porte sorgente e destinazione per i
pacchetti appartenenti al traffico di ritorno di questa connessione; si noti
infatti come rispetto ai precedenti i numeri siano gli stessi ma sorgente e
destinazione risultino invertiti. 

Vediamo allora il funzionamento del \textit{conntrack} per i tre principali
protocolli, cominciando con il più complesso, il TCP. In questo caso infatti
il protocollo già prevede l'esistenza degli stati, e come vedremo questo
comporterà un certo livello di confusione, in quanto a volte lo stato del
protocollo non coincide con quello del \textit{connection tracking}.

La caratteristica principale del TCP è che esso prevede la creazione di una
connessione tramite l'invio di tre pacchetti separati, con un procedimento
chiamato \itindex{three~way~handshake} \textit{three way handshake},
illustrato in fig.~\ref{fig:fw_TWH}, dove si è riportato lo scambio di
pacchetti ed i relativi cambiamenti di stato del protocollo su client e
server.

\begin{figure}[htb]
  \centering
  \includegraphics[width=8cm]{images/three_way_handshake}
  \caption{Lo schema del \textit{three way handshake} del TCP.}
  \label{fig:fw_TWH}
\end{figure}

Supponiamo allora di essere sul client; dal punto di vista del
\textit{conntrack} una volta che si invia un pacchetto SYN questo passerà per
la catena di \texttt{OUTPUT} e verrà riconosciuto come un pacchetto che inizia
una nuova connessione, creando una voce nella tabella delle connessioni simile
a quella mostrata in precedenza, con lo stato \texttt{SYN\_SENT}\footnote{si
  può ottenere questa situazione bloccando sul server la ricezione dei
  segmenti SYN, in questo modo il client non riceva da questo nessuna
  risposta, così che lo stato nella tabella delle connessioni resti bloccato.}
ed una connessione marcata come \texttt{UNREPLIED}.

Il primo passaggio di stato si ha una volta che si riceve la risposta dal
server con il segmento SYN+ACK ricevuto il quale la connessione si porta
immediatamente nello stato \texttt{ESTABLISHED}, ed avremo una voce del tipo:
\begin{Example}
tcp      6 431996 ESTABLISHED src=192.168.1.1 dst=192.168.1.141 sport=38469 \
      dport=22 src=192.168.1.141 dst=192.168.1.1 sport=22 \
      dport=38469 [ASSURED] use=1
\end{Example}
dove il flag che indica la condizione di \texttt{[UNREPLIED]} non c'è più ed
invece viene attivato quello che indica la condizione di \texttt{[ASSURED]};
questa ci dice che è stato osservato del traffico in entrambe le direzioni, e
che la voce nella tabella delle connessione non deve essere cancellata anche
se questa si riempie, cosa che invece avviene per le voci che non hanno tale
flag attivo.

Si tenga presente che questo accade anche se blocchiamo a questo punto il
\textit{three way handshake},\footnote{ad esempio impedendo con una apposita
  regola nella catena di \texttt{OUTPUT} che il segmento ACK di conclusione
  del procedimento venga inviato al server.} interrompendo la creazione della
connessione TCP; questa è la sequenza normale per gli stati del TCP, che è
anche illustrata in fig.~\ref{fig:fw_TWH}, e la si può verificare usando
\texttt{netstat} sul server, dove la connessione sarà riportata essere rimasta
nello stato \texttt{SYN\_RECV}.

La prima differenza fra lo stato del protocollo e quello della connessione
all'interno del sistema del \textit{connection tracking} emerge a questo
punto: lo stato del protocollo infatti è modificato alla ricezione dei
pacchetti (cioè sulla catena di \texttt{INPUT}), mentre lo stato della
connessione è, come abbiamo già detto, modificato sulla catena di
\texttt{PREROUTING}. Se si blocca con il firewall la ricezione del pacchetto
SYN+ACK, allora il risultato può essere diverso a seconda di come si esegue
detto blocco. Se infatti si blocca il pacchetto sulla catena di \texttt{INPUT}
questo passa comunque per la catena di \texttt{PREROUTING}, ed esattamente
come prima la connessione viene riconosciuta come \texttt{ESTABLISHED}.

Se invece si blocca il pacchetto SYN+ACK direttamente sulla catena di
\texttt{PREROUTING}\footnote{per farlo occorre usare la tabella di
  \texttt{mangle}, bloccando il pacchetto su di essa, dato che la tabella di
  \texttt{nat} opera solo sul primo pacchetto di una connessione.} la
ricezione dell'ACK non viene riconosciuta e la conclusione della connessione
non viene stabilita, viene però rilevato l'arrivo di un segmento SYN, e la
connessione nella tabella degli stati viene portata nello stato
\texttt{SYN\_RECV}, mentre la condizione di \texttt{UNREPLIED} sparisce,
avremo cioè una voce del tipo:
\begin{Example}
tcp      6 44 SYN_RECV src=192.168.1.1 dst=192.168.1.141 sport=35552 \
      dport=22 src=192.168.1.141 dst=192.168.1.1 sport=22 dport=35552 use=1
\end{Example}

Questa condizione si incontra anche quando si riceve un pacchetto SYN di una
connessione diretta verso di noi, in tal caso la voce viene creata alla
ricezione di un pacchetto SYN,\footnote{si può verificare il comportamento
  bloccando la risposta del SYN+ACK sulla catena di \texttt{OUTPUT}.} con una
voce del tipo:
\begin{Example}
tcp      6 55 SYN_RECV src=192.168.1.141 dst=192.168.1.1 sport=33616 \ 
      dport=22 src=192.168.1.1 dst=192.168.1.141 sport=22 dport=33616 use=1
\end{Example}
e di nuovo, non appena si emette il segmento di risposta con un SYN+ACK, la
connessione andrà in stato \texttt{ESTABLISHED}, con una voce del tipo:
\begin{Example}
tcp      6 431998 ESTABLISHED src=192.168.1.141 dst=192.168.1.1 sport=33617 \
      dport=22 src=192.168.1.1 dst=192.168.1.141 sport=22 \
      dport=33617 [ASSURED] use=1
\end{Example}
e ci resterà anche se non si conclude il \textit{three way
  handshake},\footnote{cosa che si può ottenere ad esempio bloccando con il
  firewall la ricezione dell'ultimo ACK di risposta.} questo perché nel caso
del protocollo TCP lo stabilirsi di una connessione è identificato dal
\textit{conntrack} semplicemente dal fatto che c'è uno scambio di pacchetti
TCP nelle due direzioni.

\begin{figure}[htb]
  \centering \includegraphics[width=8cm]{images/tcp_close}
  \caption{Lo schema della conclusione di una connessione TCP.}
  \label{fig:fw_conn_FIN}
\end{figure}

La chiusura di una connessione TCP avviene con lo scambio di 4 pacchetti, come
illustrato in fig.~\ref{fig:fw_conn_FIN}, e non viene mai completamente chiusa
fino a che questo non viene completato. Una volta che questa è completata la
connessione entra nello stato \texttt{TIME\_WAIT}, con una voce del tipo:
\begin{Example}
tcp      6 9 TIME_WAIT src=192.168.1.141 dst=192.168.1.1 sport=33614 \
      dport=22 src=192.168.1.1 dst=192.168.1.141 sport=22 \
      dport=33614 [ASSURED] use=1
\end{Example}
che ha una durata di default di due minuti, così che tutti gli eventuali
ulteriori pacchetti residui della connessione che possono arrivare saranno
classificati all'interno della stessa ed essere sottoposti alle stesse regole.

Lo schema di chiusura mostrato in fig.~\ref{fig:fw_conn_FIN} non è l'unico
possibile, una connessione infatti può anche essere terminata da un pacchetto
RST,\footnote{il protocollo TCP prevede infatti che in risposta a pacchetti
  inviati ad una porta su cui non è in ascolto nessun servizio, o in generale
  non ricollegabili ad una connessione debba essere risposto con l'emissione
  di un pacchetto RST, la ricezione del quale deve produrre la terminazione
  immediata di ogni eventuale connessione.}  che la porta in stato di
\texttt{CLOSE}, che resta attivo per 10 secondi.  Si tenga presente che in
risposta ad un pacchetto RST non deve essere dato nessun ricevuto e che questi
pacchetti sono generati direttamente dal kernel ed utilizzati per chiudere
immediatamente una connessione.

Gli stati possibili per una connessione TCP sono tutti quelli definiti per il
protocollo (anche se la corrispondenza non è proprio immediata, come abbiamo
appena visto). Per ciascuno di questi il \textit{conntrack} definisce un
opportuno valore di timeout scaduto il quale la voce viene rimossa dalla
tabella delle connessioni. I valori di default per il timeout (che vengono
impostati quando la connessione si porta in quello stato, e reimpostati quando
si ricevono nuovi pacchetti sulla connessione) sono definiti nel file
\texttt{net/netfilter/nf\_conntrack\_proto\_tcp.c} nei sorgenti del kernel e
riportati in tab.~\ref{tab:fw_TCP_connection_timeout}.\footnote{la tabella è
  aggiornata ai valori usati dal kernel 3.1.}

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|}
    \hline
    \textbf{Stato}&\textbf{Valore}\\
    \hline
    \hline
    \texttt{SYN\_SENT}  & 2 minuti.\\ 
    \texttt{SYN\_RECV}  & 60 secondi.\\ 
    \texttt{ESTABLISHED}& 5 giorni.\\ 
    \texttt{FIN\_WAIT}  & 2 minuti.\\ 
    \texttt{CLOSE\_WAIT}& 60 secondi.\\ 
    \texttt{LAST\_ACK}  & 30 secondi.\\ 
    \texttt{TIME\_WAIT} & 2 minuti.\\ 
    \texttt{CLOSE}      & 10 secondi.\\ 
    \texttt{SYN\_SENT2} & 2 minuti.\\ 
    \hline
  \end{tabular}
  \caption{Valori dei tempi di timeout delle connessioni TCP.}
\label{tab:fw_TCP_connection_timeout}
\end{table}

Al contrario di TCP, UDP è un protocollo che non supporta le connessioni, il
protocollo si limita ad inviare i pacchetti, questi possono arrivare in
qualunque ordine, essere perduti o duplicati, e non ci sono procedimenti per
definire l'inizio o la conclusione di una comunicazione. Nonostante questo sia
possibile è comunque possibile cercare di classificare il traffico ed
inserirlo in una logica di connessioni, anche se in questo caso (come sarà per
ICMP) la classificazione non può che essere basata su una euristica dello
scambio dei pacchetti.

L'algoritmo di classificazione per UDP si basa sul riconoscimento del traffico
dalla stessa coppia di indirizzi IP e porte (destinazione e sorgente) sui due
capi della comunicazione. Si considerano cioè parte di una connessione tutti i
pacchetti UDP che partono da un nostro IP e hanno una data porta sorgente
diretti verso un altro IP ed una data porta di destinazione, e quelli che
provengono da detto IP con sorgente la porta usata da noi come destinazione e
come destinazione la nostra porta sorgente. Si fa l'assunzione cioè che
pacchetti con queste caratteristiche siano emessi e ricevuti in corrispondenza
allo scambio di dati fra i due capi di uno stesso socket UDP.

Si tenga presente che questo criterio non assicura che una connessione così
identificata comprenda solo i pacchetti appartenenti ad un unico flusso di
dati, è infatti possibile, anche se non molto probabile, dato che in genere le
porte non vengono immediatamente riusate, una situazione in cui un client si
collega ad un nostro server UDP usando una certa porta, conclude le sue
operazioni, e poi un client diverso ritenta la stessa connessione usando la
stessa porta. In un caso come questo i pacchetti saranno classificati, se la
voce nella tabella del \textit{conntrack} non è ancora scaduta, nella stessa
connessione, anche se appartengono a due flussi di dati completamente
distinti.

Questo meccanismo di classificazione comporta che se si invia un pacchetto UDP
che non corrisponde a nessuna voce già presente nella tabella delle
connessioni, questo verrà considerato come un pacchetto iniziale e creerà una
nuova voce,\footnote{un modo per ottenere questo è bloccare con
  \texttt{iptables} sulla macchina di destinazione i pacchetti di risposta al
  collegamento via UDP.} nella forma:
\begin{Example}
udp      17 28 src=192.168.1.1 dst=192.168.1.141 sport=32769 \
      dport=13 [UNREPLIED] src=192.168.1.141 dst=192.168.1.1 sport=13 \
      dport=32769 use=1
\end{Example}

Si noti che la voce è analoga a quelle relative alle connessioni TCP, con il
nuovo nome (e relativo numero) del protocollo nei primi due campi, ed il tempo
di vita restante alla voce nel terzo. Il resto della voce è analogo a quelle
usate per il TCP, però non esiste più nel quarto campo un valore dello stato e
vengono riportati di seguito direttamente indirizzo sorgente e destinazione e
porta sorgente e destinazione. Segue, non avendo ricevuto nessun altro
pacchetto il flag della condizione \texttt{[UNREPLIED]} e indirizzi e porte
(ovviamente invertite) dei pacchetti che si aspettano come risposta.

Nel caso di UDP, quando viene creata con l'invio di un nuovo pacchetto, a
ciascuna voce viene dato un tempo di vita di 30 secondi, dei quali,
nell'esempio precedente, ne sono restati solo 28 disponibili.  Non appena si
riceve un pacchetto di risposta sulla coppia di IP corrispondente e porta la
condizione di \texttt{[UNREPLIED]} sparirà, e la connessione si potrà
considerare stabilita, la voce nella tabella delle connessioni diventerà del
tipo:
\begin{Example}
udp      17 25 src=192.168.1.1 dst=192.168.1.141 sport=32768 \
      dport=13 src=192.168.1.141 dst=192.168.1.1 sport=13 dport=32768 use=1
\end{Example}
ed il tempo di vita verrà riportato di nuovo a 30 secondi, facendo ripartire
il conto alla rovescia.

Si noti però che ancora la connessione non è considerata stabile, lo diverrà
non appena sarà osservata una certa quantità di traffico, al che comparirà il
flag di \texttt{[ASSURED]} e la voce diverrà:
\begin{Example}
udp      17 177 src=192.168.1.1 dst=192.168.1.141 sport=32768 \
      dport=13 src=192.168.1.141 dst=192.168.1.1 sport=13 
      dport=32768 [ASSURED] use=1
\end{Example}
ed il tempo di vita viene portato ad 180 secondi (nell'esempio ne sono passati
tre).

Dato che anche il protocollo ICMP non supporta connessioni, anche questo viene
classificato in base ad una euristica dei pacchetti. Inoltre questo protocollo
viene usato principalmente per l'invio di messaggi di controllo relativi ad
errori della rete, e pertanto non è neanche classificabile in una logica di
connessioni e stati. Esistono però alcuni specifici pacchetti ICMP che
richiedono una risposta, ed allora di nuovo diventa possibile classificare
queste risposte in una logica di connessione.

Per questo motivo il sistema del \textit{conntrack} classifica soltanto
quattro coppie di \textsl{tipi}\footnote{i pacchetti ICMP vengono classificati
  in base al valore di un apposito campo nella loro intestazione, il
  \textsl{tipo}, per maggiori informazioni si può fare riferimento a quanto
  illustrato in sez.~\ref{sec:fw_icmp_filtering} e a
  fig.~\ref{fig:fw_ICMP_header}.} di pacchetti ICMP, \textit{echo request} e
\textit{echo reply}, \textit{netmask request} e \textit{netmask reply},
\textit{timestamp request} e \textit{timestamp reply}, \textit{information
  request} e \textit{information reply}.  In questo caso l'euristica di
classificazione delle connessioni è identica a quella di UDP, dove al posto
della porta viene usato il tipo di pacchetto, che deve corrispondere alla
precedente richiesta.  Ad esempio pacchetti di \textit{echo reply} provenienti
da un IP a cui si era inviati un \textit{echo request} vengono considerati
facenti parte di una connessione.

Così se effettuiamo un \texttt{ping} verso una macchina all'invio del
pacchetto \textit{echo request} nella tabella del \textit{conntrack} apparirà
una voce del tipo:\footnote{al solito la si può ottenere bloccando i pacchetti
  di risposta provenienti dalla macchina che si sta ``\textsl{pingando}''.}
\begin{Example}
icmp     1 22 src=192.168.1.1 dst=192.168.1.141 type=8 code=0 id=29957 \
    [UNREPLIED] src=192.168.1.141 dst=192.168.1.1 type=0 code=0 id=29957 use=1
\end{Example}
che ha un tempo di vita di 30 secondi. Al solito la voce riporta indirizzi IP
sorgente e di destinazione del pacchetto e dell'eventuale risposta attesa. In
questo caso viene anche riportato sia il tipo di pacchetto ICMP che ha creato
la voce (8, essendo un \textit{echo request}) seguita poi da quello (0,
essendo un \textit{echo reply}) che ci si attende come risposta, mentre i
valori del campi \texttt{code} e \texttt{id} degli stessi.

Nel caso di ICMP non si ha invece nessuna voce relativa ad una connessione
stabilita, infatti la ricezione del pacchetto di risposta esaurisce tutto il
traffico previsto per questo tipo di operazioni, per cui la connessione viene
immediatamente chiusa, e la voce nella tabella del \textit{conntrack}
cancellata.



\subsection{Il funzionamento del filtro degli stati}
\label{sec:fw_state_filter}

Una delle principali innovazioni portate dal \textit{netfilter} con la serie
dei kernel 2.4.x è stata quella della possibilità di usare Linux come firewall
\textit{stateful}.  Come spiegato in sez.~\ref{sec:fw_what_fw} un firewall
\textit{stateful} è un firewall in grado di classificare i pacchetti in un
insieme di \textsl{stati}, per poi selezionarli in base a questi ultimi.

Nel caso di Linux questo viene realizzato attraverso l'infrastruttura del
\textit{connection tracking} descritto in sez.~\ref{sec:fw_conntrack}. Benché
le modalità in cui vengono classificati i pacchetti all'interno del
\textit{connection tracking} siano abbastanza complesse, il filtro degli stati
di Linux riclassifica tutti i pacchetti in solo 4 stati, che si sono riportati
in tab.~\ref{tab:fw_connection_states}. Nella tabella si è menzionato anche
\texttt{UNTRACKED} che in realtà non è uno stato ma identifica semplicemente i
pacchetti che si sono esclusi dal \textit{connection tracking}, e quindi anche
dalla classificazione degli stati, tramite il target \texttt{NOTRAK} nella
catena di \texttt{raw}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Stato}&\textbf{Descrizione}\\
    \hline
    \hline
    \texttt{NEW}        & Identifica i pacchetti usati per dare origine ad una
                          connessione.\\ 
    \texttt{ESTABLISHED}& Identifica i pacchetti riconosciuti far parte o
                          essere associati ad una connessione già stabilita.\\ 
    \texttt{RELATED}    & Identifica i pacchetti che danno origine ad una
                          nuova connessione che è però correlata ad una
                          connessione esistente.\\  
    \texttt{INVALID}    & Identifica i pacchetti che non vengono associati a
                          nessuna connessione esistente o hanno dati o
                          intestazioni riconosciuti come non validi.\\ 
    \hline
    \texttt{UNTRACKED}  & Identifica i pacchetti che si sono forzatamente
                          esclusi dal \textit{connection tracking} e con
                          questo anche dalla classificazione negli stati
                          tramite il target \texttt{NOTRAK} nella tabella di
                          \texttt{raw}.\\
    \hline
  \end{tabular}
  \caption{Gli stati delle connessioni definiti nel \textit{netfilter}.}
\label{tab:fw_connection_states}
\end{table}

Come per la classificazione delle connessioni anche quella degli stati viene
eseguita nella catena di \texttt{PREROUTING}, con l'eccezione dei pacchetti
creati localmente che vengono analizzati su \texttt{OUTPUT}. Quando un
pacchetto arriva sulla catena di \texttt{PREROUTING} prima viene eseguito un
eventuale DNAT e le manipolazioni previste da eventuali regole nella tabella
di \texttt{mangle}, infine viene calcolato lo stato. Lo stesso avviene per i
pacchetti uscenti dalla catena di \texttt{OUTPUT}.

Quando si incontra un pacchetto che non si è mai visto prima e che può essere
considerato come pacchetto di inizio di una nuova connessione, questo verrà
inserito nello stato \texttt{NEW}. Il caso più comune è quello di un pacchetto
TCP con il flag SYN, ma può essere anche il primo pacchetto di una sessione su
UDP.  Si tenga presente inoltre che possono essere classificati in questo
stato anche pacchetti TCP diversi da un SYN, il che può comportare problemi in
certi casi, ma può essere di aiuto quando ci sono connessioni andate in
timeout ma non chiuse.

Se un pacchetto corrisponde ad una voce nella tabella delle connessioni allora
verrà classificato come parte di una connessione già stabilita ed assumerà lo
stato di \texttt{ESTABLISHED}. Perché un pacchetto sia classificato come tale
il \textit{conntrack} deve aver rilevato del traffico in entrambe le
direzioni, si arriva allo stato \texttt{ESTABLISHED} solo dopo che una
connessione è passata dallo stato \texttt{NEW}, quando arriva un pacchetto
interpretabile come risposta. Questo significa che anche dei pacchetti ICMP
possono entrare in questo stato, qualora generati come risposta ad un
pacchetto che inizia una connessione (come l'\textit{echo reply} in risposta
ad un \textit{echo request}).

Lo stato più complesso da realizzare, anche se è molto semplice da descrivere,
è \texttt{RELATED}; in breve si può dire che se il traffico può essere
collegato in qualche modo ad una connessione già stabilita (ad esempio è un
pacchetto ICMP relativo ad una connessione TCP, o il traffico dati di una
sessione FTP) questo verrà classificato nello stato \texttt{RELATED}.  Questo
significa che per potere avere un pacchetto nello stato \texttt{RELATED} deve
esistere già una connessione in stato \texttt{ESTABLISHED} cui questo è
collegato.

La difficoltà sta tutta nel meccanismo con cui \textit{conntrack} è in grado
di stabilire in che modo un pacchetto è collegato ad una connessione
stabilita.  Degli esempi per questo tipo di pacchetti sono le risposte ICMP
relative ad una connessione,\footnote{al contrario di quanto veniva affermato
  nell'\textit{Iptables HOWTO}, i messaggi di errore relativi ad una
  connessione non sono classificati allo stato \texttt{ESTABLISHED}, ma nello
  stato \texttt{RELATED}.} il traffico dati FTP collegato alla presenza di una
connessione di controllo, o le connessioni DCC eseguite tramite IRC. In alcuni
di questi casi il meccanismo per rilevare il collegamento può essere molto
complesso, e richiedere anche l'analisi (parziale) del contenuto dei dati
trasmessi all'interno dei vari protocolli, nel qual caso diventa necessario
utilizzare degli opportuni moduli di supporto che estendono le capacità di
classificazione del \textit{conntrack}. 

Questo è ad esempio quello che serve per poter utilizzare i citati protocolli
per FTP e IRC, per i quali nella distribuzione standard del kernel sono
previsti due appositi moduli, che quando inclusi forniscono le estensioni
necessarie; altri moduli relativi ad altri protocolli (H323, SIP) sono
disponibili sia come patch esterne che nei kernel di default.

Infine tutto il traffico che non rientra nelle tre categorie precedenti, che
cioè non può essere identificato o a cui non è possibile assegnare uno stato,
viene classificato come \texttt{INVALID}. Si tenga presente che ciò può
avvenire sia perché effettivamente si tratta di pacchetti malformati, o di
risposte a connessioni inesistenti, sia perché si è esaurito lo spazio nella
tabella degli stati, e non è pertanto più possibile classificare il traffico
ulteriore.

Come si vede il meccanismo del filtro sugli stati è piuttosto complesso, anche
se semplifica notevolmente il lavoro di gestione di un firewall. Ad esempio la
classificazione dei pacchetti consente di bloccare in maniera pulita tutti i
pacchetti sospetti classificati nello stato \texttt{INVALID}. Inoltre con le
combinazioni degli stati \texttt{NEW} e \texttt{ESTABLISHED} consente di
gestire in maniera flessibile la creazione nuove ``\textsl{connessioni}''
anche per protocolli come UDP e ICMP che non supportano nativamente questo
concetto, e per i quali sarebbe impossibile, senza la presenza del
\textit{conntrack} che traccia il flusso dei pacchetti, identificare flussi di
dati collegati fra loro con regole basate esclusivamente sul contenuto delle
intestazioni dei singoli protocolli.

Inoltre l'uso dello stato \texttt{RELATED} permette di ricostruire
collegamenti anche fra pacchetti, connessioni e flussi di dati che, fermandosi
al punto di vista dei protocolli di livello inferiore, sarebbero completamente
scorrelati fra di loro, rendendo possibile filtrare in maniera semplice su
protocolli complessi a livello di applicazione, che non sarebbe possibile
controllare con un firewall non \textit{stateful}.

La semplificazione della complessità dei protocolli di rete in quattro stati
diversi comporta come sempre la necessità di capire bene cosa succede sotto la
superficie, onde evitare effetti indesiderati non previsti.  Per questo
esamineremo in dettaglio il funzionamento del filtro degli stati per ciascuno
dei protocolli principali su cui esso opera.

Nel caso del protocollo TCP il punto più critico sta nella definizione di cosa
si intende per un pacchetto in stato \texttt{NEW}. Infatti dal punto di vista
del protocollo l'unico pacchetto che può iniziare una connessione è quello che
ha attivo il flag SYN e disattivi i flag ACK e RST. La classificazione del
filtro degli stati in certi casi però classifica come \texttt{NEW} anche
pacchetti che non hanno questa caratteristica. Questo viene fatto per
consentire al traffico di una connessione già stabilita (fatta passare da un
altro firewall cui si è subentrati, o autorizzata prima di aver caricato in
memoria il \textit{conntrack}) di proseguire.

Questo però non è quello che appunto si intende normalmente, per cui se si
vuole che passino strettamente soltanto i pacchetti che danno origine ad una
nuova connessione TCP, occorrerà scartare i pacchetti classificati in stato
\texttt{NEW} ma che non hanno il flag SYN opportunamente impostato.

Un altro punto da capire è che dal punto di vista della classificazione dei
pacchetti vengono considerati come facenti parte dello stato
\texttt{ESTABLISHED} tutti i pacchetti successivi al primo (come abbiamo visto
in sez.~\ref{sec:fw_conntrack}), anche se ancora dal punto di vista del TCP la
connessione non ha concluso il \textit{three way handshake} e non può essere
considerata come stabilita. Questo avviene perché deve essere possibile
consentire ai pacchetti in stato \texttt{NEW} e \texttt{ESTABLISHED} di uscire
dalla nostra macchina ed accettare in risposta solo i pacchetti di stato
\texttt{ESTABLISHED}: se si considerasse la risposta del SYN+ACK come facente
parte dello stato \texttt{NEW} questo non sarebbe possibile.

Nel caso di UDP il meccanismo è molto più semplice, e si considera in stato
\texttt{NEW} il primo pacchetto che non corrisponde ad una voce già presente
nella tabella delle connessioni. Come sempre controllo viene fatto sulla
tabella di \texttt{OUTPUT} per le connessioni uscenti e su quella di
\texttt{PREROUTING} per le connessioni entranti. Ogni pacchetto successivo
corrispondente viene considerato essere nello stato \texttt{ESTABLISHED}. Dato
che UDP non prevede nessun meccanismo di conclusione della connessione questa
viene effettuata tramite la scadenza della relativa voce nella tabella delle
connessioni, che avviene dopo 3 minuti di assenza di traffico.

Infine nel caso di ICMP si considerano come facenti parte dello stato
\texttt{NEW} i pacchetti di richiesta (cioè \textit{echo request} e affini),
mentre si considerano come \texttt{ESTABLISHED} tutti quelli di risposta (cioè
\textit{echo reply} e affini). Come già accennato dato che alla ricezione del
pacchetto di risposta non può esserci alcun altro traffico legale, la relativa
voce nella tabella delle connessioni viene immediatamente cancellata.

I pacchetti ICMP però vengono utilizzati anche per comunicare messaggi di
controllo relativi ad errori e problemi della rete. In questo caso allora gran
parte di questi pacchetti vengono classificati in stato \texttt{RELATED}
facendo riferimento ai pacchetti della connessione in risposta ai quali sono
stati creati.\footnote{questo avviene solo quando i dati riportati nel payload
  del pacchetto coincidono; in particolare vengono inseriti in questo stato i
  pacchetti ICMP di tipo: \textit{destination-unreachable},
  \textit{source-quench}, \textit{time-exceeded}, \textit{paremeter-problem} e
  \textit{redirect}.} Ad esempio due dei pacchetti ICMP più comuni sono
\textit{host unreachable} e \textit{network unreachable}, generati dal router
che riceve il nostro traffico quando questo si accorge che la macchina di
destinazione o un altro router che dà accesso alla rete su cui essa si trova
non è più raggiungibile.



\section{Il comando \texttt{iptables}}
\label{sec:fw_iptables}

Affronteremo in questa sezione la sintassi di uso del comando
\index{comando!\texttt{iptables}}\texttt{iptables}, e le modalità con cui
questo viene impiegato per gestire il funzionamento delle regole utilizzate
dal \textit{netfilter} per eseguire i compiti di filtraggio e manipolazione dei
pacchetti.


\subsection{La sintassi generale del comando}
\label{sec:fw_iptables_sintax}

Come illustrato in sez.~\ref{sec:fw_tables_chains} il \textit{netfilter} mette
a disposizione dei punti di aggancio nei quali è possibile intercettare i
pacchetti, esaminarli, e decidere cosa farne.  Usando l'infrastruttura di
\textit{IP Tables} questo si può fare inserendo delle \textsl{regole}
all'interno delle varie \textsl{catene} presenti nelle varie \textsl{tabelle}.

Il comando che permette di selezionare ed esaminare le tabelle, controllare,
creare e cancellare le catene, gestirne le proprietà, definire e creare le
varie regole è appunto \texttt{iptables}. Data le molteplici funzionalità che
fornisce il comando è piuttosto complesso e presenta una grande quantità di
opzioni, queste si possono classificare secondo una schematizzazione generale
per cui l'invocazione del comando ha la forma:
\begin{Example}
iptables controllo [selezione] [azione]
\end{Example}
in cui le opzioni sono raggruppate in tre classi generiche, quelle per il
controllo di tabelle e catene, quelle per la selezione dei pacchetti, e quelle
per la decisione delle azioni da compiere sui pacchetti selezionati.  Le parti
indicate tra parentesi sono opzionali, nel senso che ci sono sintassi valide
del comando in cui non compaiono opzioni di selezione dei pacchetti o azioni
da compiere su questi ultimi.

In realtà non è necessario specificare le varie opzioni di \texttt{iptables}
nell'ordine appena mostrato, né raggruppate nelle tre classi ivi elencate;
esse possono essere invocate in qualunque ordine, ma usare questa
schematizzazione facilita senz'altro la leggibilità del comando. Dato poi che
in genere un firewall si costruisce inserendo tutte le relative regole di
filtraggio all'interno del \textit{netfilter} con una serie di chiamate
successive ad \texttt{iptables} (in genere effettuate all'interno di uno
script di shell), scrivere in maniera ordinata facilita la comprensione dello
stesso.

Unica eccezione alla struttura appena mostrata è l'invocazione del comando
senza opzioni, che si limita a stampare una riga di aiuto che invita ad usare
le due opzioni \texttt{-{}-help} o \texttt{-h}. Usando solo queste ultime è
possibile ottenere la stampa a video di una breve sinossi delle opzioni
principali. L'unica altra opzione utilizzabile singolarmente è, come per tutti
i comandi che seguono lo standard GNU, \texttt{-{}-version}, che stampa a
video la versione del comando.


\subsection{Le opzioni per il controllo di tabelle e catene}
\label{sec:fw_iptables_chain}

Cominciamo allora con il prendere in esame le varie opzioni che vengono
utilizzate per scegliere su quale tabella o catena si va ad operare, per
controllare i contenuti, per impostare le proprietà delle catene predefinite,
per gestire la selezione, creazione, cancellazione e modifica delle catene
create dall'utente stesso.

La prima opzione di \texttt{iptables} è \texttt{-t} (o \texttt{-{}-table}) che
permette di selezionare su quale tabella operare, usando come parametro il
nome della stessa come indicato in sez.~\ref{sec:fw_tables_chains}. Dato che
il comando è usato principalmente per la realizzazione di firewall, se non si
specifica nessuna tabella viene utilizzata di default la tabella
\texttt{filter}, se invece si vogliono inserire delle regole in catene
presenti sulle altre tabelle occorrerà sempre selezionarle esplicitamente
specificandole come parametro per l'opzione \texttt{-t}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|p{8cm}|}
    \hline
    \multicolumn{2}{|c|}{\textbf{Opzione}}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{-N}&\texttt{-{}-new-chain}   & Crea una nuova catena, il cui nome
                                           deve essere passato come
                                           parametro, e non deve corrispondere
                                           ad una catena già esistente. \\ 
    \texttt{-X}&\texttt{-{}-delete-chain}& Cancella una catena, il cui nome
                                           deve essere passato come
                                           parametro; la catena deve essere
                                           vuota e le catene predefinite non
                                           possono essere cancellate. \\
    \texttt{-E}&\texttt{-{}-rename-chain}& Rinomina una catena, il vecchio nome
                                           ed il nuovo devono essere passati
                                           come parametri, le catena
                                           predefinite non possono essere
                                           rinominate.  \\
    \texttt{-L}&\texttt{-{}-list}        & Elenca le regole presenti nella
                                           catena; se non si passa nessun
                                           parametro elenca le regole di tutte
                                           le catene nella tabella. \\
    \texttt{-F}&\texttt{-{}-flush}       & Cancella tutte le regole presenti
                                           nella catena; se non si passa nessun
                                           parametro cancella le regole di 
                                           tutte la catene nella tabella. \\
    \texttt{-Z}&\texttt{-{}-zero}        & Azzera i contatori di una
                                           catena; se non si passa nessun  
                                           parametro azzera i contatori di
                                           tutte le catene nella tabella. \\
    \texttt{-P}&\texttt{-{}-policy}      & Imposta la politica di default per
                                           la catena, prende come parametro
                                           addizionale la destinazione da
                                           usare per tutti i pacchetti che
                                           arrivano alla fine della catena
                                           senza incontrare una corrispondenza
                                           in alcuna regola. \\
    \hline
  \end{tabular}
  \caption{Opzioni per la gestione delle catene.}
\label{tab:fw_chain_management}
\end{table}


Come accennato in sez.~\ref{sec:fw_tables_chains} oltre alle catene
predefinite si possono creare (con l'opzione \texttt{-N}) delle nuove catene
definite dall'utente, inoltre \texttt{iptables} consente di analizzare i
contenuti di una catena, e di leggerne i contatori associati (che indicano il
numero di pacchetti che l'hanno attraversata) con l'opzione \texttt{-L}. Si
possono cancellare le regole di una catena con \texttt{-F} o impostarne la
politica (solo per quelle predefinite) con \texttt{-P}.  L'elenco completo
delle opzioni per operare sulle catene è riportato in
tab.~\ref{tab:fw_chain_management}. 

Inoltre usando l'opzione \texttt{-v} si può aumentare la quantità di
informazione fornita dal comando; l'uso di questa opzione è di particolare
importanza quando usata insieme a \texttt{-L}, dato che permette di mostrare
tutti i dettagli delle regole di selezione comprese quelle sulle interfacce,
sul campo TOS di IP, e le varie opzioni delle regole.  Sempre con \texttt{-L}
si possono usare anche due altre opzioni, \texttt{-n} che disabilita la
risoluzione degli indirizzi e delle porte, che verranno stampati in forma
numerica, e \texttt{-{}-line-numbers} che stampa un numero progressivo per le
regole presenti nella catena, in modo da poterlo utilizzare con le opzioni
\texttt{-D}, \texttt{-R} e \texttt{-I}.

Dato che il funzionamento del \textit{netfilter} prevede la scansione
sequenziale delle catene, il comando \texttt{iptables} prevede diverse
opzioni, riportate in tab.~\ref{tab:fw_rules_insertion}, per inserire o
cancellare una regola all'interno di una catena in una posizione definita. Per
ciascuna di questa opzioni deve essere specificata come parametro la catena da
utilizzare, che può essere sia una di quelle predefinite, che una di quelle
create con i comandi di tab.~\ref{tab:fw_chain_management}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|p{8cm}|}
    \hline
    \multicolumn{2}{|c|}{\textbf{Opzione}}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{-A}&\texttt{-{}-append} & Inserisce la regola in cosa alla catena.
                                      In questo modo la regola sarà sempre
                                      l'ultima della catena, fintanto che non
                                      se ne aggiunge un'altra.\\
    \texttt{-D}&\texttt{-{}-delete} & Cancella una regola nella catena, sia
                                      indicandola per posizione numerica nella
                                      catena, che esprimendola integralmente.\\
    \texttt{-R}&\texttt{-{}-replace}& Rimpiazza la regola nella catena,
                                      identificata con il numero che ne indica
                                      la posizione, con quella specificata nel
                                      comando.\\
    \texttt{-I}&\texttt{-{}-insert} & Inserisce una regola in una posizione
                                      specifica nella catena. \\
    \hline
  \end{tabular}
  \caption{Opzioni per l'inserimento di una regola all'interno di una catena.}
\label{tab:fw_rules_insertion}
\end{table}

Infine le opzioni \texttt{-R}, \texttt{-I} e \texttt{-D} prevedono un secondo
parametro che specifica la posizione nella catena in cui rimpiazzare, inserire
o cancellare una regola; questo deve essere indicato nella forma del numero
progressivo della regola, che si può ottenere combinando l'opzione
\texttt{-{}-line-numbers} con quella per la stampa delle regole \texttt{-L}.



\subsection{I criteri di selezione dei pacchetti}
\label{sec:fw_iptables_match}

Come illustrato in sez.~\ref{sec:fw_iptables_sintax} oltre ad indicare tabelle
e catene da usare, il comando \texttt{iptables} serve principalmente a creare
le regole da inserire al loro interno.  Per creare una regola allora, oltre
alla catena su cui inserirla, occorre anche specificare un criterio di
selezione dei pacchetti.

Per questo motivo la seconda classe di opzioni, la più numerosa, è quella che
permette di definire i criteri per la selezione dei pacchetti, il cuore di
ogni regola. Questi criteri possono essere di diversi tipi, i primi che
affronteremo sono i criteri generici, che sono sempre disponibili perché
forniti dall'infrastruttura stessa del \textit{netfilter}, indipendentemente
dal protocollo dei pacchetti o delle estensioni che si possono usare.

Si tenga presente poi che per quanto in seguito si elencheranno, per esigenza
di chiarezza nell'esposizione, i vari criteri di selezione uno per uno, con le
opzioni relative a ciascuno di essi, normalmente quando si definisce una
regola da inserire in una catena, si possono specificare insieme più criteri
di selezione. In tal caso il significato della regola è che un pacchetto, per
avere una corrispondenza, deve soddisfarli tutti quanti; vale cioè una
modalità di \textsl{AND} logico dei criteri di selezione, ad esempio una
regola del tipo ``\texttt{-s 192.168.1.24 -d 192.168.0.4}'' richiede che il
pacchetto abbia un certo indirizzo sorgente \textsl{e} un certo indirizzo di
destinazione.

I criteri generici sono sostanzialmente i criteri che operano direttamente sui
parametri più comuni contenuti nella intestazione dei pacchetti IP, e sulle
interfacce da cui i pacchetti entrano o escono, e sono disponibili nativamente
nel \textit{netfilter} di Linux. Le relative opzioni sono le seguenti:
\begin{basedescript}{\desclabelwidth{1.cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{-p}, \texttt{-{}-protocol}] Seleziona il pacchetto in base al
  protocollo del livello di trasporto, che deve essere specificato come
  parametro. I valori possibili sono \texttt{tcp}, \texttt{udp}, \texttt{icmp}
  o \texttt{all} per indicare tutti e tre. L'uso di questi valori speciali
  consente di attivare le opzioni specifiche relative a tali protocolli su cui
  torneremo più avanti, per cui in realtà quando si usano questi valori si va
  oltre i criteri generici.  Oltre a questi nomi si può usare direttamente il
  valore numerico del protocollo, o il nome corrispondente che deve essere
  però indicato nel file \texttt{/etc/protocols}. Inoltre si può usare il
  carattere ``\texttt{!}'' per invertire la selezione. Possibili esempi sono:
\begin{Example}
-p tcp
--protocol ! udp
\end{Example}
  
\item[\texttt{-s}, \texttt{-{}-src}, \texttt{-{}-source}] Seleziona il
  pacchetto in base all'indirizzo sorgente. L'indirizzo sorgente può essere
  specificato sia in forma numerica che con un nome a dominio; è però una
  pessima idea usare nomi che devono essere risolti attraverso una
  interrogazione al DNS, data la vulnerabilità di questo protocollo che può
  anche fornire risposte false. Si può anche indicare una intera rete,
  specificandola nella forma \texttt{indirizzo/rete}, dove la parte di rete
  può essere specificata sia come netmask, che con la notazione CIDR.  Anche
  in questo caso si può invertire la selezione apponendo il carattere
  ``\texttt{!}''. Possibili esempi sono:
\begin{Example}
-s 192.168.1.1
-s 192.168.2.0/24
--src 10.0.0.0/255.0.0.0
--source ! 172.16.1.2
\end{Example}
  
\item[\texttt{-d}, \texttt{-{}-dst}, \texttt{-{}-destination}] Seleziona il
  pacchetto in base all'indirizzo di destinazione. Come per l'indirizzo
  sorgente si può specificare (con la stessa sintassi) sia un indirizzo che
  una intera rete. Possibili esempi sono:
\begin{Example}
-d 192.168.1.1
-d 192.168.2.0/24
--dst 10.0.0.0/255.0.0.0
--destination ! 172.16.1.2
\end{Example}
  
\item[\texttt{-i}, \texttt{-{}-in-interface}] Seleziona il pacchetto sulla
  base dell'interfaccia di rete da cui proviene. L'opzione richiede come
  parametro il nome dell'interfaccia, e può essere usata solo sulle catene
  \texttt{INPUT}, \texttt{FORWARD} e \texttt{PREROUTING}. Oltre al nome esatto
  si può indicare una intera classe di interfacce usando il carattere
  ``\texttt{+}'', se ad esempio si vogliono selezionare tutte le interfacce
  Ethernet si potrà usare il parametro \texttt{eth+}. L'opzione supporta pure
  l'inversione della soluzione con l'uso del carattere ``\texttt{!}''.
  Possibili esempi sono:
\begin{Example}
-i ppp0
-i ! eth1
--in-interface tun+
\end{Example}
  
\item[\texttt{-o}, \texttt{-{}-out-interface}] Seleziona il pacchetto sulla
  base dell'interfaccia di rete in uscita a cui è destinato.  L'opzione
  richiede come parametro il nome dell'interfaccia, e può essere usata solo
  sulle catene \texttt{FORWARD}, \texttt{OUTPUT} e \texttt{POSTROUTING}.
  Supporta le stesse estensioni per indicare classi di interfacce e la
  negazione della selezione viste per l'analoga precedente.  Possibili esempi
  sono:
\begin{Example}
-o ppp0
-o ! eth0
--out-interface tun+
\end{Example}
  
\item[\texttt{-f}, \texttt{-{}-fragment}] Seleziona i pacchetti IP frammentati
  (si veda quanto detto a proposito in sez.~\ref{sec:fw_conntrack} e
  sez.~\ref{sec:fw_ip_filtering}).  Dato che solo il primo frammento contiene
  l'intestazione del protocollo IP i criteri di selezione basati su indirizzi
  sorgente o destinazione o altri dati desumibili dall'intestazione, non
  potranno mai corrispondere per dei frammenti successivi al primo che allora
  vengono selezionati tramite questa opzione.  L'opzione può essere preceduta
  da un carattere ``\texttt{!}'' che inverte la selezione.  Possibili esempi
  sono:
\begin{Example}
-f
! --fragment
\end{Example} 
\end{basedescript}

Come appena accennato, qualora si richieda una corrispondenza per protocollo
che coinvolge uno dei tre protocolli principali del TCP/IP (vale a dire quando
si specifica uno dei criteri con \texttt{-p tcp}, \texttt{-p udp} o \texttt{-p
  icmp}) vengono attivate automaticamente una serie di ulteriori possibili
criteri di selezione basati sulle caratteristiche particolari di questi stessi
protocolli.

In particolare quando si usano sia \texttt{tcp} che \texttt{udp} si potranno
effettuare selezioni ulteriori sui valori delle porte utilizzate da detti
protocolli, secondo i criteri specificabili tramite le opzioni:
\begin{basedescript}{\desclabelwidth{1.cm}\desclabelstyle{\nextlinelabel}}  
\item[\texttt{-{}-sport}, \texttt{-{}-source-port}] Seleziona il pacchetto in
  base alla porta sorgente. La porta può essere specificata sia per numero che
  per il nome utilizzato in \texttt{/etc/services}.\footnote{si tenga presente
    però che in questo caso la scrittura delle regole viene ritardata dalla
    risoluzione del nome, e quando si scrive un gran numero di regole, il
    ritardo può essere sensibile.} Usando i numeri si può specificare un
  intervallo di porte usando il carattere ``\texttt{:}'' come separatore,
  omettendo uno dei due estremi di un intervallo si sottintende l'uso del
  relativo valore massimo (65535) o minimo (0). Anche in questo caso si può
  invertire una selezione apponendo ad essa il carattere ``\texttt{!}''.
  Possibili esempi sono:
\begin{Example}
--sport 25
--sport ! smtp
--source-port 0:1024
--source-port 25000:
\end{Example}
 
\item[\texttt{-{}-dport}, \texttt{-{}-destination-port}] Seleziona il
  pacchetto in base alla porta di destinazione.  La porta può essere
  specificata sia per numero che utilizzando il nome utilizzato in
  \texttt{/etc/services}, usando la stessa sintassi vista in precedenza per
  \texttt{-{}-sport}. Anche in questo caso si può invertire la selezione
  apponendo il carattere ``\texttt{!}''. Possibili esempi sono:
\begin{Example}
--dport 80
--dport ! ssh
--destination-port 25000:
\end{Example}
\end{basedescript}

Quando si effettua il filtraggio sul protocollo \texttt{udp} le precedenti
sono le sole opzioni aggiuntive disponibili, nel caso invece si filtri su
\texttt{tcp} invece diverranno utilizzabili anche le seguenti ulteriori
opzioni:
\begin{basedescript}{\desclabelwidth{1.cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{-{}-tcp-flags}] Seleziona il pacchetto in base allo stato dei
  flag del protocollo TCP, questi sono una serie di bit nell'intestazione dei
  pacchetti utilizzati nella gestione delle connessioni. L'opzione richiede
  due parametri, il primo è la lista dei flag da tenere sotto controllo
  (separati da virgole e senza spazi) ed il secondo la lista di tutti e soli i
  flag che fra i precedenti si richiede siano attivi. I valori usati per
  specificare i flag sono quelli dei rispettivi nomi, come indicati nella
  definizione del protocollo,\footnote{si faccia riferimento
    all'\href{http://www.ietf.org/rfc/rfc0793.txt}{RFC~793}.} cioè
  \texttt{SYN}, \texttt{ACK}, \texttt{FIN}, \texttt{RST}, \texttt{URG},
  \texttt{PSH}, a cui si aggiungono i due valori \texttt{ALL} e \texttt{NONE},
  il cui significato è ovvio. Possibili esempi sono:
\begin{Example}
--tcp-flags SYN,ACK,FIN,RST SYN
--tcp-flags ! SYN,ACK,RST SYN
\end{Example}
  
\item[\texttt{-{}-syn}] Seleziona i pacchetti che hanno il flag SYN attivo e i
  flag ACK e RST disattivi, che sono la caratteristica che identifica il
  pacchetto TCP usato per iniziare una connessione. Pertanto bloccare questi
  pacchetti significa bloccare ogni connessione TCP. È una abbreviazione della
  regola \texttt{-{}-tcp-flags SYN,RST,ACK SYN}. Al solito apponendo ad essa
  il carattere ``\texttt{!}'' si inverte la selezione.  Possibili esempi sono:
\begin{Example}
--syn
! --syn
\end{Example}

\item[\texttt{-{}-tcp-option}] Seleziona il pacchetto in base al valore della
  sezione dell'intestazione di un pacchetto TCP chiamata appunto \textit{TCP
    option}. Questa indica delle sezioni appunto opzionali che si possono
  trovare nell'intestazione, queste hanno sempre una struttura divisa in tre
  campi in cui il primo indica il tipo di opzione, ed è un numero a 8 bit
  selezionabile con questa opzione.  I restanti campi sono la lunghezza
  dell'opzione\footnote{essendo opzionale non è necessario che tutti i tipi di
    opzione siano riconosciuti, per questo se uno non lo è deve essere
    possibile scartare i dati relativi passando alla sezione successiva.} ed i
  relativi dati. Usando il carattere ``\texttt{!}'' si inverte la selezione.
  Possibili esempi sono:
\begin{Example}
--tcp-option 16
! --tcp-option 16
\end{Example}
  
\item[\texttt{-{}-mss}] Seleziona i pacchetti TCP con flag SYN o SYN/ACK che
  abbiano il valore specificato per la MSS \textit{Maximum Segment Size}, un
  parametro che controlla la dimensione massima dei pacchetti per quella
  connessione. Si può inoltre specificare un intervallo di valori usando il
  carattere ``\texttt{:}''. Possibili esempi sono:
\begin{Example}
--mss 100
--mss 150:200
\end{Example}
\end{basedescript}

Infine quando si specifica il protocollo ICMP con \texttt{-p icmp} diventa
disponibile una ulteriore selezione tramite l'opzione \texttt{-{}-icmp-type}
che seleziona il tipo di pacchetti; si possono selezionare i vari tipi di
pacchetti sia secondo il valore numerico, come specificato nella definizione
del protocollo, (si veda
l'\href{http://www.ietf.org/rfc/rfc0792.txt}{RFC~792}) che utilizzando uno dei
nomi ottenibili con il comando \texttt{iptables -p icmp -h}, che si sono
riportati in tab.~\ref{tab:fw_icmp_type}.


\subsection{Le estensioni dei criteri di selezione}
\label{sec:fw_match_extension}

I precedenti criteri di selezione sono quelli più elementari, che supportano
la selezione sulla base dei principali parametri dei protocolli più
importanti. La flessibilità del \textit{netfilter} è che diventa possibile,
scrivendo degli opportuni moduli per il kernel, estendere le capacità di
selezione dei pacchetti.

Per questo esiste l'opzione \texttt{-m} (o \texttt{-{}-match}) che permette di
attivare queste estensioni, ciascuna delle quali ha un suo nome (di norma
corrispondente al nome del modulo usato dal kernel). La sintassi comune in
questi casi è richiedere l'uso dell'estensione con il comando \texttt{-m
  estensione} per poi utilizzarla usando le nuove opzioni ad essa relative,
che diventano disponibili una volta che la si è attivata.

Grazie a questi moduli le capacità di selezione dei pacchetti possono essere
ampliate in maniera incredibilmente estesa e complessa, mettendo a
disposizione, oltre a criteri basati sulle proprietà specifiche di ciascun
pacchetto (in genere relativi a dati presenti nelle intestazioni dei
protocolli) altri criteri più astratti, relativi a proprietà più ampie e non
legate al singolo pacchetto, come quelle usate dal filtro sugli stati il cui
funzionamento è illustrato in sez.~\ref{sec:fw_conntrack}.

Un elenco delle principali estensioni dei criteri di selezione è quello
seguente, in cui per ciascuna estensione si riportano le principali
caratteristiche e le ulteriori opzioni di controllo abilitate:
\begin{basedescript}{\desclabelwidth{1.cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{-m limit}] L'estensione permette di utilizzare uno dei criteri
  di selezione speciale che non dipende dal contenuto di un singolo pacchetto,
  ma da proprietà ``\textsl{collettive}'' degli stessi. Questa estensione
  permette di creare una selezione in base al flusso (nel senso di numero per
  unità di tempo) di pacchetti che corrispondono ad un determinato criterio.
  Si può così limitare il flusso di pacchetti accettati, in modo da rispondere
  ad eventuali attacchi di \itindex{Denial~of~Service~(DoS)} DoS (vedi
  sez.~\ref{sec:security_risk}) basati su tecniche di \itindex{flood}
  \textit{flood}.\footnote{si chiamano così le tecniche che mirano a creare
    una ``\textsl{inondazione}'' di pacchetti nei confronti di una macchina
    bersaglio, in modo da poterla bloccare nel tentativo di rispondere.}
  
  Il funzionamento di questa estensione non è banale, dato che non è semplice
  calcolare un flusso medio di pacchetti, in quanto il valore di una media
  temporale dipende strettamente dal periodo di tempo su cui la si calcola. Se
  si contasse semplicemente il numero di pacchetti che arrivano durante un
  certo intervallo di tempo, una raffica concentrata di pacchetti potrebbe
  dare un flusso elevatissimo se l'intervallo su cui si media è piccolo e
  coincide con il picco, e nullo nei successivi intervalli, con variazioni
  enormi dei possibili valori della media a seconda della dimensione
  dell'intervallo in cui la si calcola.
  
  Per evitare questo problema e garantire comunque un flusso medio affidabile
  il meccanismo di selezione è assimilabile a quello di un \textsl{serbatoio}
  di pacchetti.  Fintanto che nel serbatoio c'è spazio tutti i pacchetti
  vengono accettati, e il criterio di selezione corrisponde.  Quando lo spazio
  si esaurisce ogni ulteriore pacchetto sarà scartato. Il serbatoio però viene
  svuotato ad un ritmo costante, cosicché dopo un certo tempo si libera dello
  spazio e un nuovo pacchetto potrà essere accettato. In questo modo si può
  garantire su una media di lungo periodo (a serbatoio vuoto si può avere un
  picco dovuto ad una raffica di pacchetti) un flusso costante.
  
  Per controllare questo meccanismo l'estensione introduce due opzioni, la
  prima delle quali, \texttt{-{}-limit-burst}, è quella che ci permette di
  stabilire la dimensione in numero di pacchetti del nostro serbatoio. Il suo
  valore di default è di 5 pacchetti; questo significa che una volta inserita
  la regola i primi 5 pacchetti saranno sempre accettati, mentre per i
  successivi si dovrà aspettare che il \textsl{serbatoio} si sia svuotato a
  sufficienza per accettarne di altri. Questo comportamento ci fa anche capire
  il significato del nome dell'opzione: con questa possiamo decidere fino a
  che punto vogliamo rispondere a dei flussi concentrati (i \textit{burst}) di
  pacchetti.
  
  Invece l'opzione che controlla lo \textsl{svuotamento} del nostro serbatoio,
  e definisce pertanto il flusso medio di pacchetti che accetteremo, è
  \texttt{-{}-limit} che permette di definire la frequenza con cui si libera
  uno spazio per un nuovo pacchetto nel serbatoio (il valore di default è 3
  all'ora).  L'opzione prende un parametro del tipo \texttt{N/tempo} dove
  \texttt{N} indica il numero di spazi da liberare, e \texttt{tempo}
  l'intervallo di tempo in cui farlo; quest'ultimo deve essere specificato
  tramite una opportuna parola chiave, l'opzione accetta i valori
  \texttt{second}, \texttt{minute}, \texttt{hour}, o \texttt{day}.
  Possibili esempi sono:
\begin{Example}
--limit 3/second
--limit-burst 10    
\end{Example}

%   Infine
%   l'uso del carattere ``\texttt{!}'' anteposto a questa opzione serve ad
%   invertire la selezione (cioè ad accettare i pacchetti che escono quando il
%   serbatoio è pieno).
% TODO questo è citato nella man page ma non va nel comando, verificare perché

% TODO trattare hashlimit
% \item[\texttt{-m hashlimit}] Questa estensione consente di applicare dei
%   limiti, con gli stessi criteri di funzionamento della precedente
%   \texttt{-{}-limit}, a gruppi di connessioni usando una unica regola. 



% TODO trattare connlimit

\item[\texttt{-m connbytes}] L'estensione consente di effettuare una selezione
  in base al numero di pacchetti/bytes passati su una connessione, sia nelle
  singole direzioni che in totale, e permette così di individuare quelle che
  consumano più banda in modo da poterle adeguatamente abbassare di priorità.
  Perché l'estensione possa funzionare è necessario abilitare la contabilità
  dei pacchetti in transito sulle connessioni scrivendo un valore diverso da
  zero in \texttt{/proc/sys/net/netfilter/nf\_conntrack\_acct}, ma si tenga
  presente che questa sarà presente solo per le nuove connessioni create dopo
  l'abilitazione. Se l'informazione non è presente il criterio non
  corrisponderà mai.

  L'estensione abilita tre nuove opzioni; la prima è \texttt{-{}-connbytes}
  che indica l'intervallo dei valori in pacchetti o bytes su cui effettuare la
  selezione e deve essere specificata con valori numerici nella forma
  \texttt{min:max} dove la seconda parte (\texttt{:max}) può essere omessa per
  impostare solo un valore minimo, la selezione inoltre può essere invertita
  anteponendo il carattere ``\texttt{!}''. La seconda opzione è
  \texttt{-{}-connbytes-dir} che indica quali direzioni del flusso di
  pacchetti prendere in esame nella selezione e richiede come argomento uno
  fra i valori \texttt{original} (i pacchetti in uscita che han creato la
  connessione) \texttt{reply} (le risposte) e \texttt{both} (entrambe le
  direzioni). La terza opzione è \texttt{-{}-connbytes-mode} che invece
  consente di indicare se i valori specificati per \texttt{-{}-connbytes}
  devono essere considerati come numero di pacchetti (\texttt{packets}),
  numero di byte (\texttt{bytes}) o dimensione media del pacchetto
  \texttt{avgpkt}. Un possibile esempio è:
\begin{Example}
--connbytes 1000000 --connbytes-dir both --connbytes-mode bytes
--connbytes 10000 --connbytes-dir reply --connbytes-mode packets
\end{Example}


% TODO trattare dccp

\item[\texttt{-m mac}] L'estensione permette di selezionare, attraverso
  l'opzione \texttt{-{}-mac-source}, il pacchetto sulla base del MAC address
  sorgente del pacchetto (in genere Ethernet) che arriva sull'interfaccia di
  rete. Questo criterio è disponibile solo sulle catene di
  \texttt{PREROUTING}, \texttt{FORWARD} e \texttt{INPUT}. Al solito è
  possibile invertire la selezione con ``\texttt{!}''.  Possibili esempi sono:
\begin{Example}
--mac-source 00:0A:95:74:C3:D4
--mac-source ! 00:0A:95:74:C3:D4
\end{Example}
  
\item[\texttt{-m mark}] L'estensione permette di selezionare, attraverso
  l'opzione \texttt{-{}-mark}, i pacchetti che attraversano il
  \textit{netfilter} che sono stati marcati con un opportuno valore tramite
  l'uso dell'azione \texttt{MARK} (vedi sez.~\ref{sec:fw_iptables_target} per
  la spiegazione del meccanismo). L'opzione prende come parametro il valore
  numerico impostato per il relativo pacchetto. Questo può essere specificato
  anche nella forma \texttt{valore/maschera}, dove la maschera viene usata per
  eseguire un AND binario del valore del \texttt{MARK} del pacchetto prima di
  eseguire il confronto. Possibili esempi sono:
\begin{Example}
--mark 10
--mark 1/7
\end{Example}
  
\item[\texttt{-m multiport}] L'estensione permette di utilizzare le opzioni di
  selezione per le porte sorgente e destinazione \texttt{-{}-source-ports} e
  \texttt{-{}-destination-ports}. Queste sono molto simili (presentano solo
  una \texttt{s} aggiunta al nome) a quelle illustrate in
  sez.~\ref{sec:fw_match_extension} per i protocolli TCP e UDP e come in quel
  caso possono essere usate solo se si è richiesta anche una selezione sui
  suddetti protocolli (con \texttt{-p tcp} o \texttt{-p udp}). L'estensione
  permette di usare una sintassi in cui diventa possibile selezionare le porte
  con una lista di numeri (separati da virgole e senza spazi, con un limite
  massimo di 15 porte diverse) invece che singolarmente o come intervalli.
  L'estensione definisce inoltre l'opzione \texttt{-{}-ports} che permette di
  applicare la stessa selezione alla lista di numeri indicati richiedendo che
  porta destinazione e sorgente siano identiche, e corrispondenti ad una delle
  porte della lista.  Possibili esempi sono:
\begin{Example}
--source-ports 25,80,111
--destination-ports 25,80,111
--ports 5000,5001
\end{Example}
  
\item[\texttt{-m owner}] L'estensione permette di filtrare usando alcune
  caratteristiche specifiche del processo che ha creato i pacchetti, ed è
  utilizzabile soltanto sulla catena di \texttt{OUTPUT}. Dato che alcuni
  pacchetti (ad esempio quelli ICMP) vengono creati dal kernel e non sono mai
  associabili ad un processo, essi non potranno mai essere selezionati da
  questa estensione. L'elenco delle opzioni possibili è il seguente:
  \begin{basedescript}{\desclabelwidth{2.5cm}}
  \item[\texttt{-{}-uid-owner}] seleziona i pacchetti creati da un processo
    con user-ID effettivo uguale a quello specificato come parametro.
  \item[\texttt{-{}-gid-owner}] seleziona i pacchetti creati da un processo
    con group-ID effettivo uguale a quello specificato come parametro.
  \item[\texttt{-{}-pid-owner}] seleziona i pacchetti creati dal processo il
    cui \textit{pid} è uguale a quello specificato.
  \item[\texttt{-{}-sid-owner}] seleziona i pacchetti creati da un processo il
    cui session-ID è uguale a quello specificato come parametro.
  \item[\texttt{-{}-cmd-owner}] seleziona i pacchetti creati da un processo
    invocato con il comando specificato.\footnote{questa opzione è presente
      solo quando \texttt{iptables} è stato compilato con un kernel che
      supporta questa funzionalità.}
  \end{basedescript}

%\item[\texttt{-m physdev}] 

%\item[\texttt{-m pkttype}] 
 
% \item[\texttt{-m recent}] 

%\item[\texttt{-m sctp}]
 
%\item[\texttt{-m set}] 
 
\item[\texttt{-m state}] Questa è l'estensione che permette di utilizzare il
  filtro degli stati, la cui descrizione dettagliata è in
  sez.~\ref{sec:fw_state_filter}, usando le informazioni contenute nel sistema
  di \textit{connection tracking} (anche questo descritto in
  sez.~\ref{sec:fw_conntrack}).  L'estensione abilita l'opzione
  \texttt{-{}-state}, cui si passa la lista (separata da virgole e senza
  spazi) degli stati che si vogliono selezionare, secondo i nomi riportati in
  tab.~\ref{tab:fw_connection_states}.

%\item[\texttt{-m string}] 

%\item[\texttt{-m time}] 

\item[\texttt{-m tos}] Questa estensione permette di utilizzare l'opzione
  \texttt{-{}-tos} per selezionare i pacchetti in base al valore del campo TOS
  (\textit{Type of Service}) dell'intestazione dei pacchetti IP (vedi
  fig.~\ref{fig:fw_IP_header}). Questo è un campo di 8 bit usato\footnote{non
    molto, in realtà, dato che non tutti i sistemi operativi lo supportano e
    molti amministratori ignorano completamente questa proprietà nella
    configurazione dei router.} per differenziare i flussi di dati, che serve
  a caratterizzarne la tipologia; ad esempio per indicare che i pacchetti
  devono essere trasmessi il più rapidamente possibile, o che invece occorre
  ottimizzare la quantità dei dati trasmessi, più che la rapidità o la
  latenza.  L'opzione prende come parametro il valore numerico del TOS
  espresso in cifra esadecimale, o tramite uno dei valori simbolici illustrati
  in tab.~\ref{tab:fw_tos_values}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|p{8cm}|}
    \hline
    \multicolumn{2}{|c|}{\textbf{Valore}}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{Minimize-Delay}&\texttt{0x10}     & Ottimizzare la trasmissione
                                                per rendere più veloce
                                                possibile la ritrasmissione
                                                dei pacchetti (usato per
                                                traffico interattivo di
                                                controllo come SSH).\\
    \texttt{Maximize-Throughput}&\texttt{0x8} & Ottimizzare la trasmissione
                                                per rendere il più elevato
                                                possibile il flusso netto di
                                                dati (usato su traffico dati,
                                                come quello di FTP).\\ 
    \texttt{Maximize-Reliability}&\texttt{0x4}& Ottimizzare la trasmissione
                                                per ridurre al massimo le
                                                perdite di pacchetti (usato su
                                                traffico come TFTP o BOOTP).\\ 
    \texttt{Minimize-Cost} &\texttt{0x2}      & Ottimizzare la trasmissione
                                                per utilizzare i collegamenti
                                                con minor costo (usato per i
                                                protocolli di streaming). \\
    \texttt{Normal-Service}&\texttt{0x0}      & Nessuna richiesta specifica.\\
    \hline
  \end{tabular}
  \caption{Valori del campo TOS utilizzabili con l'opzione \texttt{-{}-tos}.}
\label{tab:fw_tos_values}
\end{table}
  
\item[\texttt{-m ttl}] Questa estensione permette di utilizzare l'opzione
  \texttt{-{}-ttl} per selezionare i pacchetti in base al valore del campo TTL
  (\textit{Time to Live}) dell'intestazione dei pacchetti IP (vedi
  fig.~\ref{fig:fw_IP_header}). Il campo indica il numero di router che il
  pacchetto può ancora attraversare prima di essere scartato.
  
\item[\texttt{-m unclean}] L'estensione non definisce nessuna opzione
  ulteriore e si limita a selezionare tutti i pacchetti che sembrano essere
  malformati o avere caratteristiche non usuali. In genere la si usa per
  identificare il traffico sospetto. L'estensione è considerata ancora
  sperimentale e l'uso della stessa per scartare i pacchetti può risultare
  pericoloso e portare anche alla perdita di pacchetti facenti parti di
  connessioni perfettamente regolari.

\end{basedescript}

% TODO mettere le nuove opzioni avanzate

\subsection{Le azioni sui pacchetti}
\label{sec:fw_iptables_target}

Il terzo ed ultimo componente di ogni regola di \texttt{iptables} è l'azione
da applicare ad ogni pacchetto selezionato nella regola stessa, quello che nel
vocabolario del comando è chiamato \textit{target}. L'opzione che controlla
questa azione, che decide il destino del pacchetto quando questo corrisponde
alla regola di selezione, è \texttt{-j} (o \texttt{-{}-jump}), seguita
dall'identificatore dell'azione da applicare (il nome del \textit{target}).

Come accennato in sez.~\ref{sec:fw_netfilter_structure} nell'infrastruttura
del \textit{netfilter}, a livello del kernel, sono già previste alcune azioni
elementari possibili, che si riflettono in quelli che in \texttt{iptables}
sono chiamati gli \textit{special target}, cioè una serie di azioni che sono
sempre definite e che determinano la conclusione della scansione delle regole
all'interno di una catena predefinita (o in una eventuale ulteriore catena
definita dall'utente su cui lo si poteva esser mandato). Una di queste è
sempre quella di inviare il pacchetto su una catena definita dall'utente (da
questo deriva il nome \textit{jump}), le altre sono riportate in
tab.~\ref{tab:fw_standard_target}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Opzione}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{ACCEPT}& Accetta il pacchetto che viene fatto immediatamente 
                     proseguire per le successive catene (secondo lo schema di
                     attraversamento di fig.~\ref{fig:iptable_flux_scheme})
                     all'interno nel \textit{netfilter}.\\ 
    \texttt{DROP}  & Il pacchetto viene scartato immediatamente, ed ogni
                     ulteriore controllo non è più necessario. Nessuna altra
                     regola verrà presa in considerazione.\\
    \texttt{QUEUE} & Il pacchetto viene passato in user space (dove può essere
                     letto dagli opportuni programmi).\\
    \texttt{RETURN}& Blocca l'attraversamento della catena corrente e torna a
                     quella precedente, se usato su una catena predefinita
                     applica la politica di default della stessa.\\
    \hline
  \end{tabular}
  \caption{Le azioni elementari (\textit{special target}) del comando
    \texttt{iptables}.} 
\label{tab:fw_standard_target}
\end{table}

Una delle caratteristiche di \texttt{iptables} è che oltre ai criteri di
selezione è possibile ampliare anche le possibili azioni che si possono
eseguire sui pacchetti, al di là di quelle elementari di
tab.~\ref{tab:fw_standard_target}, attraverso quelle che vengono chiamate le
``\textit{target extension}'', sempre grazie all'utilizzo di ulteriori moduli
nel kernel che definiscono nuovi parametri (corrispondenti a nuovi
\textit{target}) da utilizzare con l'opzione \texttt{-j}, che a loro volta
possono richiedere ulteriori opzioni.

Le principali estensioni dei \textit{target} disponibili come azioni da
compiere sui pacchetti è data dalla seguente lista (non completa, dato che
molte estensioni non è detto siano incluse nei sorgenti ufficiali del kernel):
\begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{DNAT}] Questa è una azione valida solo nella tabella di
  \texttt{nat} e nelle catene \texttt{PREROUTING} e \texttt{OUTPUT}, e nelle
  eventuali catene definite dall'utente se vi si \textsl{salta} a partire da
  una di queste.
  
  Questa azione permette di riscrivere l'indirizzo di destinazione di un
  pacchetto. Come già accennato in sez.~\ref{sec:fw_conntrack} la regola di
  selezione viene applicata solo sul primo pacchetto di una connessione
  (necessita quindi dell'uso del sistema del \textit{conntrack}) e poi viene
  automaticamente ripetuta per tutti i pacchetti facenti parte della stessa
  connessione. Una volta modificato il pacchetto questo verrà instradato
  secondo il nuovo indirizzo.
  
  Si tenga presente inoltre che siccome il \textit{Destination NAT} è operato
  nella catena di \texttt{PREROUTING}, nel successivo attraversamento del
  \textit{netfilter} i pacchetti modificati con \texttt{DNAT} si presenteranno
  con l'indirizzo modificato, per cui tutte le eventuali regole di firewall
  che si vogliono mettere nelle catene successive dovranno usare
  quest'ultimo. Lo stesso vale per i pacchetti modificati sulla catena di
  \texttt{OUTPUT}, in quanto la catena di \texttt{nat} è attraversata prima di
  quella di \texttt{filter} (si riveda lo schema di
  fig.~\ref{fig:iptable_flux_scheme}).  In caso di DNAT le sole catene che
  vedono l'indirizzo originale del pacchetto sono quella di
  \texttt{PREROUTING} e quella di \texttt{OUTPUT} ma solo nella tabella di
  \texttt{mangle}.
  
  La traslazione degli indirizzi viene specificata attraverso l'opzione
  \texttt{-{}-to-destination}, questa può prendere come parametro un singolo
  indirizzo di destinazione, od un intervallo che va indicato con gli
  indirizzi degli estremi separati da un ``\texttt{-}'' senza spazi
  interposti. In questo caso la traslazione sceglierà a turno uno dei valori
  dell'intervallo (dato che la scelta è fatta solo sul primo pacchetto di una
  connessione, ed i successivi pacchetti subiscono la stessa traslazione,
  questo garantisce che tutto il traffico vada verso lo stesso IP finale). In
  questo modo si può eseguire una forma semplificata (\textit{round-robin}) di
  bilanciamento di carico.
  
  Qualora si effettui la traslazione per pacchetti TCP o UDP, si potrà
  effettuare la traslazione anche della porta di destinazione, da specificare
  singolarmente facendola seguire all'indirizzo di destinazione separata con
  un ``\texttt{:}''. Si potrà anche specificare un intervallo di porte
  indicando i due estremi separati da un ``\texttt{-}''. Questo è possibile
  solo avendo abilitato con \texttt{-p} la relativa selezione sui suddetti
  protocolli. Possibili esempi sono:
\begin{Example}
--to-destination 192.168.2.2
--to-destination 192.168.2.2:8080
--to-destination 192.168.2.16-192.168.2.32
--to-destination 192.168.2.16:6000-6010
\end{Example}

%item[\texttt{DSCP}] 

%item[\texttt{ECN}] 
  
\item[\texttt{LOG}] Questa azione abilita la registrazione sul \textit{syslog}
  dei dati dei pacchetti selezionati. Dato che la registrazione viene eseguita
  dal kernel la facility del \textit{syslog} utilizzata è \texttt{kern};
  questo significa che i messaggi vengono mostrati anche dal comando
  \texttt{dmesg} e inviati, a meno di non ridurne la priorità, sulla console.
  Una regola con criterio di selezione che usi questa azione come
  \textit{target} non termina la scansione della catena, che proseguirà dalla
  regola successiva. Per questo se si vuole eseguire il logging di pacchetti
  che poi si desidera scartare occorre sempre usare una azione di \texttt{LOG}
  prima di quella di \texttt{DROP}. Si tenga presente inoltre che i log
  contengono informazioni dettagliate riguardo il vostro traffico di rete, che
  possono essere lette dagli utenti e costituire un possibile rischio di
  sicurezza.
  
  Con l'uso di questa azione vengono attivate una serie di opzioni che
  permettono di definire le modalità in cui il logging viene eseguito, il loro
  elenco è il seguente:
  \begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
  \item[\texttt{-{}-log-level}] imposta la priorità dei messaggi, prende come
    parametro il valore numerico della priorità o il corrispondente
    identificativo, come si può ottenere dalla pagina di manuale del
    \textit{syslog}, accessibile con \texttt{man syslog.conf}. Si può usare
    questo valore e le impostazioni del \textit{syslog} per evitare che i log
    prodotti da \texttt{iptables} siano letti dagli utenti. Possibili esempi
    sono:
\begin{Example}
--log-level 3
--log-level debug
\end{Example}
  \item[\texttt{-{}-log-prefix}] Permette di aggiungere una stringa (di un
    massimo di 29 caratteri) da premettere ai messaggi di log, una
    caratteristica utile per aumentarne la leggibilità. Possibili esempi sono:
\begin{Example}
--log-prefix "INPUT"
\end{Example}
  \item[\texttt{-{}-log-tcp-sequence}] Permette di inserire nei log i
    \textit{numeri di sequenza}\footnote{i \textit{numeri di sequenza} sono
      delle informazioni caratteristiche del protocollo TCP (vedi
      fig.~\ref{fig:fw_TCP_header}), mantenute nelle intestazioni dei
      pacchetti, che identificano ciascun pacchetto e permettono di inserirlo
      al posto giusto nel flusso dei dati quando questo viene riassemblato.}
    dei pacchetti TCP. Questa opzione non ha parametri.
  \item[\texttt{-{}-log-tcp-options}] Permette di inserire nei log il valore
    delle opzioni del protocollo TCP. Questa opzione non ha parametri.
  \item[\texttt{-{}-log-ip-options}] Permette di inserire nei log il valore
    delle opzioni del protocollo IP. Questa opzione non ha parametri.
  \end{basedescript}
  
\item[\texttt{MARK}] Questa azione è valida solo nella tabella di
  \texttt{mangle}, e serve per marcare i pacchetti con un valore numerico,
  questo non va a modificare niente nel contenuto del pacchetto stesso, ma è
  una sorta di etichetta che viene attaccata al pacchetto che resterà
  associata al pacchetto all'interno del kernel. Così sarà possibile filtrare
  i pacchetti sulla base di tale valore con l'estensione \texttt{-{}-mark}
  vista in sez.~\ref{sec:fw_match_extension}, ma lo stesso valore sarà
  accessibile anche dal sistema di routing avanzato ed in questo modo si
  potranno impostare politiche di routing diverse (ad esempio una limitazione
  sul traffico) per i pacchetti ``\textsl{marcati}'' tramite questa azione.
  
  Il valore da usare per marcare il pacchetto deve essere specificato
  attraverso l'opzione \texttt{-{}-set-mark} che prende come parametro il
  valore numerico da associare al pacchetto. Si ricordi che questo valore è
  puramente interno al kernel e pertanto non sarà disponibile quando il
  pacchetto transiterà su altre macchine.  Possibili esempi sono:
\begin{Example}
--set-mark 4
\end{Example}
  
\item[\texttt{MASQUERADE}] Questa azione è valida soltanto nella tabella di
  \texttt{nat} e nella catena di \texttt{POSTROUTING}.  Sostanzialmente è una
  abbreviazione di \texttt{SNAT} e viene usata principalmente per condividere
  le connessioni temporanee ad Internet (in genere quelle via modem gestite
  con \texttt{pppd} dove viene assegnato un IP dinamico). L'azione è quella di
  fare un \textit{Source Network Address Translation} usando l'IP assegnato
  dinamicamente (ricavato da quello assegnato all'interfaccia da cui i
  pacchetti devono uscire). In tutti gli altri casi è meglio usare
  \texttt{SNAT} in quanto la risoluzione dell'indirizzo dall'interfaccia
  comporta un certo degrado delle prestazioni.
  
  L'uso di \texttt{MASQUERADE} ha inoltre l'effetto di cancellare tutte le
  connessioni presenti quando l'interfaccia va giù, dato che è poco probabile
  avere lo stesso indirizzo quando l'interfaccia sarà riutilizzata e che in
  ogni caso si saranno dovuti bloccare tutti i programmi che le usavano. In
  questo modo si evita che restino ad occupare spazio nella tabella delle
  connessioni voci ormai inutilizzabili, e che si possa ricevere del traffico
  spurio corrispondente a connessioni che in realtà non esistono più.
  
  Se si opera su pacchetti TCP e UDP (specificando l'uso di detti protocolli
  con \texttt{-p}) con l'uso di questa azione viene abilitata anche l'opzione
  \texttt{-{}-to-ports} che può essere usata per soprassedere l'assegnazione
  automatica delle porte sorgente fatta dal kernel (torneremo su questo nella
  spiegazione di \texttt{SNAT}) con un intervallo da specificare come
  parametro indicandone i due estremi separati con un ``\texttt{-}''. Si può
  anche indicare una sola porta.  Possibili esempi sono:
\begin{Example}
--to-ports 10000
--to-ports 10000-15000
\end{Example}

%\item[\texttt{MIRROR}] 
  
\item[\texttt{REDIRECT}] Questa azione è valida soltanto nella tabella di
  \texttt{nat} e nelle catene di \texttt{PREROUTING} e \texttt{OUTPUT} (o
  nelle catene definite dall'utente che derivino da queste) e serve a
  modificare l'IP di destinazione dei pacchetti selezionati perché questi
  vengano inviati alla macchina stessa (i pacchetti generati localmente
  vengono mappati sul localhost). Qualora si siano selezionati (con
  \texttt{-p}) dei pacchetti TCP o UDP diventa disponibile l'opzione
  \texttt{-{}-to-ports} che permette anche di specificare su quale porta
  effettuare la redirezione (normalmente viene usata quella originaria del
  pacchetto). L'opzione permette anche di specificare un intervallo, indicato
  tramite gli estremi separati con un ``\texttt{-}''.  Possibili esempi sono:
\begin{Example}
--to-ports 8080
--to-ports 8000-8010
\end{Example}
  
\item[\texttt{REJECT}] Questa azione è sostanzialmente equivalente a
  \texttt{DROP}, ma oltre ad eliminare il pacchetto fermando ogni ulteriore
  scansione delle regole, si incarica anche di inviare indietro un opportuno
  messaggio di errore. L'azione è utilizzabile solo nelle catene di
  \texttt{INPUT}, \texttt{FORWARD} e \texttt{OUTPUT}. L'azione abilita l'uso
  dell'opzione \texttt{-{}-reject-with} che permette di specificare il
  pacchetto inviato come messaggio di errore, e prende come parametro uno dei
  valori riportati in tab.~\ref{tab:fw_reject_message}.

\begin{table}[!h]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|}
    \hline
    \textbf{Opzione}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{icmp-net-unreachable}  & Restituisce un pacchetto ICMP di tipo
                                     \textit{net unreachable}.\\
    \texttt{icmp-host-unreachable} & Restituisce un pacchetto ICMP di tipo
                                     \textit{host unreachable}.\\
    \texttt{icmp-port-unreachable} & Restituisce un pacchetto ICMP di tipo
                                     \textit{port unreachable}.\\
    \texttt{icmp-proto-unreachable}& Restituisce un pacchetto ICMP di tipo
                                     \textit{proto unreachable}.\\
    \texttt{icmp-net-prohibited}   & Restituisce un pacchetto ICMP di tipo
                                     \textit{net prohibited}.\\
    \texttt{icmp-host-prohibited}  & Restituisce un pacchetto ICMP di tipo
                                     \textit{host prohibited}.\\
    \texttt{icmp-admin-prohibited} & Restituisce un pacchetto ICMP di tipo
                                     \textit{admin prohibited}.\\
    \texttt{tcp-reset}             & Restituisce un pacchetto TCP con il flag
                                     RST attivo.\\
    \hline
  \end{tabular}
  \caption{I vari tipi di messaggi di errore utilizzabili con l'opzione
    \texttt{-{}-reject-with}.} 
\label{tab:fw_reject_message}
\end{table}

Il valore di default è \texttt{icmp-port-unreachable}, degli altri
\texttt{icmp-admin-prohibited} può essere usato solo con i kernel che lo
supportano, mentre \texttt{tcp-reset} può essere usato solo con regole che
selezionano pacchetti TCP, e serve a chiudere in maniera pulita una
connessione TCP.

\item[\texttt{SNAT}] Questa azione è valida solo nella tabella di \texttt{nat}
  e nella catena di \texttt{POSTROUTING}. Come le altre regole che operano
  nella tabella di \texttt{nat} essa si applica solo al primo pacchetto di una
  connessione e poi viene automaticamente ripetuta per tutti i pacchetti
  facenti parte della stessa connessione. L'azione modifica l'indirizzo
  sorgente dei pacchetti eseguendo il \textit{Source NAT},\footnote{questo è
    il caso più comune di NAT, che viene implementato di default nella gran
    parte dei router usati per connettersi alle linee DSL, tanto che spesso si
    usa NAT come indicativo di questo particolare tipo di traslazione.} e si
  usa di solito per condividere una connessione ad internet, facendo in modo
  che tutti i pacchetti in uscita figurino come originanti dalla macchina
  corrente; il meccanismo del \textit{connection tracking} si incarica di
  effettuare automaticamente la traslazione inversa (sull'indirizzo di
  destinazione) per i pacchetti ottenuti in risposta ai precedenti.
  
  La traslazione degli indirizzi viene specificata attraverso l'opzione
  \texttt{-{}-to-source}, questa può prendere come parametro un singolo
  indirizzo sorgente, od un intervallo che va indicato con gli
  indirizzi degli estremi separati da un ``\texttt{-}'' (senza spazi
  interposti). In questo caso la traslazione sceglierà a turno uno dei valori
  dell'intervallo, ottenendo una forma semplificata (\textit{round-robin}) di
  bilanciamento.
  
  Qualora si effettui la traslazione per pacchetti TCP o UDP (selezionati in
  precedenza con \texttt{-p}) si può anche specificare (con sintassi analoga a
  quella di \texttt{DNAT}) una porta sorgente o un intervallo di porte da
  utilizzare per la traslazione. In tal caso i pacchetti uscenti avranno come
  porta sorgente un valore compreso nell'intervallo specificato.  Possibili
  esempi sono:
\begin{Example}
--to-source 192.168.2.2
--to-source 192.168.2.16-192.168.2.20
--to-source 192.168.2.16:10000-30000
\end{Example}
  
  In realtà per poter gestire più connessioni contemporanee l'utilizzo di
  questa opzione prevede che possano essere modificati, oltre l'indirizzo
  sorgente, anche altre caratteristiche dei pacchetti. Il kernel cerca di
  modificare il meno possibile i pacchetti limitandosi al solo indirizzo
  sorgente, ma qualora le modifiche siano necessarie perché si ha un conflitto
  (ad esempio due connessioni allo stesso server sullo stesso servizio che
  usano la stessa porta sorgente) il kernel deve intervenire per consentire
  una identificazione univoca della connessione. Questo nel caso dei pacchetti
  TCP e UDP significa che deve essere modificata anche la porta sorgente, nel
  qual caso la regola seguita è che (sempre che non si sia specificato in un
  intervallo definito) se la porta originale è inferiore a 512 vengono usate
  altre porte sotto 512, se è fra 512 a 1024 vengono usate porte inferiori a
  1024 e per tutte le altre porte sono usate quelle a partire da 1024.
  
  Nel caso di ICMP invece, non esistendo i numeri di porta, in caso di più
  pacchetti inviati allo stesso IP, viene modificato il campo di codice.

\item[\texttt{NOTRACK}] Questa azione è valida solo nella tabella di
  \texttt{raw} e consente di disabilitare il \textit{connection tracking} per
  tutti i pacchetti che corrispondono al criterio di selezione usato nella
  regola che la usa come \texttt{target}.

%\item[\texttt{TCPMSS}] 
  
\item[\texttt{TOS}] Questa azione è valida solo nella tabella di
  \texttt{mangle}, ed abilita l'uso dell'opzione \texttt{-{}-set-tos} che
  permette di modificare il valore del campo TOS nell'intestazione di
  IP,\footnote{come accennato in sez.~\ref{sec:fw_iptables_match} per
    l'omonimo criterio di selezione, il \textit{Type of Service} è un campo
    usato per classificare il traffico IP in una serie di classi in modo che
    possa essere trattato diversamente dai router.} usato per dare ai router
  indicazioni sul tipo di traffico di cui il pacchetto fa parte.  L'opzione
  prende come parametro il nuovo valore del TOS, che può essere specificato
  sia con il valore numerico esadecimale che con uno degli identificativi già
  visti in tab.~\ref{tab:fw_tos_values} per l'opzione relativa all'omonimo
  criterio di selezione.  Possibili esempi sono:
\begin{Example}
--set-tos 0x10
--set-tos Normal-Service
\end{Example}
  
\item[\texttt{TTL}] Questa azione è valida solo nella tabella di
  \texttt{mangle}, ed abilita l'uso di una serie di opzioni che permettono di
  modificare il valore del campo TTL di IP, usato per limitare il numero di
  volte che un pacchetto può transitare attraverso un router, in modo da
  evitare l'intrappolamento permanente in eventuali \textit{routing
    loop}.\footnote{si chiama così quella situazione in cui, per un qualche
    malfunzionamento della rete, i pacchetti si trovano ad essere reinviati ad
    un router da cui sono provenuti, innescando così un circolo vizioso; per
    questo il valore di questo campo viene decrementato di una unità ogni
    volta che un pacchetto attraversa un router e quando si annulla il
    pacchetto viene scartato e viene inviato in messaggio di errore
    (\textit{ICMP time expired}).} Questa azione può servire a riportare allo
  stesso valore di TTL tutti i pacchetti uscenti dalla macchina, in modo da
  mascherare all'esterno i valori diversi che indicherebbero la presenza di
  una operazione di \texttt{SNAT}. Le opzioni abilitate con l'uso di questa
  azione sono:
  \begin{basedescript}{\desclabelwidth{1.9cm}\desclabelstyle{\nextlinelabel}}
  \item[\texttt{-{}-ttl-set}] imposta un valore per il TTL dei pacchetti
    selezionati, da specificare come parametro per l'opzione (il valore di
    default usato dal kernel è 64).
  \item[\texttt{-{}-ttl-dec}] permette di decrementare il valore del TTL dei
    pacchetti selezionati del valore specificato come parametro. Questo può
    essere utilizzato per bloccare il raggiungimento di certi servizi (di
    norma il DNS) da macchine troppo lontane, per costringerle ad usare server
    più vicini.
  \item[\texttt{-{}-ttl-inc}] permette di incrementare il valore del TTL dei
    pacchetti selezionati del valore specificato come parametro, dato che al
    passaggio da un router questo valore viene decrementato di uno, con questa
    opzione lo si può reincrementare in modo da non far rilevare la presenza
    del nostro firewall in programmi come \texttt{traceroute}.
  \end{basedescript}
  Possibili esempi sono:
\begin{Example}
--ttl-set 64
--ttl-dec 5
--ttl-inc 1
\end{Example}

%\item[\texttt{ULOG}] 
\end{basedescript}

% TODO mettere i nuovi target avanzati


\subsection{Programmi di gestione}
\label{sec:fw_firewall_utils}

% TODO mettere ipset

Abbiamo fin qui trattato le varie capacità del \textit{netfilter} di Linux, e
come queste possono essere utilizzate attraverso l'uso del comando
\texttt{iptables}; esso però consente di eseguire sulle tabelle del kernel
solo una operazione alla volta, per questo sono stati creati degli opportuni
programmi per permettere la gestione di \textsl{gruppi} di regole.

Il comando \texttt{iptables} infatti permette di inserire le regole una alla
volta, per questo in genere si suole costruire un firewall tramite uno script
di shell che si incarica di invocare \texttt{iptables} più volte. Quando però
le regole diventano molte questo meccanismo comporta una penalizzazione nelle
prestazioni, infatti si deve ripetere il comando continuamente, e questo
comporta che ogni volta deve essere estratto dal kernel l'intero insieme delle
regole, che deve essere opportunamente modificato secondo quanto specificato
dal comando, e poi reinserito nel kernel, compiendo così un gran numero volte
il trasferimento dei dati da kernel space ad user space.

Per velocizzare queste operazioni insieme ad \texttt{iptables} vengono forniti
altri due programmi che permettono il trasferimento di un gruppo di regole in
un blocco unico. Il primo è \texttt{iptables-save}, che serve a scrivere
(sullo standard output) l'insieme di regole correntemente attive, utilizzando
un apposito formato di facile scansione. Il comando permette anche, con
l'opzione \texttt{-c} (o \texttt{-{}-counters}) di salvare i valori dei
contatori associati a ciascuna regola,\footnote{e può servire quando non si
  vogliono perdere questi valori, che potrebbero essere utilizzati a fini
  statistici, tutte le volte che si modificano le regole del firewall.} mentre
con \texttt{-t} (o \texttt{-{}-table}) si può richiedere il salvataggio delle
regole relative ad una singola tabella, invece che a tutte e tre.  Un esempio
del formato generato da questo comando è il seguente:
\begin{FileExample}[label=iptables-save]
# Generated by iptables-save v1.2.9 on Sun Dec 14 19:52:50 2003
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -s 127.0.0.1 -d 127.0.0.1 -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
...
COMMIT
# Completed on Sun Dec 14 19:52:50 2003
\end{FileExample}


Il secondo comando, \texttt{iptables-restore}, permette di caricare nel kernel
un insieme di regole letto dallo standard input,\footnote{ovviamente, grazie
  alle normali capacità di redirezione presenti in qualunque shell, è sempre
  possibile utilizzare un file qualsiasi.} nello stesso formato usato da
\texttt{iptables-save}. A meno di non specificare l'opzione \texttt{-n} (o
\texttt{-{}-noflush}) le regole presenti vengono cancellate, mentre con
\texttt{-c} (o \texttt{-{}-counters}) si può richiedere il ripristino dei
relativi contatori.

Il problema con \texttt{iptables-restore} è che esso accetta, come è ovvio,
solo un contenuto statico, ed è pertanto impossibile utilizzarlo con una
qualche forma di scripting per permettergli ad esempio di usare un indirizzo
dinamico. In casi come questi l'unica soluzione possibile è quella di scrivere
uno script per modificare direttamente il file su cui si sono salvate le
regole da utilizzare, prima di darlo in pasto al comando stesso.

%% Nel caso di Debian è possibile far caricare automaticamente un insieme di
%% regole di \texttt{iptables} all'avvio, attraverso l'omonimo script di avvio
%% \texttt{/etc/init.d/iptables}. In genere la scelta se attivare o meno questa
%% funzionalità può essere fatta all'installazione di \texttt{iptables}, ma è
%% possibile cambiarla in seguito con \texttt{dpkg-reconfigure}. 

%% Lo script di avvio utilizza di default due insiemi di regole, \texttt{active}
%% ed \texttt{inactive}, mantenuti negli omonimi file in
%% \texttt{/var/lib/iptables}.



\section{Criteri per la costruzione di un firewall}
\label{sec:fw_filter_criteria}

Una volta esaminata la struttura del \textit{netfilter} e le funzionalità dei
comandi che permettono di utilizzarlo, passiamo a definire i criteri generali
per il filtraggio dei pacchetti, e le regole da utilizzare per la
realizzazione pratica di un firewall, entrando nei dettagli di come questo poi
possa essere realizzato con Linux.


\subsection{Le funzionalità dirette del kernel}
\label{sec:fw_kernel_sysctl}

Le regole del \textit{netfilter} non sono il solo componente da usare nella
realizzazione di un firewall; oltre al sistema del \textit{netfilter} infatti
il kernel fornisce direttamente anche una serie di funzionalità che, pur non
essendo direttamente legate al filtraggio dei pacchetti, sono di grande
utilità nella realizzazione di un firewall. Queste sono controllate
dall'interfaccia del \textit{sysctl},\footnote{per una trattazione di questa
  interfaccia si può fare riferimento al capitolo 6 di \cite{GaPiL},
  \textsl{Guida alla Programmazione in Linux}, disponibile su
  \url{http://gapil.gnulinux.it}.} che permette di impostare i valori di tutta
una serie di parametri interni al kernel.

L'accesso a questi parametri è di norma effettuabile attraverso il filesystem
\texttt{/proc};\footnote{si può usare anche il comando \texttt{sysctl}, ma in
  genere l'interfaccia è più macchinosa; molte distribuzioni però consentono
  di impostare detti parametri all'avvio attraverso il file
  \texttt{/etc/sysctl.conf}, per i dettagli si possono consultare le relative
  pagine di manuale.} infatti tutti i parametri sono visibili (e modificabili)
come file all'interno della directory \texttt{/proc/sys}. Nel nostro caso
quelli che ci interessano sono i parametri relativi alla rete, mantenuti nella
sottodirectory \texttt{net} ed in particolare quelli usati per controllare il
comportamento dello stack TCP/IP del kernel, a loro volta disponibili
nell'ulteriore sottodirectory \texttt{ipv4}.

In tab.~\ref{tab:fw_kernel_ipv4_options} si sono riportati, insieme ad una
breve spiegazione del loro significato, ed al tipo di valore utilizzato, i
principali parametri del kernel relativi allo stack TCP/IP rilevanti per la
costruzione di un firewall, modificabili scrivendo direttamente negli omonimi
file presenti nella directory \texttt{/proc/sys/net/ipv4}. Una descrizione più
completa dei parametri presenti in questa directory (relativi alla gestione
dello stack TCP/IP) si trova nella documentazione allegata al kernel, nel file
\texttt{Documentation/networking/ip-sysctl.txt}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|c|p{8cm}|}
    \hline
    \textbf{Parametro}&\textbf{Tipo}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{ip\_forward}      & \texttt{bool} & 
            Abilita il kernel all'inoltro dei pacchetti da una interfaccia ad
            un'altra, di default è disabilitato (valore nullo). Un valore non
            nullo lo abilita. \\
    \texttt{icmp\_echo\_ignore\_all} & \texttt{int} & 
            Istruisce il kernel a ignorare tutte le richieste di pacchetti
            ICMP di tipo \textit{echo reply} dirette alla macchina.\\
    \texttt{icmp\_echo\_ignore\_broadcast}& \texttt{bool} & 
            Istruisce il kernel a ignorare tutte le richieste di pacchetti
            ICMP di tipo \textit{echo reply} dirette a indirizzi di broadcast
            o multicast. \\
   % mettere echo_reply_rate.
    \texttt{icmp\_ratelimit}  & \texttt{int} & 
            Istruisce il kernel a limitare il numero di pacchetti ICMP che
            possono essere inviati per numero. Un valore nullo disabilita la
            limitazione, un valore positivo indica il numero di pacchetti al
            millisecondo.\\%\footnotemark\\ 
    \texttt{icmp\_ratemask}   & \texttt{int} & 
            Imposta la maschera binaria dei pacchetti ICMP per i quali vale la
            limitazione di flusso impostata con il precedente parametro
            \texttt{icmp\_ratelimit}. Viene attivata la limitazione per ciascun
            tipo di pacchetto per cui il bit nella posizione corrispondente al
            valore del tipo è attivo. \\
    \texttt{tcp\_syncookies}  & \texttt{bool} & 
            Abilita la protezione dei \textit{syncookies} nei confronti di
            attacchi di \itindex{flood} \textit{syn flood}.\\
    \hline
  \end{tabular}
  \caption{I parametri del kernel che controllano il comportamento dello stack
    TCP/IP di rilevanza per la costruzione di firewall, con relativo tipo di
    dato e spiegazione del significato.} 
  \label{tab:fw_kernel_ipv4_options}
\end{table}

% \footnotetext{il \texttt{jiffie} è l'unità di tempo dell'interrupt di sistema,
%   che è la base per la misura del tempo nel kernel, essa corrisponde nei
%   normali PC ad un centesimo di secondo.}

In realtà il primo parametro, \texttt{ip\_forward}, è usato nella costruzione
dei firewall solo per attivare l'inoltro dei pacchetti da una interfaccia ad
un'altra, una funzionalità che in realtà non ha niente a che fare con il
filtraggio dei pacchetti, ma che è necessaria quando si usano più interfacce.

Gli altri parametri permettono di bloccare o limitare direttamente (senza
l'uso di specifiche regole) alcuni pacchetti ICMP, infine il parametro
\texttt{tcp\_syncookies} richiede un kernel che sia stato compilato con la
relativa opzione, ed abilita una protezione specifica contro i cosiddetti
\itindex{flood} \textit{syn flood}, attacchi \itindex{Denial~of~Service~(DoS)}
DoS in cui la propria macchina viene \textsl{inondata} di pacchetti di inizio
connessione (i SYN appunto). Per bloccare questo tipo di attacchi quando la
coda delle connessioni per un socket viene esaurita inizia l'emissione di
speciali pacchetti (i cosiddetti \textit{syncookies}) e riprende
l'accettazione di ulteriori SYN solo in corrispondenza di una risposta. Questo
però modifica il funzionamento usuale del protocollo TCP, ed è da usare solo
in caso di emergenza in quanto degrada comunque notevolmente alcuni servizi.

Oltre ai parametri di tab.~\ref{tab:fw_kernel_ipv4_options}, che controllano
il comportamento dello stack TCP/IP del kernel nel suo insieme, esistono una
serie di altri parametri che permettono di configurarne il comportamento per
ciascuna interfaccia. Questi sono accessibili all'interno della directory
\texttt{/proc/sys/net/ipv4/conf}, che contiene a sua volta delle ulteriori
directory (ad esempio \texttt{lo}, \texttt{eth0}, ecc.) per ciascuna delle
interfacce di rete presenti nel sistema, e la directory \texttt{default} per
indicare l'interfaccia usata per la \textit{default route}. 

Oltre a queste è inoltre presente la directory speciale \texttt{all} che
contiene gli stessi parametri delle altre, in questo caso però essi assumono
un significato diverso e possono essere usati o per attivare la relativa
funzionalità contemporaneamente su tutte le interfacce, o per abilitare la
possibilità di usarla; in quest'ultimo caso occorrerà attivare esplicitamente
la funzionalità anche nella directory relative a ciascuna interfaccia (per
quelle su cui la si vuole). In tab.~\ref{tab:fw_kernel_ipv4_if_options} si
sono riportati i parametri rilevanti per la costruzione di un firewall.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|c|p{8cm}|}
    \hline
    \textbf{Parametro}&\textbf{Tipo}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{forwarding}  & \texttt{bool} & 
            Abilita il kernel all'inoltro dei pacchetti sull'interfaccia. \\
    \texttt{rp\_filter}  & \texttt{bool} & 
            Abilita la protezione \itindex{antispoofing} \textit{antispoofing} 
            sull'interfaccia.\\
    \hline
  \end{tabular}
  \caption{I parametri del kernel di rilevanza per la costruzione di firewall,
    che controllano il comportamento dello stack TCP/IP per le singole
    interfacce.}  
  \label{tab:fw_kernel_ipv4_if_options}
\end{table}

Il primo parametro può essere usato per restringere il reinstradamento dei
pacchetti fra le sole interfacce selezionate attraverso di esso, evitando
l'attivazione generale che si ottiene con il precedente
\texttt{ip\_forward}. 


Il secondo invece permette di attivare una protezione \itindex{antispoofing}
\textit{antispoofing}\footnote{in questo contesto si parla di
  \itindex{spoofing} \textit{spoofing} quando si falsificano gli indirizzi
  sorgenti dei pacchetti, per farli apparire come provenienti da altre
  macchine; in genere questa tecnica viene usata per attacchi di tipo
  \itindex{Denial~of~Service~(DoS)} \textit{Distributed Denial of Service}
  (detti DDoS) in cui si inviano pacchetti di questo tipo, con l'indirizzo
  sorgente della macchina bersaglio, ad un gran numero di macchine su
  internet, in modo che la loro risposta \textsl{allaghi} il bersaglio,
  saturando la banda.}  direttamente a livello di instradamento.  Una
interfaccia per cui si attiva questa protezione non farà passare nessun
pacchetto che arrivi su di essa che presenti un indirizzo sorgente non
corrispondente alla rete su cui l'interfaccia stessa si affaccia.



\subsection{Regole generali e politiche di gestione}
\label{sec:fw_policies}

Prima di entrare nei dettagli relativi all'uso dei vari criteri di selezione e
filtraggio dei pacchetti, è opportuno prendere in esame alcune regole generali
da applicare nella costruzione di un firewall. Si tratta in sostanza di
chiarirsi quale metodo usare per la politica di gestione dei pacchetti, che in
sostanza si traduce nella decisione riguardo alla \textit{policy} di default
da applicare alle catene (quella che si imposta con l'opzione \texttt{-P} di
\texttt{iptables}).

Esistono di fatto due politiche di gestione, che si riflettono anche nei due
possibili valori della \textit{policy} delle catene, quella in cui si lascia
passare tutto (\texttt{ACCEPT} nel linguaggio di \texttt{iptables}) per poi
selezionare quello che si vuole bloccare, e quella in cui si blocca tutto di
default (\texttt{DROP} nel linguaggio di \texttt{iptables}) per poi abilitare
solo il traffico consentito.

La prima politica ha il vantaggio che funziona tutto di default; ma questo è
l'unico vantaggio, infatti richiede una pianificazione attenta delle regole
per individuare tutti i possibili traffici anomali che si vogliono bloccare, e
che proprio per la loro caratteristica di essere anomali non sono affatto
facili da individuare. Il grosso problema di questa politica, che la rende
estremamente debole sul piano della sicurezza, è che tutto quello che non
avete previsto, ma che un attaccante può inventarsi, passa. Pertanto non la
prenderemo ulteriormente in considerazione.

Se invece si usa la politica di bloccare tutto per default, e poi far passare
solo il traffico consentito, avremo l'inconveniente che all'inizio non
funziona nulla, ma il grande vantaggio che dovremo solo individuare il
traffico che ci interessa far passare, dato che tutto il resto sarà comunque
bloccato. Questo ovviamente rende impossibile costruire da zero una simile
politica da remoto, ma permettere l'accesso da remoto ad un firewall, sia pure
per un servizio controllato come SSH, non è comunque una buona idea. Nel caso
comunque abbiate questa necessità dovrete per forza partire consentendo almeno
il traffico necessario alla connessione di controllo.\footnote{il rischio di
  \textsl{chiudersi fuori} in questo caso è molto alto, per cui almeno
  all'inizio, le prove conviene farle da una console, e non da remoto.}

Da questo si potrebbe evincere l'indicazione di cambiare la politica di
default di tutte le catene a \texttt{DROP}, ma in realtà questo non è
necessario e comporta il rischio di chiudersi fuori (se per esempio si esegue
un reset delle regole con \texttt{-F}). Basterà invece mettere come ultima
regola di ciascuna catena un \texttt{-j DROP}, senza nessun criterio di
selezione, così che comunque tutto quello che verrebbe sottoposto alla
politica di default (che può restare ad \texttt{ACCEPT}) viene bloccato.

In questo modo un firewall ben scritto dovrà contenere soltanto (a parte
quella finale) delle regole terminanti con \texttt{ACCEPT}, con la sola
eccezione (che sarebbe comunque meglio riformulare adeguatamente) in cui si
usa \texttt{DROP} per escludere preventivamente una selezione di pacchetti
fatti passare da un successivo \texttt{ACCEPT} troppo ampio.


\subsection{I criteri di filtraggio per IP}
\label{sec:fw_ip_filtering}

In sez.~\ref{sec:fw_iptables_match} abbiamo descritto in dettaglio le varie
opzioni di \texttt{iptables} che permettono di selezionare pacchetti, il
problema adesso è quello di capirne i possibili criteri di applicazione.
Cominceremo iniziando a esaminare come utilizzare i criteri di selezione per i
pacchetti IP, ma per fare questo occorre prima capire il significato dei vari
campi che possono essere filtrati e l'uso che ne viene fatto all'interno del
funzionamento del protocollo.

In fig.~\ref{fig:fw_IP_header} si è riportato lo schema della testata di un
pacchetto IP; i due dati fondamentali sono l'IP destinazione, che indica la
macchina cui il pacchetto è diretto, e l'IP sorgente, che indica la macchina
da cui proviene (e a cui pertanto saranno inviate le risposte).  Il
\textit{netfilter} è in grado di selezionare i pacchetti in base a questi
campi (con le opzioni \texttt{-d} e \texttt{-s} di \texttt{iptables}).

\begin{figure}[htb]
  \centering \includegraphics[width=10cm]{images/ipv4_head}
  \caption{Lo schema della testata di un pacchetto IP, con evidenziati i campi
    controllabili con \texttt{iptables}.}
  \label{fig:fw_IP_header}
\end{figure}

Il filtraggio in base ad indirizzi destinazione e sorgente è la funzionalità
più basilare di un firewall e permette di selezionare i pacchetti in base alle
reti da cui provengono e sono destinati. É con questi criteri di selezione che
si possono abilitare o disabilitare gli accessi a reti o singole macchine. 

Si tenga presente però che per una qualunque connessione i pacchetti con i
quali inviamo dati verso un server avranno come sorgente il nostro IP e
destinazione quello del server, mentre quelli di risposta avranno come
sorgente l'IP del server (è lui infatti che ce li spedisce) e destinazione il
nostro. Pertanto per selezionare tutto il traffico fra due macchine usando
solo i valori dei relativi indirizzi, occorrono due regole, una per il
traffico in entrata e l'altra per quello in uscita. 

Se si vogliono selezionare le connessioni in uscita verso un qualunque
indirizzo di destinazione, senza però accettare quelle in ingresso, non si può
pertanto usare un criterio basato soltanto sugli indirizzi in
gioco,\footnote{il trucco delle due regole vale solo per le connessioni ad una
  singola macchina, e comunque una regola di questo tipo accetta pacchetti di
  qualunque connessione verso di noi provenienti da essa, non solo le risposte
  ad una nostra connessione su di essa.} in quanto per accettare il traffico
di ritorno si dovrebbe garantire l'accesso da qualunque IP, consentendo con
questo anche la possibilità di connessioni in ingresso.  Per questa operazione
è necessario l'uso del filtro sugli stati (con la sola eccezione del
protocollo TCP, che vedremo in sez.~\ref{sec:fw_tcp_filtering}).

Il terzo criterio di base per la selezione dei pacchetti (con l'opzione
\texttt{-p} di \texttt{iptables}), è quello sul campo che contiene il numero
identificativo del protocollo. Questo campo identifica il contenuto del carico
di dati contenuto nel resto del pacchetto, che è sempre un pacchetto di un
altro protocollo trasportato da IP. Vedremo in seguito quali altri possibilità
di filtraggio si attivano qualora questo protocollo sia uno dei tre protocolli
principali (TCP, UDP e ICMP). In generale il \textit{netfilter} permette di
selezionare i pacchetti in base a qualunque valore, e questo può essere usato
ad esempio per redirigere il traffico relativo a certi protocolli (con il
DNAT) a macchine dedicate al loro trattamento.

L'ultimo criterio di base è quello che permette di selezionare i pacchetti
frammentati (con l'opzione \texttt{-f} di \texttt{iptables}). La
frammentazione è una caratteristica del protocollo IPv4, che permette ai
router di spezzare pacchetti troppo grandi per poter essere trasmessi su un
segmento di rete. Se un pacchetto eccede la MTU di un tratto di rete non potrà
essere trasmesso integralmente su quel tratto, pertanto il router lo
suddividerà in varie parti. Questo significa che il campo dati sarà diviso in
varie parti di dimensione opportuna, cui sarà aggiunta una nuova intestazione
che contiene nel campo \textit{offset} l'indicazione di quale parte dei dati
del pacchetto originale è contenuta. 

Questo comporta che tutti i pacchetti generati dallo stesso frammento
(eccettuato il primo) non conterranno l'intestazione del protocollo
successivo, per cui tali pacchetti non passeranno nessun criterio di selezione
basato su valori relativi a questi.  Attivando il sistema del
\textit{conntrack} i pacchetti vengono deframmentati all'ingresso nel
\textit{netfilter}, e quindi il criterio diventa inutile, ma se non lo si usa
si possono selezionare tutti i frammenti successivi al primo (sulla base di un
valore non nullo del capo \textit{offset}).

Come accennato non si usano quasi mai dei criteri di filtraggio basati solo su
IP, l'unica eccezione può essere quella del filtro relativo al
\textit{localhost}, in tal caso infatti, dato che tutto il traffico deve
provenire ed arrivare dallo stesso indirizzo, non c'è il problema di dover
consentire traffico verso il localhost da un indirizzo qualsiasi,\footnote{un
  tale traffico, tra l'altro, sarebbe oltremodo sospetto.} e sono
perfettamente legittime (e necessarie, se si vuole poterlo usare) regole come:
\begin{Example}
iptables -A INPUT -i lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -o lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
\end{Example}

Sebbene i criteri di selezione basati su IP non siano mai usati da soli, sono
però quelli usati più comunemente in tutte le altre regole, sia per limitare
gli accessi da e per sottoreti definite (in genere in combinazione con il
filtro degli stati), che per selezionare i protocolli su cui applicare le
ulteriori regole di selezione.


\subsection{I criteri di filtraggio per ICMP}
\label{sec:fw_icmp_filtering}

Il protocollo ICMP, come indica il nome (\textit{Internet Control Message
  Protocol}) è un protocollo speciale che viene utilizzato per l'invio di
messaggi di controllo, e che è fondamentale per il funzionamento di IP. Con
\texttt{iptables} si possono selezionare i pacchetti ICMP con \texttt{-p
  icmp}.  I pacchetti ICMP vengono trasmessi direttamente su IP, il protocollo
prevede una intestazione molto semplice il cui formato è illustrato in
fig.~\ref{fig:fw_ICMP_header}.

  
\begin{figure}[htb]
  \centering \includegraphics[width=10cm]{images/icmp_head}
  \caption{Lo schema della testata di un pacchetto ICMP, con evidenziati i
    campi controllabili con \texttt{iptables}.}
  \label{fig:fw_ICMP_header}
\end{figure}

Il protocollo classifica i messaggi in base ai valori dei due campi
\textsl{tipo} e \textsl{codice}.  Ciascun tipo di messaggio ha un suo preciso
significato e viene impiegato per un certo compito ben definito. Un elenco dei
vari tipi di pacchetti, insieme all'identificativo da passare come argomento
all'opzione \texttt{-{}-icmp-type} e ad una breve descrizione del significato,
si trova in tab.~\ref{tab:fw_icmp_type}.

In alcuni casi (la cosa vale soltanto per i pacchetti di tipo
\textit{destination unreachable}, \textit{redirect}, \textit{time-exceeded} e
\textit{parameter problem}) per lo stesso tipo di pacchetto possono esistere
diverse condizioni di errore o diversi significati che il messaggio deve poter
portare, questi allora vengono ulteriormente specificati attraverso un diverso
valore del campo \textsl{codice}.

La selezione \texttt{iptables} consente di scegliere anche questi specifici
pacchetti (i valori di tab.~\ref{tab:fw_icmp_type} selezionano solo sulla base
del tipo, e il valore del codice viene ignorato), attraverso i valori
riportati in tab.~\ref{tab:fw_icmp_code}, nella quale si è riportato anche
(dividendo la tabella in sezioni diverse per ciascuno dei quattro tipi di
pacchetto precedentemente citati), il valore numerico del campo codice.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|p{8cm}|}
    \hline
    \textbf{Valore}&\textbf{Tipo}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{any} & -- & Seleziona tutti i possibili valori \\
    \hline
    \texttt{echo-reply}             &0& Inviato in risposta ad un ICMP
                                        \textit{echo-request} \\ 
    \texttt{destination-unreachable}&3& Segnala una destinazione 
                                        irraggiungibile, viene
                                        inviato all'IP sorgente di un
                                        pacchetto quando un router realizza
                                        che questo non può essere inviato a
                                        destinazione. \\
    \texttt{source-quench}          &4& Inviato in caso di congestione della
                                        rete per indicare all'IP sorgente di
                                        diminuire il traffico inviato.\\
    \texttt{redirect}               &5& Inviato per segnalare un errore di
                                        routing, richiede che la macchina
                                        sorgente rediriga il traffico ad un
                                        altro router da esso specificato. \\
    \texttt{echo-request}           &8& Richiede l'invio in risposta di un
                                        \texttt{echo-reply}. \\
%    \texttt{router-advertisement}   & & \\
%    \texttt{router-solicitation}    & & \\
    \texttt{time-exceeded}          &11& Inviato quando il TTL di un pacchetto
                                         viene azzerato.\\
    \texttt{parameter-problem}      &12& Inviato da un router che rileva dei
                                         problemi con l'intestazione di un
                                         pacchetto. \\
    \texttt{timestamp-request}      &13& Richiede l'invio in risposta di un
                                         \texttt{timestamp-reply}.\\
    \texttt{timestamp-reply}        &14& inviato in risposta di un
                                         \texttt{timestamp-request}. \\
    \texttt{info-request}           &15& Richiede l'invio in risposta di un
                                         \texttt{info-reply}.\\
    \texttt{info-reply}             &16& Inviato in risposta di un
                                         \texttt{info-request}.\\
    \texttt{address-mask-request}   &17& Richiede l'invio in risposta di un
                                         \texttt{address-mask-reply}. \\
    \texttt{address-mask-reply}     &18& Inviato in risposta di un
                                         \texttt{address-mask-request}. \\
    \hline
  \end{tabular}
  \caption{Tipi di pacchetti ICMP selezionabili con \texttt{-{}-icmp-type}.}
\label{tab:fw_icmp_type}
\end{table}

In sez.~\ref{sec:fw_conntrack} abbiamo visto come alcuni pacchetti ICMP,
\textit{echo request}, \textit{netmask request}, \textit{timestamp request} e
\textit{information request} (ed i corrispondenti pacchetti di risposta)
vengano classificati dal sistema del \textit{conntrack}.  Di questi le ultime
tre coppie riguardano delle funzionalità poco usate, e possono essere
tranquillamente ignorati e venire bloccati da un firewall.  Tra l'altro la
risposta ad un \textit{timestamp request} permette di conoscere il valore
dell'orologio di sistema di una macchina, e questo può essere utile in certi
attacchi.


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|}
    \hline
    \textbf{Valore}&\textbf{Codice}\\
    \hline
    \hline
    \texttt{network-unreachable}      &0\\
    \texttt{host-unreachable}         &1\\
    \texttt{protocol-unreachable}     &2\\
    \texttt{port-unreachable}         &3 \\
    \texttt{fragmentation-needed}     &4\\
    \texttt{source-route-failed}      &5\\
    \texttt{network-unknown}          &6\\
    \texttt{host-unknown}             &7\\
    \texttt{host-isolated}            &8\\
    \texttt{network-prohibited}       &9\\
    \texttt{host-prohibited}          &10 \\
    \texttt{TOS-network-unreachable}  &11 \\
    \texttt{TOS-host-unreachable}     &12 \\
    \texttt{communication-prohibited} &13 \\
    \texttt{host-precedence-violation}&14 \\
    \texttt{precedence-cutoff}        &15 \\
    \hline
    \texttt{network-redirect}         &0  \\
    \texttt{host-redirect}            &1  \\
    \texttt{TOS-network-redirect}     &2  \\
    \texttt{TOS-host-redirect}        &3  \\
    \hline
    \texttt{ttl-zero-during-transit}  &0 \\
    \texttt{ttl-zero-during-reassembly}&1 \\
    \hline
    \texttt{ip-header-bad}            &0 \\
    \texttt{required-option-missing}  &1 \\
    \hline
  \end{tabular}
  \caption{Specifici pacchetti ICMP classificati in base ai valori del campo
    \textsl{codice}, suddivisi per tipo: \textit{destination unreachable},
    \textit{redirect}, \textit{time-exceeded} e \textit{parameter problem}.}
\label{tab:fw_icmp_code}
\end{table}

I pacchetti \textit{echo request} e \textit{echo reply} costituiscono invece
la base del comando \texttt{ping} e sono molto utilizzati per scopi
diagnostici, per questo non è il caso di scartarli a priori.  Il problema è
che molti attacchi di tipo \itindex{Denial~of~Service~(DoS)}
\textit{Distributed Denial of Service} si basano appunto sull'uso di questi
pacchetti. In genere il trucco è quello di inviare (da macchine compromesse)
una serie di \textit{echo request} falsificando l'indirizzo sorgente in quello
della macchina da attaccare. Questo comporta che essa riceverà tutte le
risposte. Se si aggiunge che in molti casi i router lasciano passare degli
\textit{echo request} in \textit{broadcast}, questo consente un grosso effetto
moltiplicativo (un solo pacchetto scatena la risposta di tutta una rete) che
conduce in genere ad una \textsl{alluvione} di \textit{echo reply} (questo
tipo di attacchi infatti viene spesso chiamato \itindex{flood} \textit{flood})
sulla macchina vittima dell'attacco.

Per questo motivo alcuni amministratori poco competenti tendono a filtrare
completamente tutto ICMP, invece di provvedere a risolvere il problema
seriamente. In tal caso infatti quello che va fatto è bloccare le risposte a
richieste in \textit{broadcast} (questo può essere fatto con Linux con i
parametri \texttt{icmp-ignore-broadcast} del kernel illustrati in
sez.~\ref{sec:fw_kernel_sysctl}), e inserire (con l'estensione \texttt{limit})
un controllo sul flusso massimo di questo tipo di pacchetti.

Inoltre per evitare di essere usati come \textsl{complici} di un tale attacco
occorre abilitare sui \textsl{router di frontiera}\footnote{si chiamano così
  (\textit{border router}) i router che stanno ai bordi di Internet, che hanno
  cioè dietro di loro dei tratti di rete chiusi, dai quali non si rientra in
  Internet; in sostanza quelli che non stanno sulle dorsali.} la protezione
\textit{antispoofing} (sempre descritta in sez.~\ref{sec:fw_kernel_sysctl},
con il parametro \texttt{rp\_filter}) che blocca i pacchetti uscenti da una
interfaccia il cui indirizzo sorgente non corrisponda alla rete che sta su
quell'interfaccia.

Una volta fatto questo occorre poi compiere una scelta relativa ai pacchetti
ICMP che si vogliono far passare, tenendo presente che alcuni di essi sono
importanti per il buon funzionamento della rete, e che bloccarli tutti
danneggia anzitutto noi stessi.

Un pacchetto pericoloso, e da filtrare senz'altro, è il \texttt{redirect}, in
quanto esso comporta la possibilità di riscrivere da remoto la tabella di
routing di una macchina modificando la rotta per la destinazione dei
pacchetti, con possibilità enormi di attacchi di tipo
\itindex{Denial~of~Service~(DoS)} DoS. Il pacchetto infatti veniva utilizzato
quando un router identificava una rotta migliore per un pacchetto arrivato a
lui, con esso si indicava alla macchina sorgente di redirigere il traffico
direttamente sulla nuova rotta; il problema è che un pacchetto appositamente
forgiato potrebbe ad esempio farvi redirigere il traffico sul localhost, con
effetti tutt'altro che gradevoli per la vostra rete.

Lo stesso problema, anche se in maniera molto minore, può derivare
dall'accettare i pacchetti \texttt{source-quench} che vengono usati dai router
per comunicare uno stato di congestione della linea, richiedendo appunto uno
\textsl{smorzamento} del traffico.  In genere la loro ricezione fa eseguire al
kernel un rallentamento del traffico in uscita verso quella destinazione, in
modo da diminuire la congestione. Di nuovo un uso \textsl{malizioso} potrebbe
portarvi a ridurre il traffico anche quando non ce n'è bisogno, ma il problema
è senz'altro minore rispetto al \texttt{redirect}.

I pacchetti \texttt{time-exceeded} e \texttt{destination-unreachable} sono
invece pacchetti utili alla rilevazione di problemi sulla rete, e sono di
norma da accettare, è in particolare molto importante accettare il pacchetto
\texttt{fragmentation-needed} in quanto viene usato per la determinazione
della MTU (la dimensione massima) dei pacchetti da inviare su una connessione,
la cosiddetta \itindex{Path~MTU} \textit{Path MTU}.

Come accennato in sez.~\ref{sec:fw_ip_filtering} quando un router individua un
pacchetto la cui dimensione eccede la capacità del tratto di rete su cui deve
inviarlo, lo frammenta. Questa operazione rallenta sia le operazioni del
router, e aumenta (per la necessità di header aggiuntivi) il consumo di banda,
nuocendo alla velocità di trasmissione; dato inoltre che la \textit{Path MTU}
può variare, è stato previsto il meccanismo del \textit{Path MTU Discovery}
(descritto nell'\href{http://www.ietf.org/rfc/rfc1191.txt}{RFC~1191}) che
permette di riconoscere quale è il valore massimo delle dimensioni di un
pacchetto da inviare su una collegamento, senza che questo debba essere
frammentato. Il meccanismo sfrutta il flag \textit{Don't Fragment} del
protocollo IP (vedi fig.~\ref{fig:fw_IP_header}) che richiede al router di non
eseguire la frammentazione di pacchetti di dimensione eccessiva, ma di
generare in ritorno un pacchetto ICMP di tipo \texttt{destination-unreachable}
e codice \texttt{fragmentation-needed}, ricevendo il quale si può riconoscere
quando un pacchetto ha una dimensione eccessiva e determinare quella corretta.

Un elenco tipico di regole riguardanti ICMP è pertanto il seguente:
\begin{Example}
iptables -A INPUT -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT
\end{Example}



\subsection{I criteri di filtraggio per TCP}
\label{sec:fw_tcp_filtering}

Il protocollo TCP è il più utilizzato dei protocolli trasportati su IP, ed è
l'unico dei protocolli della suite TCP/IP che supporta nativamente connessioni
e stati. Realizzare tutto questo però ha un suo costo, e come si può vedere
dalla quanto mostrato in fig.~\ref{fig:fw_TCP_header}, la testata dei
pacchetti TCP è una delle più complesse.

\begin{figure}[htb]
  \centering \includegraphics[width=10cm]{images/tcp_head}
  \caption{Lo schema della testata di un pacchetto TCP, con evidenziati i
    campi controllabili con \texttt{iptables}.}
  \label{fig:fw_TCP_header}
\end{figure}

La caratteristica principale di TCP, comune con UDP come protocollo di
trasporto, è la presenza di due campi di 16 bit usati per mantenere il numero
di porta (sorgente e destinazione), che vengono utilizzati per distinguere,
fra tutti i pacchetti che transitano fra due macchine, quelli appartenenti ad
una specifica connessione. Come abbiamo visto queste possono essere
selezionate attraverso l'uso delle opzioni \texttt{-{}-sport} e
\texttt{-{}-dport}.

Usare solo i valori delle porte per identificare una connessione non è però
pratico. Come abbiamo visto in sez.~\ref{sec:fw_conntrack} infatti le due
direzioni del flusso di dati all'interno di una connessione hanno destinazione
e sorgente invertita. Allora anche se è possibile selezionare tutti i
pacchetti di una connessione qualora siano note le porte (destinazione e
sorgente) usate, il problema sorge dal fatto che queste non sono determinabili
a priori. Infatti in una connessione solo una porta è sempre ben stabilita
(quella relativa al servizio cui ci si vuole collegare), l'altra, che viene
detta per questo \textsl{effimera}, viene scelta dal kernel della macchina di
chi inizia la connessione con un valore dinamico, preso fra quelli
disponibili, e può essere qualunque. Pertanto, se si vuole ricevere in maniera
generica il traffico di ritorno di una connessione, si dovrà consentire
l'accesso a tutto un insieme di porte, e benché questo sia possibile, è poco
pratico (e fa passare qualunque pacchetto proveniente dalla stessa origine,
anche se non collegato a nessuna connessione).

Per questo l'uso classico della selezione sulle porte TCP è quello sulla porta
destinazione combinato con il filtro degli stati; questo permetterà di
selezionare per quali porte di destinazione si accettano pacchetti in stato
\texttt{NEW}, consentendo di effettuare connessioni verso di esse, sia in
ingresso (quali server locali possono essere contattati dall'esterno) che in
uscita (a quali servizi esterni si consente l'accesso).

In generale perciò i criteri di filtraggio basati su TCP si riducono
sostanzialmente alla scelta dei servizi cui di vuole dare accesso. È usuale
consentire l'accesso via SSH alle macchine sulla DMZ, purtroppo spesso questo
viene fatto anche per il firewall nonostante il rischio che tutto ciò
comporta. In genere, oltre a SSH, i servizi più comuni sono il web, e la posta
elettronica, che vanno posti nella DMZ.  Un elenco tipico di regole che
consentono l'accesso a questi servizi su un server è il seguente:
\begin{Example}
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 25 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
\end{Example}

In genere è da evitare di fornire accesso ad eventuali database (anche se
posti nella DMZ) dall'esterno, limitando questo solo alle macchine nella
stessa rete. Inoltre è assolutamente da escludere l'accesso a servizi tipici
di un rete interna, come i file server (Samba) o i servizi per le
autenticazioni centralizzate (LDAP o NIS). Qualora alcuni dati di questi
servizi dovessero risultare utili per le macchine presenti in DMZ si dovrà
piuttosto predisporre un meccanismo di replicazione delle informazioni, (e
solo di quelle indispensabili), a partire dalla rete interna e verso l'esterna
(e mai il viceversa).

Per quanto riguarda l'accesso verso l'esterno tutto dipende da eventuali
politiche di restrizione degli accessi che si intendono implementare, ad
esempio si può consentire soltanto l'accesso a web e posta bloccando tutto il
resto. In genere poi, per alcuni servizi, si può provvedere alla impostazione
di un \textsl{proxy trasparente}, utilizzando le capacità di redirezione del
\textit{netfilter}.



\subsection{I criteri di filtraggio per UDP}
\label{sec:fw_udp_filtering}

Il secondo protocollo più utilizzato su internet dopo il TCP è UDP, questo
protocollo non è altro che un semplice involucro (un \textit{wrapper}) per
utilizzare le caratteristiche di IP a livello di trasporto. Pertanto
l'intestazione del protocollo, illustrata in fig.~\ref{fig:fw_UDP_header}, è
estremamente semplice, e si limita ad aggiungere ad IP i campi relativi alle
porte (per poter supportare diversi canali di comunicazione) e due campi
ausiliari di controllo (la lunghezza del pacchetto e la somma di controllo).

\begin{figure}[htb]
  \centering \includegraphics[width=10cm]{images/udp_head}
  \caption{Lo schema della testata di un pacchetto UDP, con evidenziati i
    campi controllabili con \texttt{iptables}.}
  \label{fig:fw_UDP_header}
\end{figure}

Benché nel caso di UDP non esistano connessioni (il protocollo si limita a
garantire solo il massimo sforzo nella consegna dei dati) si possono comunque,
come fa il filtro degli stati, identificare dei canali di comunicazione;
questi hanno (in termini di porte coinvolte e flussi dei relativi pacchetti)
la stessa caratteristiche di una connessione TCP, e pertanto valgono anche in
questo caso le considerazioni precedenti relative al filtraggio in base al
valore della porta di destinazione.

Come per il TCP si tratta di selezionare quali sono i servizi a cui si vuole
consentire l'accesso dall'esterno, il principale servizio che opera su UDP è
il DNS, che di nuovo deve essere posto in DMZ; un altro servizio importante
che utilizza UDP è NFS, ma come per Samba (e qualunque altro meccanismo di
condivisione dei file della rete interna) esso non deve mai reso visibile
all'esterno. Un esempio di regole utilizzate per UDP è il seguente:
\begin{Example}
iptables -A INPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
iptables -A INPUT -p udp --dport 500 -m state --state NEW -j ACCEPT
\end{Example}
che forniscono accesso remoto al DNS ed al servizio IKE per IPSEC (che vedremo
in sez.~\ref{sec:VPN_IPSEC}).


\subsection{Un esempio di firewall}
\label{sec:fw_firewall_example}

Vedremo adesso una serie di regole che possono essere utilizzate per costruire
un firewall elementare; si è fatto la scelta di non creare e commentare uno
script già pronto, perché lo scopo è quello di mettere in grado le persone di
scrivere il proprio. Per questo useremo volutamente esempi particolari (senza
definire variabili al posto delle varie interfacce e indirizzi) e regole
spesso incomplete, in modo che ciascuno, una volta compresi i concetti che le
sottendono, debba a sua volta creare un suo script.

Negli esempi usati per illustrare i criteri di filtraggio sui vari protocolli
si è sempre fatto riferimento ad una singola macchina presa come origine o
destinazione finale dei pacchetti, operando quindi sulle catene di
\texttt{INPUT} e \texttt{OUTPUT}; nel caso si debba installare un firewall
però si tratterà di operare principalmente sulla catena di \texttt{FORWARD},
dovendo filtrare i pacchetti in transito fra diverse interfacce di rete.

\begin{figure}[!htb]
  \centering
  \includegraphics[width=10cm]{images/dmzfw}
  \caption{Schema delle interfacce per un firewall di esempio nella
    configurazione di base con DMZ, con illustrazione dei flussi di dati.}
  \label{fig:fw_iface_scheme}
\end{figure}

Il caso più comune, utilizzando una topologia come quella di
fig.~\ref{fig:DMZ_net}, è quello di consentire l'accesso ad internet dalla
rete interna senza restrizioni, di impedire l'accesso da internet alla rete
interna e di consentire l'accesso dall'esterno alla DMZ solo per i servizi
pubblici che si sono posti su di essa.

Come esempio particolare consideriamo la disposizione delle interfacce e delle
sottoreti illustrata in fig.~\ref{fig:fw_iface_scheme}, in cui si sono anche
riportati i flussi dei pacchetti da consentire secondo quanto detto in
sez.~\ref{sec:fw_deploy}. In figura si è indicato un flusso di dati che
permette la connessione con una freccia piena ed il flusso dei pacchetti di
ritorno con la freccia vuota; inoltre si è usata una linea continua per
indicare un flusso generico non filtrato e una discontinua per quello
consentito solo per alcuni servizi.

Il primo passo è allora quello di definire quali pacchetti vogliamo comunque
far passare. Useremo il filtro degli stati, per cui in generale questi saranno
tutti quelli in stato \texttt{ESTABLISHED} o \texttt{RELATED}, in quanto
risposte a connessioni consentite, più i pacchetti ICMP di controllo di cui
abbiamo parlato in sez.~\ref{sec:fw_icmp_filtering}; metteremo il tutto su una
catena \texttt{allowed} utilizzando una definizione del tipo:
\begin{FileExample}[label=firewall.sh]
iptables -N allowed

iptables -A allowed -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A allowed -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A allowed -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A allowed -p icmp --icmp-type echo-request -j ACCEPT
#iptables -A allowed -p icmp --icmp-type fragmentation-needed -j ACCEPT
\end{FileExample}
dove prima si crea la catena, e poi vi si inseriscono le regole per i
pacchetti appena citati. 

Attenendoci rigidamente al criterio per cui non deve essere possibile arrivare
da internet alla rete interna, bloccheremo anche ogni accesso diretto al
firewall dall'esterno. La soluzione più sicura è quella di bloccare qualunque
connessione remota diretta al firewall, per comodità si può sacrificare un po'
di sicurezza concedendo un accesso limitato solo dalla rete interna.  Questo
significa che per quanto riguarda le due catene di \texttt{INPUT} e
\texttt{OUTPUT} (che si ricordi riguardano solo i pacchetti diretti o
provenienti dal firewall) basteranno una serie di regole del tipo:
\begin{FileExample}[label=firewall.sh]
#
# INPUT
#
iptables -A INPUT -i lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
iptables -A INPUT -j allowed
# iptables -A INPUT -i eth0 -s 192.168.1.0/24 --state NEW -j ACCEPT
iptables -A INPUT -j DROP
#
# OUTPUT
#
iptables -A OUTPUT -o lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -m state --state NEW -j ACCEPT
iptables -A OUTPUT -j allowed
iptables -A OUTPUT -j DROP
\end{FileExample}

Nell'esempio si abilita sia in ingresso che in uscita tutto il traffico sul
\texttt{localhost}, e si accettano i pacchetti delle connessioni già stabilite
e quelli ICMP di controllo secondo quanto già specificato nella catena
\texttt{allowed}; poi si permettono le nuove connessioni in uscita dal server.
Volendo abilitare delle connessioni in ingresso si può ad esempio scommentare
la riga in cui si abilitano le connessioni dirette al firewall solo se
provenienti dalla corretta interfaccia e dalla relativa sottorete (sarebbe
opportuno comunque essere più restrittivi e limitarle sulla base di singoli
indirizzi, ad esempio quello della macchina dell'amministratore).

Una volta definito cosa fare dei pacchetti destinati direttamente alla
macchina che fa da firewall la configurazione di quest'ultimo riguarda
sostanzialmente i pacchetti in transito, e cioè la catena di \texttt{FORWARD}.
Per consentire i flussi illustrati in fig.~\ref{fig:fw_iface_scheme} si
dovranno definire delle regole del tipo:
\begin{FileExample}[label=firewall.sh]
iptables -A FORWARD -j allowed
iptables -A FORWARD -i eth0 -o ppp0 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth1 -o ppp0 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i ppp0 -o eth1 -m state --state NEW -j services
iptables -A FORWARD -j DROP
\end{FileExample}

In questo caso prima si fanno passare i soliti pacchetti sempre consentiti
tramite la catena \texttt{allowed}, poi si abilita l'accesso a partire dalla
LAN sia per la DMZ che per internet; volendo essere pignoli, il che quando si
tratta di sicurezza è sempre un pregio, occorrerebbe specificare anche le reti
di origine e quelle di destinazione, lo lasciamo per esercizio.  Si dà poi
accesso ad internet dalla DMZ, ed infine per le connessioni provenienti da
internet e dirette sulla DMZ si userà una catena \texttt{services}
opportunamente creata.

Il grosso del lavoro di filtraggio è da fare su \texttt{services}, qui si
dovranno definire a quali servizi e su quali server si potrà accedere da
internet; di nuovo prendiamo un esempio in cui nella DMZ ci sono sulla solo
due macchine, la \texttt{192.168.2.2} che fa da server di posta e DNS, e la
\texttt{192.168.2.3} che fa da server web, in questo caso potremo usare delle
regole del tipo:
\begin{FileExample}[label=firewall.sh]
iptables -N services
iptables -A services -d 192.168.2.2 -p tcp --dport 25  -j ACCEPT
iptables -A services -d 192.168.2.2 -p udp --dport 53  -j ACCEPT
iptables -A services -d 192.168.2.3 -p tcp --dport 80  -j ACCEPT
\end{FileExample}

Fin qui si sono trattate solo le regole destinate alla gestione del firewall,
ma avendo usato nell'esempio un caso di reti private sia per la DMZ che per la
LAN queste non sono in realtà sufficienti. L'ipotesi dell'esempio di
fig.~\ref{fig:fw_iface_scheme} è allora quella che il firewall faccia anche da
router per una connessione con un IP pubblico solo per
\texttt{ppp0}.\footnote{è il caso tipico di una connessione via modem, sia su
  linea telefonica analogica, che via ADSL.} In questo caso è necessario usare
le funzionalità della tabella di \texttt{nat} per compiere le opportune
trasformazioni degli indirizzi.

Il primo passo è quello di eseguire un \textit{Source NAT} per i pacchetti
uscenti su internet in modo che questi assumano l'indirizzo pubblico del
nostro \textit{router/firewall}; questo si ottiene andando ad operare sulla
catena di \texttt{POSTROUTING} della tabella di \texttt{nat} con una regola
del tipo:
\begin{FileExample}[label=firewall.sh]
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
\end{FileExample}
che esegue il \textit{Source NAT} su tutti i pacchetti uscenti su
\texttt{ppp0}.

Si tenga presente che \texttt{MASQUERADE} è una azione speciale, che esegue il
\textit{Source NAT} andando a vedere quale è l'IP assegnato sulla relativa
interfaccia; per questo in genere la si usa solo per le interfacce su cui l'IP
è assegnato dinamicamente, dato che è in grado di riconoscere al volo un
eventuale cambiamento dello stesso (ed è quindi tipica delle connessioni
\textit{dial-in}).  Questo processo comporta un piccolo \textit{overhead} per
la determinazione dell'indirizzo, per cui se l'IP è statico è più opportuno
usare direttamente il \textit{Source NAT} su quest'ultimo, con qualcosa del
tipo:
\begin{FileExample}[label=firewall.sh]
iptables -t nat -A POSTROUTING -o ppp0 -j SNAT --to-source 62.94.208.119
\end{FileExample}

Il passo successivo è quello di redirigere le connessioni provenienti da
internet per i servizi cui si vuole dare accesso sui rispettivi server nella
DMZ; questo significa dover eseguire un \textit{Destination NAT} relativo a
detti servizi, cosa che si otterrà operando sulla catena di
\texttt{PREROUTING} della tabella di \texttt{nat} con un qualcosa del tipo:
\begin{FileExample}[label=firewall.sh]
iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 80 -j DNAT \
                --to-destination 192.168.2.3
iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 25 -j DNAT \
                --to-destination 192.168.2.2
iptables -t nat -A PREROUTING -i ppp0 -p udp --dport 53 -j DNAT \
                --to-destination 192.168.2.2
\end{FileExample}

Si noti come in questo caso si sia utilizzata la selezione sull'interfaccia di
provenienza per identificare le connessioni entranti da internet, e
selezionati i pacchetti solo sulla base della porta di destinazione. Questo
perché nell'esempio in questione c'è un unico indirizzo pubblico possibile,
quello associato con \texttt{ppp0}. Nel caso invece si abbiano più indirizzi
esterni, con una configurazione in cui la macchina fa solo da firewall (come
in fig.~\ref{fig:DMZ_net} e non anche da router per la connessione, come in
fig.~\ref{fig:fw_iface_scheme}) e si vogliano usare per i server nella DMZ
degli IP diversi,\footnote{una tecnica usata comunemente è quella di assegnare
  comunque tutti gli IP pubblici (con l'\textit{IP aliasing}) all'interfaccia
  esterna del firewall, e poi eseguire comunque un DNAT su altrettanti diversi
  IP privati, messi all'interno della DMZ.} bisognerà selezionare i pacchetti
in arrivo anche in base agli indirizzi pubblici cui sono rivolti e non solo in
base all'interfaccia.

Infine si noti come in tutti gli esempi precedenti le regole di firewall sono
state espresse usando direttamente indirizzi presenti sulle reti locali, anche
per i servizi pubblici messi nella DMZ; questo è corretto perché la
traslazione degli indirizzi avviene sulle due catene di \texttt{PREROUTING} e
\texttt{POSTROUTING}, cioè rispettivamente prima dell'entrata e dopo l'uscita
dal firewall e pertanto a livello della tabella di \texttt{filter} si può
senza problemi fare riferimento agli indirizzi come li si vedono all'interno
della propria rete locale.




\chapter{Virtual Private Network}
\label{cha:VPN}


\section{Cenni di teoria delle VPN}
\label{sec:VPN_theory}

Prima di parlare della implementazione pratica e delle modalità di
installazione, uso e configurazione delle VPN, faremo una introduzione su cosa
sono le VPN, quali caratteristiche hanno, cosa le contraddistingue, e sulle
basi teoriche (algoritmi e protocolli) sulle quali queste vengono costruite.


\subsection{Cos'è una VPN}
\label{sec:VPN_whatis}

Con la sigla VPN (\textit{Virtual Private Network}) si intende in realtà una
classe di tecnologie che permettono di mettere in comunicazione appunto delle
\textsl{reti private} attraverso internet. Con reti private si intendono in
genere reti non accessibili direttamente da internet, che di norma utilizzano
gli indirizzi non instradabili
dell'\href{http://www.ietf.org/rfc/rfc1918.txt}{RFC~1918},\footnote{cioè gli
  indirizzi della rete di classe A \texttt{10.0.0.0/8}, delle 16 reti di
  classe B da \texttt{172.16.0.0/16} a \texttt{172.31.0.0/16} e delle 256 reti
  di classe C da \texttt{192.168.0.0/24} a \texttt{192.168.255.0/24}.} e
condividono la connessione ad internet attraverso un router che effettua il
mascheramento di detti indirizzi.\footnote{abbiamo visto in
  sez.~\ref{sec:fw_iptables_target} come eseguire questa operazione con il
  \textit{netfilter}, attraverso il target \texttt{SNAT} nella tabella di
  \texttt{nat}.}

Dato che questi indirizzi non vengono instradati dai router è ovviamente
impossibile collegare direttamente attraverso Internet due reti di questo
tipo, anche se non usano gli stessi indirizzi. Se però si trovasse il modo di
far arrivare in una qualche maniera i pacchetti che le due reti vogliono
scambiarsi ai due relativi router, questi non avrebbero alcun problema a
consegnarli ai relativi destinatari.

Una VPN è questo canale di comunicazione alternativa che permette di
trasmettere i pacchetti fra due router secondo lo schema di
fig.~\ref{fig:VPN_scheme}, canale che di norma, come misura di ulteriore
sicurezza, viene opportunamente cifrato in modo che nel transito da internet
il traffico trasmesso non possa essere osservato; una caratteristica che
rafforza l'uso del nome di \textit{private}.

\begin{figure}[htb]
  \centering \includegraphics[width=10cm]{images/vpnnet}
  \caption{Lo schema generico di una VPN che collega due reti private.}
  \label{fig:VPN_scheme}
\end{figure}

In generale non è necessario, per avere una VPN, che i due tratti di rete agli
estremi della stessa usino indirizzi privati; e di per sé per collegare due
reti private non è necessario che il canale di comunicazione sia cifrato, ma
questa è una delle caratteristiche più tipiche di una VPN, senza la quale si
avrebbe un semplice \textit{tunnel}. Per questo normalmente il cuore di una
VPN è un algoritmo crittografico che costituisce la base su cui è possibile
costruire un canale di comunicazione sicuro attraverso cui passeranno i nostri
dati.

Inoltre quello di fig.~\ref{fig:VPN_scheme} è solo lo schema più comune di
utilizzo di una VPN, in realtà si possono usare le VPN anche dare accesso ad
una singola macchina (nella configurazione detta \textit{road warrior})
all'interno di una rete altrimenti invisibile dall'esterno, o per mettere in
contatto due macchine singole (configurazione limite della precedente, in cui
la rete si riduce ad una sola macchina). 

Infine è sempre possibile, usando più canali, mettere in comunicazione fra
loro un numero arbitrario di reti, purché ovviamente queste mantengano
indirizzi non in conflitto fra di loro. In questo caso avremo ovviamente una
struttura più complessa, anche se alla base resta un incrocio di tante
configurazioni del tipo di quella mostrata in fig.~\ref{fig:VPN_scheme}. 


\subsection{Il protocollo IPSEC}
\label{sec:VPN_IPSEC}

Benché spesso si preferisca utilizzare altre soluzioni (ed in particolare
tunnel basati sui protocolli di trasporto, normalmente UDP) dal punto di vista
della standardizzazione la soluzione più appropriata per realizzare delle VPN
è quella di usare IPSEC, cioè una reimplementazione del protocollo IP,
supportata nativamente in IPv6, ed incapsulata in IPv4, che fornisce
autenticazione e crittografia direttamente al livello di rete (appunto quello
di IP).

L'uso di IPSEC al posto di IP permette infatti, fra le altre cose, di cifrare
completamente tutto il traffico fra due macchine su internet, risolvendo così
in maniera naturale il problema di comunicare in maniera privata. Dato poi che
il protocollo supporta una comunicazione in modalità tunnel fra due router che
cifra pure gli indirizzi iniziale e finale dei pacchetti, è altrettanto
naturale ottenere una VPN. Il protocollo IPSEC è basato su tre componenti:
\begin{basedescript}{\desclabelwidth{1.cm}\desclabelstyle{\nextlinelabel}}
\item[AH] definito nell'\href{http://www.ietf.org/rfc/rfc2405.txt}{RFC~2405},
  è l'acronimo di \itindex{Authentication~Header~(AH)} \textit{Authentication
    Header}, e fornisce un servizio di autenticazione dei pacchetti.
\item[ESP] definito nell'\href{http://www.ietf.org/rfc/rfc2406.txt}{RFC~2406},
  è l'acronimo di \itindex{Encapsulating~Security~Payload~(ESP)}
  \textit{Encapsulating Security Payload}, e fornisce un servizio di
  autenticazione e cifratura dei dati.
\item[IKE] definito nell'\href{http://www.ietf.org/rfc/rfc2409.txt}{RFC~2409}
  per la versione originaria (IKEv1) ed aggiornato con una seconda versione
  (IKEv2), definita nell'\href{http://www.ietf.org/rfc/rfc5996.txt}{RFC~5996}.
  è l'acronimo di \itindex{Internet~Key~Exchange~(IKE)} \textit{Internet Key
    Exchange}, e fornisce un servizio per la negoziazione dei parametri
  necessari al funzionamento dei precedenti.
\end{basedescript}

Di queste tre componenti quella di gran lunga più complessa è IKE, che nasce
dalla combinazione di una serie di altri protocolli. In sostanza IKE combina
il protocollo
\itindex{Internet~Security~Association~Key~Management~Protocol~(ISAKMP)}
ISAKMP (\textit{Internet Security Association and Key Management Protocol}
definito dall'\href{http://www.ietf.org/rfc/rfc2408.txt}{RFC~2408}) che
gestisce la negoziazione delle connessioni e definisce le cosiddette
\textit{Security Association}. A questo si aggiunge il DOI (\textit{Domain Of
  Interpretation}, definito
dall'\href{http://www.ietf.org/rfc/rfc2407.txt}{RFC~2407}) per IPSEC che
completa ISAKMP nel caso specifico di IPSEC, e il protocollo \textit{Oakley}
di scelta delle chiavi (definito
nell'\href{http://www.ietf.org/rfc/rfc2412.txt}{RFC~2412}), che è quello che
permette l'impostazione iniziale dei parametri necessari alla
comunicazione. Il protocollo è stato in seguito rivisto con la creazione di
una seconda versione, la cui specificazione finale (che riprende la
definizione originale
dell'\href{http://www.ietf.org/rfc/rfc4306.txt}{RFC~4306} ed alcuni
chiarimenti successivi
dell'\href{http://www.ietf.org/rfc/rfc4718.txt}{RFC~7418}) è fornita
nell'\href{http://www.ietf.org/rfc/rfc5996.txt}{RFC~5996}.

È a questo livello che vengono negoziate le chiavi e gli algoritmi
crittografici utilizzati, i tempi di vita delle connessioni, implementando in
pratica quel meccanismo di crittografia ibrido descritto alla fine di
sez.~\ref{sec:crypto_asymmetric}. 

Nel funzionamento di IPSEC giocano un ruolo cruciale le
\itindex{Security~Association~(SA)} \textit{Security Association} (in breve
SA), queste identificano un canale di comunicazione definendone destinazione,
protocollo utilizzato (AH o ESP) ed un
\itindex{Security~Parameter~Index~(SPI)} \textit{Security Parameter Index}
(SPI) che distingue tutti i possibili diversi canali che hanno la stessa
destinazione e usano lo stesso protocollo. Per quanto abbiamo appena detto è
evidente che una SA è unidirezionale (è infatti sempre definita a partire
dalla macchina corrente verso una certa destinazione) per cui ne occorrono
sempre due (una per direzione) per ogni canale di comunicazione.

Il primo passo per poter utilizzare IPSEC è quello di eseguire IKE per la
negoziazione dei parametri della connessione, questo in genere avviene in due
fasi; nella prima fase viene negoziata una coppia di SA di ISAKMP per la
comunicazione fra due \textit{gateway}, in modo da poter gestire più canali
indipendenti; con queste nella seconda fase vengono generate le ulteriori SA
per IPSEC (ad uso di ESP o AH) per le singole comunicazioni. Il tutto avviene
usando il protocollo UDP sulla porta 500. Pertanto è essenziale al
funzionamento di IPSEC che un firewall lasci passare il traffico su questa
porta. 

IKE è progettato per la massima flessibilità e permette di negoziare
separatamente per ciascuna SA un tempo di vita, l'algoritmo crittografico
(simmetrico) da utilizzare per la cifratura dei pacchetti, l'algoritmo per
l'autenticazione, e l'algoritmo di crittografia asimmetrica usato per lo
scambio delle chiavi. Con la versione 2, oltre a vari miglioramenti relativi
ai meccanismi di negoziazione, all'affidabilità delle connessione, e alla
resistenza ad attacchi di DoS, è stato inserito all'interno del protocollo la
gestione del cosiddetto \textit{NAT Traversal} (su cui torneremo più avanti)
con l'incapsulazione di sia di IKE che ESP in pacchetti UDP, per i quali è
stata riservata la porta 4500. Se pertanto si utilizza IKEv2 è necessario che
il firewall consenta il traffico anche su questa porta.

Una volta completata l'impostazione iniziale tramite IKE, tutto il resto della
comunicazione avviene direttamente attraverso quello che più propriamente si
indica con IPSEC, facendo riferimento solo ai due protocolli AH ed ESP, che
effettivamente operano a livello di rete. Infatti IKE è un protocollo di
livello superiore che serve a negoziare i parametri usati dagli altri due,
l'effettiva comunicazione non avviene attraverso di esso. Da qui in avanti
perciò riferendoci ad IPSEC intenderemo soltanto la parte relativa alla
comunicazione al livello di rete.

\begin{figure}[!htb]
  \centering
  \includegraphics[width=10cm]{images/IPSEC_modes}
    \caption{Modalità di trasporto dei dati realizzate tramite IPSEC.} 
    \label{fig:VPN_IPSEC_modes}
\end{figure}

Che sia incapsulato in IPv4, o implementato come estensione di IPv6, IPSEC
supporta due modalità native, illustrate in fig.~\ref{fig:VPN_IPSEC_modes}. La
prima, detta modalità di trasporto (o \textit{Transport Mode}) prevede la
comunicazione diretta da stazione a stazione, ciascuna delle quali tratta i
suoi pacchetti e li spedisce tramite IPSEC. La seconda modalità, detta tunnel
(o \textit{Tunnel Mode}) prevede invece la presenza di almeno un router (il
cosiddetto \textit{security gateway}) che faccia da tramite per la
comunicazione con le macchine poste nella rete per la quale agisce appunto da
\textit{gateway}.

La modalità tunnel è appunto la modalità tipica con cui si realizza una VPN, e
presenta le due possibilità mostrate nella parte alta di
fig.~\ref{fig:VPN_IPSEC_modes}, in cui si può realizzare la VPN per comunicare
da una macchina esterna (il \textit{road warrior}) verso il \textit{security
  gateway} per accedere alla rete dietro di questi, o direttamente fra due
\textit{security gateway}, per connettere due reti private. 

In generale IPSEC supporta due tipi di comunicazione, autenticata o cifrata,
che possono essere usate indipendentemente l'una dall'altra. Però l'uso di una
comunicazione cifrata non autenticata è insicuro e soggetto ad attacchi che
possono permettere di decifrare i messaggi, per cui non viene mai usata.  La
comunicazione autenticata avviene attraverso l'uso di AH, mentre la
comunicazione cifrata attraverso ESP, che supporta anche, ove richiesto (e
come detto questo deve essere sempre fatto) l'autenticazione. 

\begin{figure}[!htb]
  \centering
  \includegraphics[height=6cm]{images/ah_scheme}
    \caption{Schema di un pacchetto IPSEC autenticato l'uso di AH.} 
    \label{fig:VPN_AH}
\end{figure}

Dei due protocolli usati per la comunicazione effettiva AH serve solo ad
autenticare i pacchetti; il meccanismo di funzionamento di AH, nei due casi di
modalità trasporto o tunnel, è illustrato in fig.~\ref{fig:VPN_AH}. Nel caso
si usi la modalità trasporto ci si limita a frapporre fra l'intestazione di IP
e quella dei protocolli di livello superiore (nell'esempio TCP) l'intestazione
di AH, che contiene tutti i dati relativi all'autenticazione. 

Se invece si opera in modalità tunnel si crea una nuova intestazione per il
pacchetto, che conterrà solo gli indirizzi degli estremi del tunnel, e si
autentica tutto il pacchetto originale, replicandolo integralmente dopo
l'intestazione di AH. Alla ricezione del pacchetto il router che fa da
\textit{security gateway} rimuoverà l'intestazione usata per la trasmissione,
verificherà il contenuto e ricostruirà il pacchetto originale, inviandolo a
destinazione (in genere nella rete privata posta dietro il router stesso). In
questo modo si possono inviare pacchetti attraverso internet anche usando gli
indirizzi riservati per le reti private illustrati in
sez.~\ref{sec:VPN_whatis}. 

La procedura di autenticazione cerca di garantire l'autenticità del pacchetto
nella massima estensione possibile, ma dato che alcuni campi dell'intestazione
di IP possono variare in maniera impredicibile alla sorgente, il loro valore
non può essere protetto dall'autenticazione.  Il calcolo dei dati di
autenticazione viene allora effettuato alla sorgente su una versione speciale
del pacchetto inviato in cui il TTL nell'intestazione principale è impostato a
zero, così come le opzioni che possono essere modificate nella trasmissione. 
La copertura dell'autenticazione del pacchetto è mostrata sempre in
fig.~\ref{fig:VPN_AH}. 

Qualora si debba garantire una trasmissione riservata dei dati, occorre invece
usare ESP, lo schema di un pacchetto secondo questo protocollo è illustrato in
fig.~\ref{tab:VPN_ESP}; di nuovo se si opera in modalità di trasporto ci si
limita a cifrare il contenuto del pacchetto IP, interponendo il risultato fra
l'intestazione di ESP ed una coda che chiude la sezione cifrata; a questo si
aggiunge poi un'eventuale altra sezione finale che contiene le informazioni di
autenticazione; le sezioni del pacchetto coperte da autenticazione e
crittografia sono sempre riportate in fig.\ref{tab:VPN_ESP}. 

\begin{figure}[!htb]
  \centering
  \includegraphics[height=6cm]{images/esp_scheme}
  \caption{Schema di pacchetto IPSEC cifrato con l'uso di ESP.} 
  \label{tab:VPN_ESP}
\end{figure}

Se invece si opera in modalità tunnel come nel caso di AH si usa una nuova
intestazione per IP, cifrando completamente tutto il pacchetto originale.  In
questo modo non solo si potranno usare nel pacchetto originale indirizzi di
reti private, ma in generale si potrà impedire ad un osservatore di conoscere
gli indirizzi originali di sorgente e destinazione, dato che rimangono nella
parte non cifrata solo quelli dei due \textit{security gateway} che effettuano
lo scambio. 

Come accennato IPSEC è un protocollo standard ed è quello che viene utilizzato
da più tempo per la creazione di VPN; nonostante questo esso non risulta essere
molto diffuso e nel tempo sono stati proposti parecchi approcci alternativi.
Tutto questo è dovuto al fatto che i vari protocolli che compongono IPSEC
hanno una pessima interazione il NAT, per cui la versione originale di IPSEC
non è utilizzabile quando i pacchetti devono attraversare un router o un
firewall che eseguono un NAT.\footnote{il caso può sembrare irrilevante
  rispetto alle situazioni illustrate in fig.~\ref{fig:VPN_IPSEC_modes}, dato
  che basterebbe utilizzare IPSEC sul firewall o sul router dopo aver
  eseguito il NAT; il problema è che solo una piccola percentuale di router
  (quelli più evoluti) supportano IPSEC, ma anche così non si risolverebbe il
  problema, molto comune, di tutti quei client che si vorrebbero collegare
  come \textit{road warrior} partendo da una rete privata, dato che in tal
  caso l'indirizzo di partenza dei pacchetti IPSEC deve stare sul client.}

In particolare AH semplicemente non può di funzionare in caso di NAT.  Esso
infatti autentica (si riveda fig.~\ref{fig:VPN_AH}) l'intero pacchetto,
compresi gli indirizzi sorgente e destinazione, che verrebbero modificati
nell'attraversamento di un NAT, pertanto una volta passato il NAT il pacchetto
non risulterebbe più originale. Dato che AH nasce appunto per eliminare la
possibilità di ricevere pacchetti modificati, ed il NAT funziona modificando i
pacchetti, i due semplicemente non possono lavorare insieme.

Con ESP, anche quando il contenuto è autenticato, il problema è più sottile in
quanto in questo caso gli indirizzi esterni (vedi fig.~\ref{tab:VPN_ESP}) non
sono inclusi nell'autenticazione, quindi possono essere modificati nel NAT.
Restano però una serie di altri problemi; il primo è che quando il pacchetto
originale contiene dei pacchetti UDP o TCP la checksum che ne verifica
l'integrità è calcolata sugli IP originali, e questa, se il pacchetto è
cifrato con IPSEC, non può essere aggiornata, per cui a destinazione essa non
corrisponderà; inoltre si pone il problema di come reinviare all'indietro i
pacchetti di risposta, dato non ci sono dati permettano di associare in
maniera adeguata un certo pacchetto IPSEC ad uno specifico indirizzo
interno.\footnote{nel caso di TCP e UDP questo viene fatto tenendo in conto
  (ed eventualmente modificando) il numero di porta, ma ESP non ha nulla di
  equivalente, l'unica possibilità potrebbe essere l'uso del campo SPI, che
  però non può essere modificato; essendo un numero 32 bit la probabilità di
  collisione sarebbe bassa, ma il punto è che questo è associato ad una SA, ed
  è quindi diverso a seconda della direzione del pacchetto e non esiste un
  modo semplice per associare un valore in uscita con uno in ingresso.}

Oltre a questi ci sono poi un'altra serie di problemi legati all'uso di IKE
che alla fine rendono impossibile l'uso della versione originale di IPSEC
attraverso un NAT. Per questo motivo è stata realizzata una estensione del
protocollo chiamata NAT-T (da \itindex{NAT~Traversal} \textit{NAT Traversal})
che prevede l'incapsulamento dei pacchetti ESP in pacchetti UDP con l'uso
della porta 4500, così che a questo punto diventa possibile attraversare
normalmente un NAT come avviene per tutti i pacchetti UDP.  Questa però è una
estensione successiva, e compresa come parte dello standard solo con
IKEv2. Inoltre alla fin fine usare questo metodo alla fine rende IPSEC
equivalente alle modalità di funzionamento di altre soluzioni (come OpenVPN,
che vedremo in sez.~\ref{sec:fw_openvpn}) che lavorano nativamente su UDP.


\subsection{Le VPN in \textit{user-space}}
\label{sec:user_space_VPN}

Il problema maggiore di FreeS/WAN e di tutti i derivati successivi, come
\textit{Openswan}, così come dell'implementazione nativa del kernel 2.6 ed in
generale di tutte le VPN basate su IPSEC, è che il loro funzionamento,
appoggiandosi su un apposito protocollo del livello di rete, è realizzato
all'interno del kernel.  Questo comporta in genere una procedura di
installazione molto più complessa (in caso di necessità di modifiche o
aggiornamenti si tratta di reinstallare il kernel e riavviare la macchina), ed
inoltre in caso di vulnerabilità fornisce ad un attaccante il massimo dei
privilegi possibili, ed il massimo del rischio, dato che un problema può far
crollare l'intero sistema.

Se a questo si aggiunge che né FreeS/WAN né \textit{Openswan} brillavano per
semplicità di installazione e configurazione, si comprende come si siano
cercate delle alternative che permettessero di implementare una VPN in
\textit{user-space}, utilizzando dei normali programmi che implementassero il
tunnel attraverso una connessione cifrata appoggiandosi ad un normale
protocollo del livello di trasporto (in genere tramite socket UDP), risolvendo
così anche i problemi relativi all'attraversamento di firewall e NAT che sono
presenti con l'uso di IPSEC.

Una tale alternativa presenta una lunga serie di innegabili vantaggi: gli
aggiornamenti sono molto più semplici (basta reinstallare un programma e
riavviare il servizio), è possibile far girare il servizio per conto di utenti
non privilegiati (riducendo così i rischi in caso di compromissione o di bug),
si evitano completamente le problematiche relative all'attraversamento di un
NAT che avviene come per qualunque altro servizio basato su socket.

In genere questo tipo di prodotti si basano sull'uso di SSL, che è un
protocollo ampiamente noto e ben controllato, e che non presenta le
problematiche di gestione di IPSEC, che è un protocollo molto complesso che se
non è configurato correttamente rischia di perdere le sue caratteristiche di
sicurezza. In questo caso si tratta in genere di fare passare i dati della VPN
attraverso una connessione protetta con SSL.

Capita spesso però che i vantaggi in semplicità si traducano in una
diminuzione del livello di sicurezza; questo è vero in particolare per tutte
quelle VPN in \textit{user-space} che sono realizzate con un programma che
permette di aprire una connessione verso un server centrale, limitandosi
semplicemente a cifrare la comunicazione con SSL. Questo può rendere la
configurazione anche molto semplice, ma si perde così però uno dei cardini di
IPSEC, che è quello di poter identificare con certezza l'uno con l'altro i due
capi della connessione.

In altri casi invece si spaccia per VPN quello che è un banalissimo tunnel
relativo ad un singolo protocollo, cioè al fatto di far passare il traffico
verso certi servizi per una connessione SSL, redirigendo il traffico di una o
più porte su un canale cifrato come visto in sez.~\ref{sec:ssl_intro} per
\texttt{stunnel}. In questo caso manca completamente la capacità, propria di
una vera VPN, di dare un accesso all'intera gamma dei servizi di rete.

È pertanto essenziale nella scelta di una VPN in \textit{user-space}, capire
quali sono le modalità in cui questa viene realizzata, e quale può essere la
sua utilizzabilità su diverse piattaforme, dato che in questo caso non esiste
una standardizzazione di un protocollo come quella di IPSEC. Come vedremo in
sez.~\ref{sec:fw_openvpn} OpenVPN rappresenta una valida soluzione per la
realizzazione di VPN in \textit{user-space}, con funzionalità che non hanno
nulla da invidiare rispetto a nessun altro prodotto, tanto è diventata
praticamente uno standard presente in ogni distribuzione GNU/Linux.



\section{La gestione di VPN con \textit{Openswan} e \textit{strongSwan}}
\label{sec:VPN_linux_IPSEC}

Vedremo in questa sezione come realizzare una VPN con IPSEC, sia per la parte
di comunicazione di rete tramite i protocolli AH ed ESP, che per la gestione
di tunnel cifrati con IKE, facendo riferimento ad una delle diverse possibili
soluzioni, quella realizzata dal pacchetto \textit{Openswan}. Dato che la
realizzazione di IPSEC su Linux ha avuto una storia travagliata inizieremo con
una panoramica generale sull'argomento.


\subsection{Quale IPSEC per Linux}
\label{sec:VPN_IPSEC_history}

Linux ha acquisito una implementazione ufficiale, (presente cioè nella
versione standard del kernel) di IPSEC (o meglio dei protocolli AH e ESP) a
partire dai kernel della serie 2.6, di questa esiste anche un
\textit{backport} non ufficiale per i kernel della serie 2.4. Questa
implementazione, denominata \textit{NETKEY}, è stata realizzata rifacendosi
alla architettura della analoga implementazione realizzata dal progetto KAME
per i vari FreeBSD, OpenBSD, ecc.

In precedenza però era già presente una implementazione del protocollo IPSEC
realizzata dal progetto FreeS/WAN. Questo progetto, oltre ad una
implementazione dei protocolli AH ed ESP, realizzata come patch al kernel
ufficiale e denominata \textit{KLIPS}, forniva anche un demone per l'uso di
IKE ed il supporto per una modalità di funzionamento, detta
\itindex{Opportunistic Encription} \textit{Opportunistic Encription}
(abbreviata in OE) che fosse in grado di far utilizzare automaticamente IPSEC
per ogni comunicazione con altre macchine in grado di utilizzare detto
protocollo.\footnote{l'idea era di inserire opportuni record con chiavi
  pubbliche nel DNS che se ottenuti avrebbero consentito la creazione
  automatica di un canale cifrato con la destinazione.}

Gli scopi del progetto erano essenzialmente di protezione della privacy (da
cui derivava lo sviluppo della parte relativa alla \itindex{Opportunistic
  Encription} \textit{Opportunistic Encription}), con una forte attenzione
agli aspetti politici. All'epoca il software FreeS/WAN veniva sviluppato al di
fuori dagli Stati Uniti in quanto quel paese non consentiva l'esportazione di
software crittografico. Nel Gennaio del 2000 i regolamenti vennero cambiati e
le esportazioni (eccettuato quelle verso alcuni paesi considerati terroristi)
consentite.

Dato però che non vi era certezza legislativa (il permesso resta di natura
amministrativa e può essere revocato in qualunque momento) i leader del
progetto FreeS/WAN continuarono a rifiutarsi di accettare contributi da
cittadini statunitensi per essere assolutamente certi di evitare problemi di
natura legale.  Questo, insieme ad altre considerazioni di natura tecnica, e
agli immancabili attriti personali, creò un conflitto con gli sviluppatori del
kernel (che ritenevano accettabili contributi da cittadini statunitensi e
troppo pesanti i cambiamenti apportati allo stack TCP/IP del kernel) che
finirono per reimplementare indipendentemente i protocolli AH ed ESP.

In ragione di questa situazione e della percezione di uno scarso successo
dell'obiettivo principale del progetto, che rimaneva quello della diffusione
capillare della \itindex{Opportunistic Encription} \textit{Opportunistic
  Encription}, nel Marzo del 2004 il team originale decise di cessare lo
sviluppo di FreeS/WAN. Trattandosi di software libero il codice venne
immediatamente ripreso e con la nascita di altri progetti come
\textit{strongSwan} e \textit{Openswan} che ne hanno proseguito lo sviluppo,
aggiungendo al contempo un gran numero di funzionalità, come il \textit{NAT
  traversal} e l'autenticazione tramite certificati, che fino ad allora erano
state sviluppate esternamente.

Così dal lato del kernel ci si è trovati così di fronte a diverse
implementazioni dei protocolli di rete necessari. Però, come illustrato in
sez.~\ref{sec:VPN_IPSEC}, per la creazione di una VPN con IPSEC non è
sufficiente disporre di una implementazione dei protocolli AH ed ESP nel
kernel, ma occorre anche utilizzare una implementazione del protocollo IKE per
garantire autenticazione dei capi della comunicazione ed uno scambio sicuro
delle chiavi crittografiche. Benché questo tipo di supporto sia stato
parzialmente introdotto al di fuori di FreeS/WAN portando su Linux i programmi
di gestione ripresi dal progetto KAME (che fanno parte dei cosiddetti
\texttt{ipsec-tools}) l'implementazione presente in FreeS/WAN era nettamente
più evoluta ed è stata ereditata dai suoi successori.

Pertanto al momento sono disponibili una larga serie di combinazioni di
elementi con cui è possibile creare una VPN basata su IPSEC; nel seguito si è
preferito fare riferimento alle implementazioni derivate da FreeS/WAN
(\textit{Openswan} e \textit{strongSwan}),\footnote{che nel caso di Debian
  vengono distribuite direttamente negli omonimi pacchetti \texttt{openswan} e
  \texttt{strongswan}.} per le maggiori funzionalità da essi fornite (in
particolare per \textit{strongSwan} che supporta pienamente anche la versione
2 del protocollo IKE) rispetto agli strumenti di \texttt{ipsec-tools}.

Inizialmente i due progetti citati erano sostanzialmente equivalenti,
differenziandosi in seguito sulle funzionalità aggiunte e sul focus dello
sviluppo, più centrato sulle funzionalità di autenticazione e identificazione
il primo, che ha aggiunto numerose modalità di autenticazione delle VPN e
diversi algoritmi di cifratura, più sulle tecnologie di rete il secondo, che
continua a sviluppare per il 2.6 anche l'implementazione originale di IPSEC
(\textit{KLIPS}) del progetto FreeS/WAN. 



\subsection{Configurazione iniziale di \textit{strongSwan} e
  \textit{Openswan}}
\label{sec:VPN_install}

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto sulla compilazione di KLIPS 
%% non includere nelle nuove versioni
%%
\ifx\obsoletesection\undefined

\relax
\else

Il pacchetto \textit{Openswan} è costituito da due sezioni principali: la
prima parte è quella che contiene le modifiche al kernel, distribuite come
patch rispetto ai sorgenti ufficiali, che implementano i due protocolli AH e
ESP, più tutto il codice per la manipolazione dei relativi con
l'implementazione dei protocolli di crittografia necessari alla cifratura
degli stessi.

La seconda parte è quella degli strumenti in user space, e contiene il demone
Pluto, che implementa il protocollo IKE, ed il comando \texttt{ipsec} che
fornisce l'interfaccia con la quale è possibile controllare e configurare il
funzionamento di IPSEC nella macchina, più una serie di vari programmi
ausiliari per la gestione delle chiavi e delle VPN.

La parte più complessa dell'installazione è quella della ricompilazione del
kernel, questa però è necessaria soltanto se si vuole utilizzare un kernel
della serie 2.4;\footnote{nel caso di Debian, se si usano i kernel della
  distribuzione, non è necessario ricompilare neanche i kernel della serie
  2.4.x, dato che il pacchetto Debian include anche il backporting delle
  funzionalità di IPSEC.} se si usa un kernel della serie 2.6 se ne può fare a
meno, usando il supporto già presente nelle versioni ufficiali.  Qualora sia
necessario o si voglia usare la implementazione dei protocolli di IPSEC di
\textit{Openswan} ci può venire in aiuto il \texttt{kernel-package} di Debian,
che consente la ricompilazione con l'applicazione al volo dei vari patch
necessari.

\begin{figure}[h!tb]
\centering
\includegraphics[scale=0.5]{images/IPSEC_options}
\caption{Opzioni di configurazione su un kernel 2.4 per i patch di IPSEC.} 
\label{fig:VPN_kernel_options}
\end{figure}

Non staremo qui a coprire i dettagli di questo procedimento, confidando in APT
per considerare compiuta l'installazione. Ci limitiamo a riportare quanto deve
essere fatto nella configurazione del kernel per l'uso di IPSEC una volta che
si siano installati i relativi pacchetti. Questa è accessibile dal menù
\texttt{Networking Options}, in cui compare una apposita sezione mostrata in
fig.~\ref{fig:VPN_kernel_options}. 

In particolare l'opzione principale è quella che attiva IPSEC (\texttt{IP
  Security Protocol}) che può essere utilizzata anche modularmente. Per poter
costruire VPN con IPSEC occorre utilizzare il tunnel mode, abilitando il
relativo supporto. Le opzioni successive abilitano il supporto per AH e ESP,
con i relativi algoritmi di cifratura e identificazione disponibili con la
versione standard di IPSEC.

In fig.~\ref{fig:VPN_kernel_options} si è lasciata non attiva l'opzione
relativa alle estensioni modulari, che diventano disponibili installando il
pacchetto \texttt{openswan-modules-source}; se la si attiva diverranno
disponibili una lunga serie di altri algoritmi crittografici utilizzabili per
la cifratura e l'autenticazione, mostrati in fig.~\ref{fig:VPN_ipsec_modules}.

\begin{figure}[htb]
  \centering \includegraphics[scale=0.5]{images/IPSEC_modules}
\caption{Opzioni di configurazione per i moduli aggiuntivi di crittografia.} 
\label{fig:VPN_ipsec_modules}
\end{figure}

In caso di compilazione modulare si possono tranquillamente attivare tutte le
opzioni. La prima volta che si installa \textit{Openswan} può anche essere
utile usare l'ultima opzione che permette di attivare la modalità di debug; in
produzione però è meglio disattivarla per avere migliori prestazioni e file di
log più snelli.

Per usare le funzionalità evolute del \texttt{kernel-package} di Debian
occorre anzitutto definire la variabile \texttt{PATCH\_THE\_KERNEL=yes}, dopo
di che si può procedere alla ricompilazione del kernel con:
\begin{Command}
make-kpkg --added-patches=openswan kernel_image
\end{Command}
per poi installare il pacchetto prodotto. Altrimenti si può usare la stessa
procedura che si usa abitualmente per la ricompilazione del kernel e la
relativa installazione.

Una volta che si sia installato e si stia utilizzando un kernel con
l'opportuno supporto si può passare alla configurazione di \textit{Openswan}. In
sostanza si tratterà di configurare il demone che permette di utilizzare il
protocollo IKE per lo scambio delle chiavi fra due macchine che usano IPSEC.

Con il pacchetto \texttt{openswan} si installa il demone \texttt{pluto} che
effettua la gestione di IKE, i vari script di avvio, ed il programma di
controllo \texttt{ipsec}. Il sistema del \textit{debconf} si incarica inoltre
di richiedere le informazioni necessarie alla creazione di uno scheletro di
configurazione iniziale.  La prima richiesta è quella relativa al momento in
cui avviare il servizio, per cui dopo una schermata informativa sulle varie
opzioni verrà presentato il menù illustrato in fig.~\ref{fig:VPN_ipsec_conf1}.

\begin{figure}[!htb]
  \centering \includegraphics[scale=0.5]{images/openswan_conf1}
\caption{Schermata di configurazione per l'avvio di \textit{Openswan}.} 
\label{fig:VPN_ipsec_conf1}
\end{figure}

Le possibilità in questo caso sono tre, ma considerato che in
\textit{Openswan} dovrà girare su una macchina che fa da router è ovviamente
sconsigliabile che su di essa sia attivo NFS, e dato che è piuttosto raro che
l'interfaccia verso internet sia su un scheda PCMCIA, normalmente la scelta è
quella di farlo partire il prima possibile.

\begin{figure}[!htb]
  \centering \includegraphics[scale=0.5]{images/openswan_conf2}
\caption{Schermata per la configurazione del tipo di credenziali di
  autenticazione.} 
\label{fig:VPN_ipsec_conf2}
\end{figure}

Una volta decisa la strategia di avvio seguono due schermate che consentono di
scegliere se si vuole riavviare il demone dopo un aggiornamento, e se si vuole
abilitare \itindex{Opportunistic Encription} l'\textit{Opportunistic
  Encription}. Per esse si può lasciare il default che è si e no
rispettivamente.  L'ultima parte della configurazione automatica è quella che
prevede la creazione delle credenziali per l'autenticazione dei capi della
VPN. Dopo una schermata introduttiva viene presentata una schermata di scelta
del metodo da utilizzare, illustrata in fig.~\ref{fig:VPN_ipsec_conf2}.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto KLIPS, non includere nelle nuove versioni
%%
\fi


La principale differenza nelle versioni recenti di \textit{Openswan} e
\textit{strongSwan} è che il primo continua a supportare anche per i kernel
della serie 2.6 l'implementazione originaria (KLIPS) del protocollo IPSEC
realizzata dal progetto FreeS/WAN, mentre \textit{strongSwan} usa soltanto il
supporto della implementazione standard del kernel anche se è in grado di
usare KLIPS su un kernel 2.4.

Dato che lo sviluppo di KLIPS è comunque destinato a seguire sempre con un
certo ritardo l'evoluzione del kernel, problema che non si pone rispetto
all'implementazione nativa, non prenderemo in considerazione le problematiche
relative alla sua installazione facendo riferimento al supporto standard
(NETKEY) che è presente su tutti i kernel delle principali
distribuzioni.\footnote{nel caso di Debian comunque con \textit{Openswan}
  viene distribuito il supporto di KLIPS con i due pacchetti
  \texttt{openswan-modules-source} e \texttt{openswan-modules-dkms} che
  consentono una ricompilazione dello stesso come modulo in maniera
  relativamente semplice, mentre il kernel 2.4 contiene già integrato il
  backport di NETKEY.} Per questo il resto di questo paragrafo tratterà solo
gli aspetti del supporto IPSEC in user-space, vale a dire dei programmi che
implementano il protocollo IKE.

Fra le due alternative \textit{strongSwan} sembra quella sviluppata in maniera
più attiva: ha il supporto completo per IKEv2, fornisce una documentazione
molto più aggiornata e sembra orientata verso nuove direzioni di
sviluppo. Tratteremo pertanto principalmente questa, illustrando brevemente,
dove possibile, le eventuali differenze con \textit{Openswan}, anche se, a
causa dell'origine comune, i nomi dei file di configurazione e la relativa
sintassi, molte direttive, i comandi di gestione e le relative opzioni, sono
gli stessi anche per \textit{Openswan}.

Essendo disponibili i pacchetti per le principali distribuzioni non staremo a
trattare le modalità di installazione; nel caso di Debian i pacchetti
forniscono i programmi per la gestione di IKE, lo script di avvio
(\texttt{/etc/init.d/ipsec}), ed il programma di controllo \texttt{ipsec}. In
entrambi i casi con il pacchetto viene installato uno scheletro di file di
configurazione.\footnote{nel caso di \textit{Openswan} \textit{debconf}
  presenta una schermata in cui si chiede se usare certificati per
  l'identificazione (con la possibilità successiva di crearne o importarne
  uno) o lasciare la cosa non configurata.}  La configurazione dipende infatti
da quali sono i canali IPSEC che si vogliono stabilire e dalle modalità di
autenticazione che si vogliono usare per la loro creazione (che tratteremo a
parte in sez.~\ref{sec:VPN_ident}), e dovrà essere completata manualmente.

Nel caso di \textit{strongSwan}, che come accennato fornisce anche una
implementazione completa della versione 2 del protocollo IKE, oltre al
classico demone \texttt{pluto} ereditato da FreeS/WAN, che gestisce la
versione 1 del protocollo, viene installato anche un secondo demone,
\texttt{charon}, sviluppato da zero per questo scopo, che prevede alcune
configurazioni specifiche non contemplate da \textit{Openswan}.  Questo non è
disponibile per \textit{Openswan} che usa una sua versione modificata di
\texttt{pluto} che supporta alcune funzionalità di base di IKEv2.

%%
%% OBSOLETED CONFIG OPTIONS
%%
% In realtà dei metodi di autenticazione possibili (che tratteremo più avanti)
% ne vengono proposti solo due, quelli basati su crittografia asimmetrica,
% tramite l'uso diretto di chiavi RSA o tramite certificati X.509. Una volta
% scelto quale dei due metodi vengono chiesti i dati necessari alla creazione
% delle credenziali.

% Nel caso di uso di chiavi RSA verrà chiesta semplicemente la dimensione della
% chiave, nel caso di certificati verrà invece chiesto se si vuole creare un
% certificato autofirmato (nel qual caso successive schermate richiederanno i
% dati da includere in esso) o se si vuole utilizzare un certificato già
% presente, nel qual caso verranno chiesti rispettivamente i nomi dei file che
% contengono il certificato e la relativa chiave privata.


Il file di configurazione principale è
\index{configurazione!\texttt{/etc/ipsec.conf}} \texttt{/etc/ipsec.conf}, la
cui sintassi è descritta in dettaglio nella relativa pagina di manuale,
accessibile con \texttt{man ipsec.conf}.  Qualora si usi una versione di
\textit{Openswan} superiore alla 2.0 la prima riga non commentata del file
deve essere \texttt{version 2.0}, in quanto con il passaggio a tale versione
sono cambiate alcune opzioni di configurazione,\footnote{questo fa differenza
  solo nel caso di vecchie Debian, in quanto in \textit{woody} è presente la
  versione 1.96 di FreeS/WAN, che usa la vecchia sintassi, tutte le
  distribuzioni recenti usano la nuova sintassi e specificano questo valore.}
ed occorre perciò segnalare esplicitamente quale sintassi si sta
utilizzando. Tutto ciò non è necessario per \textit{strongSwan} che non
supporta versioni precedenti del file di configurazione.

Il file contiene tutte le informazioni di configurazione necessarie al
funzionamento di una VPN, ad eccezione delle informazioni di autenticazione
reciproca che, come vedremo in sez.~\ref{sec:VPN_ident} sono mantenute in
\texttt{ipsec.secrets}. Per questo di norma il file non contiene informazioni
riservate, e può essere tenuto accessibile in lettura.\footnote{l'unico caso
  in cui questo non è vero era con il cosiddetto \textit{manual keying}, vedi
  quanto detto all'inizio di sez.~\ref{sec:VPN_ident}.} Si possono comunque
raccogliere eventuali configurazioni che si vogliono mantenere private in
singoli file separati (senza permesso di lettura) che possono essere inclusi
in \texttt{ipsec.conf} tramite la direttiva \texttt{include}, questa richiede
che si specifichi un nome di file e supporta anche inclusioni multiple con
l'uso del carattere jolly ``\texttt{*}''.

Il formato di \texttt{ipsec.conf} segue le convezioni standard per cui righe
vuote e quanto segue il carattere ``\texttt{\#}'' viene ignorato. Il suo
contenuto è suddiviso in sezioni, che sono introdotte da una riga nella
forma ``\texttt{tipo nome}'', dove \texttt{tipo} è una parola chiave riservata
che indica il tipo della sezione, e \texttt{nome} è un identificativo scelto
dall'utente per distinguere sezioni dello stesso tipo.

Si tenga presente che la dichiarazione di una sezione, così come la direttiva
\texttt{include}, deve sempre iniziare all'inizio di una riga; il contenuto
della sezione infatti viene identificato dal fatto che le righe che ne fanno
parte iniziano almeno con uno spazio; questo consente di avere una visione
immediata del contenuto delle varie sezioni usando semplicemente
l'indentazione.  
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Tipo}&\textbf{Significato}\\
    \hline
    \hline 
    \texttt{config}  & Indica una sezione di configurazione, 
                       prevede obbligatoriamente come identificativo il valore
                       \texttt{setup}, e viene utilizzata per le impostazioni
                       di avvio dei demoni.\\
    \texttt{conn}    & Identifica una sezione di configurazione di una
                       connessione VPN, richiede un identificativo arbitrario
                       purché univoco.\\ 
    \texttt{ca}      & Identifica una sezione che consente di applicare valori
                       specifici ad una \textit{Certification Authority}
                       (valida solo per \textit{strongSwan}).\\
    \hline
    \texttt{include} & Consente di includere il contenuto del file passato
                       come identificativo (pertanto non è propriamente un
                       identificatore di sezione).\\
    \texttt{version} & Indica la versione della sintassi del file di
                       configurazione (valida solo, e da specificare
                       obbligatoriamente, per \textit{Openswan}).\\
    \hline
  \end{tabular}
  \caption{Parole chiave identificanti i tipi di sezione utilizzabili in
    \texttt{ipsec.conf}.}
\label{tab:ipsec_conf_section_type}
\end{table}

I tipi di sezione disponibili sono tre; il primo tipo è \texttt{config}, che
viene usata per impostare la configurazione di avvio dei vari demoni ed al
momento questa sezione ha un unico nome possibile che è \texttt{setup}. Il
secondo tipo di sezione è \texttt{conn} che identifica una connessione fra i
due capi di una VPN, ed il cui nome è un qualunque identificativo associato
alla stessa. Il terzo (disponibile solo per \textit{strongSwan}) è
\texttt{ca}, che permette di specificare le proprietà di una
\textit{Certification Authority}. Si è riassunta la situazione in
tab.~\ref{tab:ipsec_conf_section_type} dove si sono riportate (nella seconda
parte) anche le altre direttive che pur non definendo sezioni devono essere
utilizzate in maniera simile (cioè scritte senza indentazione).

Il contenuto di ogni sezione è poi costituito da una serie di direttive di
assegnazione dei valori per i valori dei parametri che sono definiti in quella
sezione, da esprimere nella forma \texttt{parametro=valore}, esiste però un
parametro speciale, \texttt{also}, valido per tutti i tipi di sezione, che
quando viene assegnato al nome di un'altra sezione consente di aggiungere le
definizioni dei parametri in essa presenti alla sezione in cui viene
utilizzato, come se questi venissero scritti al suo posto. L'uso di
\texttt{also} può essere nidificato, e lo si può anche utilizzare più volte
purché non ci sia mai un riferimento multiplo alla stessa sezione. La sezione
a cui si fa riferimento deve ovviamente esistere, ed essere specificata
\textsl{dopo} quella in cui lo si utilizza.

Per le sezioni di tipo \texttt{ca} e \texttt{conn} esiste inoltre il nome
riservato \texttt{\%default} che serve a configurare i valori di default che
saranno automaticamente assegnati (qualora non sovrascritti da altre
assegnazioni esplicite) ai parametri di quel tipo di sezione.\footnote{questo
  nome veniva usato per impostare correttamente le connessioni con le versioni
  di FreeS/WAN precedenti la 2.0, a partire da questa versione infatti i
  valori di default sono stati corretti e questo tipo di dichiarazione non
  viene sostanzialmente più usato.} Queste devono essere comunque specificate
prima delle sezioni normali, inoltre non si può usare il parametro
\texttt{also} in una di queste sezioni.

La prima parte della configurazione è sempre costituita dalla sezione
\texttt{config}, un esempio del suo contenuto, ripreso dal file
\texttt{ipsec.conf} installato con \textit{strongSwan} su una Debian Squeeze
come scheletro di configurazione è il seguente:
\begin{FileExample}[label=ipsec.conf]
config setup
        # plutodebug=all
        # crlcheckinterval=600
        # strictcrlpolicy=yes
        # cachecrls=yes
        # nat_traversal=yes
        charonstart=yes
        plutostart=yes
\end{FileExample}

Come accennato la sezione ha come unico nome utilizzabile \texttt{setup}, e vi
si richiede semplicemente l'avvio dei demoni \texttt{charon} e \texttt{pluto}
con i due parametri \texttt{charonstart} e \texttt{plutostart}, tenendo per
buoni i valori di default di tutti gli altri parametri.\footnote{nel caso di
  \textit{Openswan} questa sezione è totalmente diversa; non sono previste le
  direttive di avvio dei singoli demoni in quanto esiste solo \texttt{pluto},
  mentre va specificato quale implementazione dei protocolli di rete usare con
  il parametro \texttt{protostack}, impostato ad \texttt{auto} per indicare al
  programma di provare prima con NETKEY e poi con KLIPS.}  Nello scheletro
resta commentata la predisposizione di alcuni dei parametri di controllo, si
sono riportati in tab.~\ref{tab:ipsec_conf_setup} quelli ritenuti più
rilevanti, per un elenco completo si deve fare riferimento alla pagina di
manuale di \texttt{ipsec.conf}.\footnote{si tenga presente che i parametri
  sono diversi per \textit{Openswan} e \textit{strongSwan}.}

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Parametro}&\textbf{Significato}\\
    \hline
    \hline 
    % \texttt{interfaces}    & Specifica su quali interfacce fisiche abilitare
    %                          una interfaccia virtuale per ricevere il
    %                          traffico di IPSEC; viene usata con KLIPS che
    %                          definisce le interfacce virtuali
    %                          \texttt{ipsecN}. Prende come valore una  
    %                          stringa contenente una lista di assegnazioni
    %                          quotata da virgolette, nella forma
    %                          \verb|"ipsec0=eth0 ipsec1=eth1"|; l'uso del
    %                          valore \texttt{\%defaultroute} è equivalente a
    %                          \verb|"ipsec0=ethX"|, dove \texttt{ethX} è
    %                          l'interfaccia del default gateway.\\ 
    % \texttt{syslog}        & Indica le modalità di invio dei messaggi di avvio
    %                          e terminazione al sistema del
    %                          \textit{syslog}. Prende una valore nella forma
    %                          \texttt{facility.priority} ed il 
    %                          default è \texttt{daemon.error}.\\
    % \texttt{klipsdebug}    & Stabilisce quale livello di messaggi di debug
    %                          di KLIPS deve essere registrato. Se vuoto o con
    %                          il valore \texttt{none} indica nessun messaggio,
    %                          \texttt{all} indica la massima prolissità; altri
    %                          valori sono illustrati nella pagina di manuale
    %                          accessibile con \texttt{man ipsec\_klipsdebug}.\\
    \texttt{plutodebug}    & Stabilisce quale livello di messaggi di debug
                             di \texttt{pluto} deve essere registrato. Se
                             vuoto o con il valore \texttt{none} indica nessun
                             messaggio, \texttt{all} indica la massima
                             prolissità; altri valori sono illustrati nella
                             pagina di manuale accessibile con 
                             \texttt{man ipsec\_pluto} (o \texttt{man
                               pluto}).\\ 
    \texttt{plutostart} &    Richiede l'avvio del demone \texttt{pluto} per
                             IKEv1, può assumere i valori \texttt{yes} e
                             \texttt{no}.\\ 
    \texttt{charonstart} &   Richiede l'avvio del demone \texttt{charon} per
                             IKEv2, può assumere i valori \texttt{yes} e
                             \texttt{no}.\\
    \texttt{nat\_traversal}& Indica se accettare e offrire il supporto per il
                             \itindex{NAT~Traversal} \textit{NAT
                               Traversal}. Prende come valori 
                             \texttt{yes} o \texttt{no} (che è il
                             default). Questo parametro è rispecificabile
                             anche per le singole connessioni. Nel caso di
                             \textit{strongSwan} si applica solo a
                             \texttt{pluto} per IKEv1, il supporto per il
                             \itindex{NAT~Traversal} \textit{NAT Traversal} è
                             automatico con IKEv2.\\ 
    \texttt{keep\_alive} &   Indica in secondi l'intervallo di tempo da usare
                             per l'invio di pacchetti che mantengano attiva la
                             comunicazione sul canale UDP usato dal
                             \itindex{NAT~Traversal} \textit{NAT Traversal}
                             onde evitare di perdere lo 
                             stato della stessa, il default è 20.\\
    \texttt{cachecrls}   &   Indica se deve essere mantenuta in cache la lista
                             dei certificati revocati (CRL), applicabile solo
                             a \texttt{pluto} (per IKEv2 la cache è sempre
                             attiva), i valori possibili sono \texttt{yes} o
                             \texttt{no} (che è il default).\\
    \texttt{crlcheckinterval}& Specifica il tempo, in secondi in cui viene
                             rieseguita la acquisizione della lista dei
                             certificati revocati (applicabile solo
                             a \texttt{pluto}).\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{I principali parametri disponibili nella sezione \texttt{config} di
    \texttt{ipsec.conf}.} 
\label{tab:ipsec_conf_setup}
\end{table}

Il grosso della configurazione si effettua comunque all'interno di sezioni di
tipo \texttt{conn}; ciascuna di esse infatti indica una connessione di rete
che deve essere stabilita attraverso IPSEC, ed è con questa direttiva che si
imposta una VPN, specificando tutti i parametri necessari alla comunicazione
fra i due capi della stessa. Questo significa anche che per ognuna di queste
sezioni presente su un capo della VPN, ci deve una sezione corrispondente nel
file \texttt{ipsec.conf} che sta sulla macchina all'altro capo della
connessione.\footnote{questo ovviamente nell'ipotesi che si usi lo stesso
  software da ambo le parti.}

Un esempio di un paio di sezioni di configurazione per delle connessioni è il
seguente, che si è ottenuto dalla versione di \texttt{ipsec.conf} installata
come scheletro di configurazione di \textit{strongSwan} su una Debian Squeeze,
si sono rimossi i commenti che sono presenti nell'esempio per una maggiore
leggibilità:
\begin{FileExample}[label=ipsec.conf]
# Sample VPN connections

conn sample-self-signed
      left=%defaultroute
      leftsubnet=10.1.0.0/16
      leftcert=selfCert.der
      leftsendcert=never
      right=vpn.truelite.it
      rightsubnet=10.2.0.0/16
      rightcert=peerCert.der
      auto=start

conn sample-with-ca-cert
      left=%defaultroute
      leftsubnet=10.1.0.0/16
      leftcert=myCert.pem
      right=vpn2.truelite.it
      rightsubnet=10.2.0.0/16
      rightid="C=CH, O=Linux strongSwan CN=peer name"
      keyexchange=ikev2
      auto=start
\end{FileExample}

Dato che la configurazione deve essere equivalente sui due capi della
connessione, all'interno di una sezione \texttt{conn} questi non vengono
identificati in termini di locale e remoto (altrimenti occorrerebbe invertire
i ruoli passando da un capo all'altro), ma in termini di \textsl{destra} e
\textsl{sinistra}.  I due parametri principali (ed obbligatori) da impostare
nella creazione di una VPN sono infatti \texttt{left} e \texttt{right}, che
identificano gli indirizzi IP pubblici dei due \textit{security gateway} (vedi
fig.~\ref{fig:VPN_scheme}) fra cui si crea la VPN. Questi devono essere
specificati in notazione dotted decimal oppure con il nome a dominio completo
(FQDN).

Quale dei due capi si usi per indicare la macchina locale e quale la macchina
remota in genere non ha importanza, all'avvio i programmi controllano il
proprio indirizzo IP e sono in grado di identificare nella configurazione
quale fra \textsl{destra} e \textsl{sinistra} è la loro parte. Solo quando
questo non è possibile viene considerato locale \texttt{left} (seguendo la
convenzione mnemonica delle iniziali di \textsl{locale} e \textsl{remoto}).

Si può così configurare la connessione su uno dei due capi e poi copiare la
relativa sezione nel file di configurazione all'altro estremo.  Questo
comporta che un gran numero di parametri di configurazione sono doppi,
esistono cioè nella versione il cui nome inizia con \texttt{left} ed in quella
in cui inizia con \texttt{right}, il loro significato è identico, ma si
applica soltanto al rispettivo capo della connessione. 

Oltre alla indicazione esplicita degli indirizzi IP, si possono usare per
\texttt{left} e \texttt{right} anche dei valori speciali che permettono
un'assegnazione dinamica; ad esempio con il valore \texttt{\%defaultroute} si
assegna automaticamente come indirizzo quello associato all'interfaccia da cui
si esce verso internet. Ovviamente questo può essere usato solo su uno due
capi della VPN, nella configurazione dell'altro si dovrà per forza indicare
l'indirizzo IP pubblico.\footnote{se lo si usa cioè non si avrà più la
  simmetria dei due file di configurazione presenti sui due capi della
  configurazione.}

Con il valore \texttt{\%any} si indica invece che l'indirizzo IP di quel capo
(sottintendendo che si tratta del capo remoto) sarà scelto automaticamente in
fase di connessione. Si usa in genere questo valore per identificare
l'indirizzo di un \textit{road warrior} che si collega verso un concentratore
di VPN, che in genere eseguirà la connessione da IP assegnati dinamicamente da
provider e non noti a priori; in tal caso nella fase di negoziazione delle
chiavi sarà anche acquisito l'IP della macchina remota che verrà
automaticamente utilizzato per l'invio dei pacchetti.\footnote{la
  configurazione standard su un \textit{road warrior} vede cioè l'uso di
  \texttt{\%defaultroute} su un capo (quello locale) per ottenere l'IP
  dinamicamente, e dell'indirizzo del server sull'altro, quest'ultimo invece
  avrà \texttt{\%any} sul capo che identifica il \textit{road warrior} e potrà
  avere \texttt{\%defaultroute} o direttamente l'indirizzo IP sul capo che
  identifica se stesso.}

Un secondo parametro fondamentale è \texttt{leftsubnet} (e l'equivalente
\texttt{rightsubnet}) con cui si specifica la rete privata che sta dietro il
\textit{security gateway}, da indicare in notazione CIDR. Questo parametro
consente di rendere accessibile detta rete dall'altro capo della VPN.  Se non
lo si specifica viene presa come rete il singolo IP specificato con
\texttt{left}, restringendo soltanto ad esso le connessioni via VPN
(normalmente questo è quanto si fa sul lato di un \textit{road warrior}).

Il parametro \texttt{auto} serve invece a stabilire quali operazioni
effettuare all'avvio di IPSEC e corrisponde ad alcune opzioni dell'uso del
comando di controllo \texttt{ipsec auto} che è quello usato per avviare e
fermare manualmente le connessioni; l'uso del valore \texttt{add} aggiunge le
informazioni sulla connessione al database interno di \texttt{pluto}, ma non
avvia la connessione, per farlo infatti occorre indicare il valore
\texttt{start}, il valore di default è invece \texttt{ignore} che non avvia
automaticamente nessuna operazione.

%% 
%% NON USATO
% Un altro parametro di controllo è \texttt{type}; il suo valore di default è
% \texttt{tunnel} che indica il funzionamento di IPSEC in modalità tunnel (vedi
% fig.~\ref{fig:VPN_IPSEC_modes}) per la creazione di una VPN, pertanto
% usualmente non viene neanche specificato. Gli altri valori possibili sono
% \texttt{transport} per l'uso di IPSEC in modalità trasporto per una
% comunicazione punto-punto, \texttt{passthrough} per non usare IPSEC,
% \texttt{drop} per scartare i pacchetti e \texttt{reject} per scartarli con
% l'emissione di un ICMP di errore.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Parametro}&\textbf{Significato}\\
    \hline
    \hline 
    \texttt{left}       & Indica l'indirizzo IP pubblico di uno dei capi
                          della connessione. \\ 
    \texttt{leftsubnet} & Indica la rete privata posta dietro uno dei capi
                          della connessione.\\
    \texttt{leftupdown}&  Indica uno script da lanciare per modificare il
                          routing o le regole di firewall quando la
                          connessione cambia stato, il default usa
                          \texttt{ipsec \_updown}. \\
    \texttt{leftcert}   & Indica il file che contiene il certificato da usare 
                          per la propria identificazione.\\
    \texttt{leftrsasigkey}& Indica la chiave pubblica RSA da usare per la
                          propria identificazione, il valore di default è 
                          \texttt{\%cert} che indica che deve essere estratta
                          da un file (se ne può anche scrivere direttamente il
                          valore).\footnotemark\\
    \texttt{leftsendcert}&Indica le modalità di invio di un certificato
                          all'altro capo a scopo di identificazione, il
                          default è \texttt{ifasked} che lo invia su
                          richiesta, si possono usare anche \texttt{yes} o
                          \texttt{no} (o gli equivalenti \texttt{always} e
                          \texttt{never}), quest'ultimo viene in genere
                          utilizzato quando si usa una identificazione  
                          senza \textit{Certification Authority} in cui si
                          installano esplicitamente le chiavi pubbliche ai due
                          capi della connessione.\\
    \texttt{leftid}     & Indica la modalità con cui si accerta l'identità
                          dell'altro capo, può essere l'indirizzo IP, un nome
                          a dominio completo (se preceduto dal carattere
                          ``\texttt{@}''), o una stringa da confrontare con le
                          informazioni presenti un certificato.\\
    \texttt{authby}     & Indica la modalità di autenticazione usata per
                          l'identificazione dei capi della VPN, il valore di
                          default è \texttt{pubkey}, che indica l'uso di
                          certificati o chiavi asimmetriche, alternativamente
                          si può usare \texttt{secret} (o \texttt{psk}) per
                          l'uso di un segreto condiviso, le versioni recenti
                          supportano ulteriori meccanismi, deprecato per
                          IKEv2.\\ 
    \texttt{leftauth}   & Indica la modalità di autenticazione il cui uso è
                          richiesto sul capo locale della connessione (usare
                          \texttt{rightauth} per il capo remoto), prende gli
                          stessi valori di \texttt{authby}, supportato solo da
                          IKEv2.\\
    \texttt{auto}       & Indica le operazioni da effettuare all'avvio di
                          IPSEC, i valori possibili sono \texttt{ignore} che
                          ignora la connessione, \texttt{add} che la
                          predispone senza avviarla, \texttt{route} che
                          predispone anche il routing e \texttt{start} che la
                          avvia sempre automaticamente. \\ 
    % \texttt{type}       & Indica  la modalità con cui la connessione deve
    %                       essere effettuata. \\ 
    % \texttt{leftnexthop}& Indica l'indirizzo IP del gateway per l'uscita su
    %                       internet qualora l'uscita non sia diretta
    %                       (specificabile con \texttt{\%direct}, il
    %                       default). Specificando \texttt{\%defaultroute} per
    %                       \texttt{left} il suo valore viene sovrascritto. \\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{I principali parametri generali di una sezione \texttt{conn} di
    \texttt{ipsec.conf}.} 
\label{tab:ipsec_conn_general}
\end{table}

\footnotetext{questa funzionalità è fornita per compatibilità con le versioni
  precedenti di FreeS/WAN che non supportavano l'uso di certificati SSL ma
  solo di chiavi RSA; nel caso di \textit{Openswan} questo valore può essere
  ottenuto tramite il comando \texttt{ipsec showhostkey}, non presente in
  \textit{strongSwan}; vista la maggiore chiarezza e semplicità di
  configurazione è comunque consigliato sempre indicare un file contenente la
  chiave pubblica (per la generazione si possono usare i comandi
  \texttt{ssh-keygen} o \texttt{openssl rsa}).}

Una lista degli altri parametri più importanti delle sezioni di tipo
\texttt{conn} è riportata in tab.~\ref{tab:ipsec_conn_general}; un elenco più
dettagliato e completo, con la descrizione dei relativi significati, si trova
al solito nella pagina di manuale di \texttt{ipsec.conf}. Per brevità si sono
riportati solo i parametri ``\texttt{left}'', dando per scontato l'esistenza e
l'equivalenza dei corrispettivi ``\texttt{right}''.

Si tenga presente inoltre che \textit{strongSwan} a partire dalla versione
4.2.1 ha iniziato ad utilizzare un file di configurazione ausiliario,
\index{configurazione!\texttt{/etc/strongswan.conf}}
\texttt{/etc/strongswan.conf}, con una sintassi molto diversa. La
configurazione per l'uso di IPSEC resta in \texttt{ipsec.conf}, ma in questo
file verranno inserite le configurazioni delle varie estensioni fornite del
programma. Al momento è usato principalmente per il demone \texttt{charon}, e
ad esempio nella versione installata su una Debian Squeeze l'unico parametro
impostato è il numero di thread con cui viene fatto partire questo programma.


\subsection{Autenticazione e gestione delle credenziali con IPSEC}
\label{sec:VPN_ident}

Come illustrato in sez.~\ref{sec:VPN_IPSEC} la cifratura e la autenticazione
dei pacchetti di rete del protocollo IPSEC si basa sull'uso di appropriate
chiavi di cifratura con cui questi vengono generati. Se ci si limita a questo
livello (cioè a ESP ed AH) tutto quello che è necessario è fornire al kernel
una di queste chiavi in maniera opportuna, che è quello che può essere fatto,
senza tirare in ballo l'uso di IKE (e quindi anche senza \textit{strongSwan} o
\textit{Openswan}) con il cosiddetto \textit{manual keying}.

In questo caso non si fa scegliere la chiave di sessione ad IKE, ma essa viene
specificata manualmente dall'amministratore impostandola direttamente
attraverso uno \textit{shared secret}. Questa modalità è poco sicura in quanto
per cifrare viene sempre usata la stessa chiave, la scoperta della quale
compromette tutto il traffico presente e passato. Essa deve essere utilizzata
solo se costretti da compatibilità con altre implementazioni di IPSEC che
supportano unicamente questa modalità di funzionamento. Questa modalità non è
supportata da \textit{strongSwan} che suggerisce allo scopo l'uso del comando
\texttt{setkey} degli \texttt{ipsec-tools}.\footnote{con \textit{Openswan} il
  supporto per il \textit{manual keying} è disponibile, ma non lo prenderemo
  neanche in considerazione, essendo questa una modalità di utilizzo insicura,
  scomoda e totalmente sconsigliata.}

L'uso di IKE consente invece di realizzare il cosiddetto \textit{automatic
  keying}, vale a dire impostare in maniera automatica, e cambiare
periodicamente (il cosiddetto \textit{rekeying}), le chiavi di cifratura dei
pacchetti, così da rendere più sicure le comunicazioni. Inoltre nel realizzare
questo procedimento IKE supporta anche le modalità per identificare
opportunamente l'altro capo della connessione, onde evitare la possibilità di
un attacco del tipo \itindex{man-in-the-middle} \textit{man-in-the-middle} (si
riveda quando spiegato in sez.~\ref{sec:crypto_asymmetric}) ed evitare
l'accesso di estranei alle proprie VPN.

Inizialmente il supporto di IKE fornito da FreeS/WAN prevedeva soltanto due
modi per effettuare questo riconoscimento, l'usi di coppie di chiavi RSA
(analoghe a quelle usate da \texttt{ssh}) in cui è necessario scambiare le
chiavi pubbliche fra i due capi della connessione o l'uso di una chiave
condivisa (denominata \textit{Pre-Shared Key} o PSK) che deve essere la stessa
su tutti e due.\footnote{questa chiave non va confusa con lo \textit{shared
    secret} di cui si è parlato a proposito del \textit{manual keying}, in
  questo caso la \textit{Pre-Shared Key} serve solo per determinare
  l'autenticità dei due capi della VPN con IKE e non viene usata per cifrare
  il traffico, per il quale viene comunque usato l'\textit{automatic keying} e
  delle chiavi di sessione gestite dal protocollo che vengono continuamente
  rinnovate.}  In entrambe le modalità tutti i dati privati relativi alla
gestione delle VPN venivano mantenuti nel file
\index{configurazione!\texttt{/etc/ipsec.secrets}} \texttt{/etc/ipsec.secrets}
che per questo deve essere proprietà dell'amministratore ed accessibile solo
da questi. In particolare andavano inserite in questo file le chiavi private
RSA,\footnote{in un opportuno formato testuale; per \textit{Openswan} questo è
  ancora possibile.} o le \textit{Pre-Shared Key}.



%%
%% ROBA OBSOLETA 
%%
% Quest'ultima, che è l'unica che tratteremo, richiede a sua volta di
% specificare la modalità con cui si autenticano i due capi della VPN prima di
% negoziare la chiave di sessione, modalità che viene controllata dalla
% direttiva \texttt{authby}, questa può assumere due valori; quello di default è
% \texttt{rsasig}, che indica l'autenticazione tramite chiavi
% asimmetriche\footnote{e vale anche per l'uso di certificati.} mentre con
% \texttt{secret} si indica l'autenticazione tramite chiave simmetrica, nel qual
% caso quest'ultima dovrà essere specificata come \textit{Pre-Shared Key} in
% \texttt{/etc/ipsec.secrets}, secondo quanto già illustrato in
% sez.~\ref{sec:VPN_ident}.

% Di norma, usando l'autenticazione a chiave asimmetrica per i vantaggi
% illustrati in sez.~\ref{sec:crypto_asymmetric}, non è necessario specificare
% un valore per \texttt{authby}, dato che il valore di default è quello
% corretto, in questo però occorrerà utilizzare altre direttive per identificare
% le chiavi pubbliche dei due capi della VPN,\footnote{si ricordi che questi
%   sono autenticati reciprocamente nell'essere in grado di dimostrare il
%   possesso della rispettiva chiave privata.} che dovranno essere usate per
% l'autenticazione durante la procedura dell'\textit{automatic keying}.


Quando con le implementazioni successive è stata effettuata l'integrazione
delle estensioni che consentono di utilizzare certificati SSL, sia nella forma
si certificati autofirmati (sostanzialmente equivalente all'uso di chiavi RSA,
formato dei file a parte) che di certificati rilasciati da una
\textit{Certification Authority}, il ruolo di \texttt{/etc/ipsec.secrets} come
unica fonte dei dati privati è finito. Visto infatti che chiavi e certificati
vengono in genere mantenuti in file di opportuno formato (ad esempio
\textit{strongSwan} supporta sia il formato testuale PEM che il binario DER)
ormai non è più necessario inserire direttamente i dati delle chiavi private
all'interno di \texttt{/etc/ipsec.secrets},\footnote{con \textit{strongSwan}
  ad esempio questo non è più possibile, e pertanto non lo prenderemo neppure
  in considerazione, essendo molto più semplice ricorrere all'indicazione dei
  file.}  e si può semplicemente usare un riferimento ai file che le
contengono. 

Questo ha fatto sì che una parte dei dati di autenticazione sia stata spostata
nella directory \texttt{/etc/ipsec.d/}, in particolare per quanto riguarda la
possibilità di mantenere in opportune sottodirectory della stessa chiavi e
certificati; quelli dei propri corrispondenti, in caso di certificati
autofirmati, o quelli delle \textit{Certification Authority}, se le si usano.

Oltre a queste modifiche nel caso di \textit{strongSwan} sono stati introdotti
anche ulteriori metodi di autenticazione, cosa che ha comportato altri
cambiamenti. Il formato generale di \texttt{/etc/ipsec.secrets} resta comunque
lo stesso, si tratta in sostanza di una tabella di voci ciascuna delle quali è
composta da una lista di indicatori di selezione, seguiti dalla specificazione
del segreto da usare per gestire le connessioni che li riguardano. Lista e
segreto devono essere separati dal carattere ``\texttt{:}'' seguito o da uno
spazio o da un ritorno a capo, poi dall'identificatore del tipo di segreto (si
sono riportati i valori possibili in tab.~\ref{tab:VPN_ipsec_secrets_keys}) a
sua volta seguito da uno spazio e dall'opportuna indicazione del segreto
stesso.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Identificatore}&\textbf{Significato}\\
    \hline
    \hline 
    \texttt{PSK}  & Un segreto condiviso (\textit{Pre-Shared Key}) da
                    utilizzare come chiave simmetrica su entrambi i capi della
                    connessione, da specificare come stringa di caratteri
                    delimitate da virgolette (sono validi tutti i caratteri
                    tranne il ritorno a capo e le virgolette stesse).\\ 
    \texttt{RSA}  & Una chiave RSA o la chiave di un certificato X.509, da
                    specificare tramite pathname assoluto o come pathname
                    relativo a \texttt{/etc/ipsec.d/certs/}, se la chiave è
                    protetta da password la si può specificare come secondo
                    argomento o richiederne l'immissione da terminale
                    all'avvio con \texttt{\%prompt}.\\ 
    \texttt{ECDSA}& Specifica una chiave privata ECDSA, usa la stessa sintassi
                    usata per \texttt{RSA}.\\
    \texttt{EAP}  & Definisce delle credenziali per l'autenticazione con il
                    protocollo EAP; richiede di specificare una password di
                    autenticazione come stringa di caratteri delimitate da
                    virgolette, deve essere usato come indicatore il nome
                    utente (utilizzabile solo con IKEv2).\\
    \texttt{XAUTH}& Definisce delle credenziali per XAUTH; richiede di
                    specificare una password di autenticazione come stringa di
                    caratteri delimitate da virgolette, deve essere usato come
                    indicatore il nome utente (utilizzabile solo con IKEv2).\\ 
    \texttt{PIN}  & Definisce un PIN da usare per una smartcard, non è
                    previsto l'uso di un indicatore.\\ 
    \hline
  \end{tabular}
  \caption{Identificatori del tipo di segreto utilizzabili all'interno di
    \texttt{ipsec.secrets}.}
\label{tab:VPN_ipsec_secrets_keys}
\end{table}

Ogni voce deve iniziare al margine sinistro del file, ma può proseguire su più
righe, nel qual caso però le righe successive la prima devono essere
rientranti ed indentate. Si possono inserire nel file delle righe di commento
facendole iniziare con il carattere ``\texttt{\#}'', ed inoltre si può
specificare una direttiva \texttt{include} che permette di includere il
contenuto del file specificato, per il nome del quale si può usare anche il
carattere jolly ``\texttt{*}'' che sarà espanso con le regole del
\textit{filename globbing} dalla shell.

Gli indicatori della prima parte di ciascuna voce sono usati per selezionare
quale segreto deve essere usato per identificare i capi di una VPN. Il
significato dei selettori dipende dal tipo di segreto,\footnote{la sintassi
  purtroppo è ambigua e confusa e nasce del sovrapporsi di diversi metodi, ed
  è inoltre pure scarsamente documentata, se non per esempi; si può
  considerare questo file e la sua documentazione come un ottimo esempio di
  come \textsl{non} fare le cose.}  ma per chiavi e certificati indicano gli
indirizzi dei capi corrispondenti possono essere espressi come numeri IP (in
notazione \textit{dotted decimal}) come nome di dominio qualificati (preceduti
dal carattere ``\texttt{@}''). Se si usano le \textit{Pre-Shared Key} non è
consigliabile fare riferimento a nomi a dominio, dato che non è detto che ci
si possa sempre fidare delle risoluzioni del DNS, questo non vale quando si
usano segreti a chiave asimmetrica in quanto in tal caso l'identificazione è
basata direttamente sulla chiave o sul certificato. Per indicare un IP
qualunque si può utilizzare la notazione \texttt{\%any}, anche se per
compatibilità viene supportato con lo stesso significato anche l'indirizzo
\texttt{0.0.0.0}.

Per determinare quale segreto (e relativa modalità di autenticazione) verrà
usato fra quelli indicati in \texttt{/etc/ipsec.secrets} viene cercata una
corrispondenza fra gli indirizzi locale e remoto dei due capi della
connessione con gli indicatori della prima parte di ogni voce, e viene scelta
la corrispondenza più specifica. L'assenza di indicatori implica che la voce
corrisponderà ad una combinazione qualsiasi per gli indirizzi dei capi della
VPN. Un solo indicatore verrà confrontato con l'indirizzo del capo locale (il
ricevente) senza nessun controllo sul capo remoto (il richiedente), qualora ve
ne siano indicati più di uno devono trovare corrispondenza entrambi i capi
della connessione, a meno che non si stia usando una autenticazione a chiave
asimmetrica (RSA) nel qual caso la lista viene interpretata come elenco delle
possibili identità del capo locale e basta che l'indirizzo di questo
corrisponda con uno degli indicatori dell'elenco. 

Per capire meglio il funzionamento delle varie modalità di identificazione dei
capi di una VPN tratteremo più esplicitamente i metodi più usati per la
gestione delle autenticazioni: \textit{Pre-Shared Key}, chiavi RSA e
certificati. Si ricordi che indipendentemente dalla configurazione di VPN
scelta (\textit{road-warrior}, fra reti o fra singole macchine), è comunque
necessario che ciascun \textit{security gateway} possa identificare l'altro e
questo comporta sia la presenza delle proprie credenziali (che nel caso di una
\textit{Pre-Shared Key} coincidono con quelle dell'altro capo) in
\texttt{ipsec.secrets} per farsi autenticare, che l'indicazione di come
identificare l'altro in \texttt{ipsec.conf}.

Benché meno sicuro rispetto agli altri metodi, che non prevedono la necessità
di trasmissione su un canale sicuro della chiave condivisa e la compromissione
di entrambi i lati della comunicazione in caso di intercettazione, l'uso delle
\textit{Pre-Shared Key} è ancora abbastanza comune per la sua semplicità di
configurazione, specie quando ci si deve collegare con altri apparati per i
quali l'uso degli altri metodi potrebbe risultare o più complesso o non
supportato. Per autenticare un corrispondente con questo metodo occorre
indicarne la scelta nella sezione che definisce della connessione in
\texttt{ipsec.conf} con il parametro \texttt{authby=secret}.

In questo caso occorre anche la chiave sia indicata in \texttt{ipsec.secrets}
in una voce di tipo \texttt{PSK} come stringa delimitata da delle virgolette
che può contenere qualunque carattere eccetto le virgolette stesse o un a
capo.\footnote{in questo caso la chiave serve sia ad identificare l'altro capo
  che a farsi identificare.} Un esempio di questo tipo di voci è il seguente:
\begin{FileExample}[label=ipsec.secrets]
# sample /etc/ipsec.secrets file for 10.1.0.1
10.1.0.1 10.2.0.1: PSK "secret shared by two hosts"
                                                                 
# an entry may be split across lines,
# but indentation matters
www.xs4all.nl @www.kremvax.ru
    10.6.0.1 10.7.0.1 1.8.0.1: PSK "secret shared by 5"

# shared key for road warrior
10.0.0.1 0.0.0.0 : PSK "jxTR1lnmSjuj33n4W51uW3kTR55luUmSmnlRUuW..." 
\end{FileExample}

Si tenga presente che, come nell'esempio, si possono avere diverse
\textit{Pre-Shared Key}, specificate in altrettante voci del file, da usare
per VPN fra macchine diverse. In questo caso come accennato la chiave da usare
per una certa connessione viene determinata in base agli IP delle due macchine
ai capi della VPN, cercando una corrispondenza nella lista degli indici
associati a ciascuna chiave.

Questo ha una conseguenza precisa quando si usano le \textit{Pre-Shared Key}
per i \textit{road-warrior}.  In tal caso infatti, dato che l'indirizzo che
essi assumeranno non può essere noto a priori, si dovrà usare nell'indice
l'indirizzo generico, e a questo punto non si potranno usare due chiavi
diverse per due macchine diverse, in quanto non sarebbe più possibile la
risoluzione univoca della chiave da usare. Ciò comporta che per tutti i
\textit{road warrior} è necessario usare la stessa chiave simmetrica, cosa che
rende questa modalità di autenticazione piuttosto debole.

%%
%% OBSOLETO
%%
% Data la criticità intrinseca nell'uso di chiavi simmetriche (si ricordi quanto
% detto in sez.~\ref{sec:crypto_symmetric}) è opportuno scegliere con molta cura
% la chiave. Per questo \textit{Openswan} mette a disposizione un apposito
% comando, \index{comando!\texttt{ipsec ranbits}} \texttt{ipsec ranbits}, che
% permette di generare stringhe casuali di dimensione arbitraria; pertanto si
% possono generare dei valori adatti a queste chiavi con i comandi:
% \begin{Verbatim}[fontsize=\footnotesize,frame=single,samepage=true,
%   xleftmargin=1cm,xrightmargin=1.5cm]
% anarres:~# umask 177
% anarres:~# ipsec ranbits 192  > key
% \end{Verbatim}
% e poi usare il valore preso dal file temporaneo, si noti l'uso di
% \texttt{umask} per evitare la creazione del file con permesso di accesso in
% lettura. 

La seconda modalità di autenticazione è quella basata su chiavi RSA,
identificate dall'omonimo identificatore illustrato in
tab.~\ref{tab:VPN_ipsec_secrets_keys}. In questo caso il possesso della chiave
privata serve soltanto ad identificare noi stessi presso gli altri capi di
tutte le eventuali VPN che si vogliono creare, cui bisognerà distribuire la
nostra chiave pubblica.  L'autenticazione degli altri capi della connessione,
utilizzando un meccanismo a chiave asimmetrica, non sarà più fatta in base al
contenuto di \texttt{ipsec.secrets} (non serve più infatti un segreto
condiviso), ma sarà effettuata sulla base della \textsl{loro} chiave pubblica,
cui dovrà essere associata, dalla loro parte, la relativa chiave privata
mantenuta nel \textsl{loro} file \texttt{ipsec.secrets}. Questo consente di
utilizzare chiavi diverse per ciascun \textit{road warrior}.

Le chiavi possono essere specificate in maniera diversa, a seconda della
modalità utilizzata per definirle. Il parametro principale da usare in
\texttt{ipsec.conf} in questo caso è \texttt{leftrsasigkey} che indica la
chiave pubblica dell'altro capo, inoltre in questo caso non è necessario
assegnare \texttt{authby=pubkey} perché questo è il valore di default. Con
FreeS/WAN occorreva scrivere direttamente la chiave nel file in un opportuno
formato testuale,\footnote{con \textit{Openswan} questo è ancora possibile e
  si può ottenere il valore da inserire all'altro capo usando il comando
  \texttt{ipsec showhostkey} dalla propria parte.} con le versioni più recenti
si usa il valore speciale \texttt{\%cert} e si indica il file da cui leggerla
con \texttt{leftcert}, per cui è sufficiente disporre della chiave in un file
di formato standard.

Allo stesso tempo perché l'altro capo della connessione possa identificarci
sarà necessario specificare la nostra chiave privata in
\texttt{ipsec.secrets}; questo viene fatto con l'indicativo RSA seguito dal
nome del file in cui questa è contenuta.\footnote{con \textit{Openswan} è
  ancora supportata l'indicazione diretta della chiave privata dentro questo
  file con un opportuno formato testuale, non la tratteremo essendo una
  configurazione inutilmente complessa e facilmente soggetta ad errori.}
Questo può essere un pathname assoluto o relativo rispetto a
\texttt{/etc/ipsec.d/private}. Opzionalmente si può indicare come secondo
argomento una password da usare per sbloccare la chiave (se questa è protetta)
o l'uso della parola riservata \texttt{\%prompt} per far effettuare la
richiesta della stessa sulla console all'avvio della VPN. Un esempio di questa
configurazione potrebbe essere il seguente:
\begin{FileExample}[label=ipsec.secrets]
: RSA /etc/ipsec.d/private/hollandKey.pem
\end{FileExample}

%%
%% OBSOLETO
%%
% Qualora si usino delle coppie di chiavi RSA prodotte manualmente tramite il
% comando \texttt{ipsec rsasigkey}, queste devono essere specificate assegnando
% il parametro \texttt{leftrsasigkey} al valore numerico della chiave
% pubblica. Questo valore può essere ottenuto tramite il comando \texttt{ipsec
%   showhostkey}, eseguendolo come:
% \begin{Verbatim}[fontsize=\footnotesize,frame=single,samepage=true,
%   xleftmargin=1cm,xrightmargin=1.5cm]
% anarres:~# ipsec showhostkey --left
%         # RSA 1024 bits   anarres   Thu Apr 29 16:10:21 2004
%         leftrsasigkey=0sAQN5nXw+enIvimav ..... 
% \end{Verbatim}
% che produce direttamente (posto che la chiave sia stata inserita correttamente
% in \texttt{ipsec.secrets}) la riga da piazzare all'interno di
% \texttt{ipsec.conf}. 

Si tenga presente che la configurazione andrà eseguita per entrambi i capi
della VPN, usando le chiavi pubbliche di ciascuno di essi. Di nuovo non
importa quale è la macchina identificata come \texttt{left} e qual'è quella
identificata come \texttt{right}, l'importante è che si assegnino le chiavi
pubbliche in maniera coerente; un errore comune che si aveva quando le chiavi
pubbliche erano scritte direttamente dentro \texttt{ipsec.conf} era quello di
assegnare per sbaglio la chiave pubblica dell'altro capo al proprio capo e
viceversa, con la conseguente impossibilità di stabilire la connessione per la
non corrispondenza alle rispettive chiavi private.

%%
%% OBSOLETO
%% 
%  Si tenga presente inoltre che il comando \texttt{ipsec
%   showhostkey} può generare una voce per \texttt{rightrsasigkey} invece che
% \texttt{leftrsasigkey} se lo si invoca con \texttt{-{}-right}.\footnote{il
%   valore della chiave è sempre lo stesso, derivato dal contenuto di
%   \texttt{ipsec.secrets}, nel risultato cambia soltanto la stringa di
%   identificazione della direttiva.}

% A differenza delle chiavi simmetriche, che possono essere anche scritte a mano
% secondo l'esempio mostrato in precedenza, le chiavi RSA devono essere generate
% opportunamente. Per questo si può usare il comando \texttt{ipsec rsasigkey}
% che genera un file di testo nel formato adatto per l'inclusione in
% \texttt{ipsec.secrets}, il comando vuole come parametro la lunghezza (in
% numero di bit) della chiave, un valore accettabile è 2048.  L'output del
% comando è il seguente:
% \begin{Verbatim}[fontsize=\footnotesize,frame=single,samepage=true,
%   xleftmargin=1cm,xrightmargin=1.5cm]
% havnor:/etc/ipsec.d/private# ipsec rsasigkey 2048 
%         # RSA 2048 bits   anarres   Fri Nov 21 19:09:21 2003
%         # for signatures only, UNSAFE FOR ENCRYPTION
%         #pubkey=0sAQPHy5/ ... ... Q0a0lQQ==
%         Modulus: 0xc7cb9fe ... ... 0d1ad2541
%         PublicExponent: 0x03
%         # everything after this point is secret
%         PrivateExponent: 0x085326a ... ... 972d4413
%         Prime1: 0xf970fd0f ... ... 62f39669
%         Prime2: 0xcd0c7703 ... ... 427b2d19
%         Exponent1: 0xa64b535f5 ... ... 41f7b99b
%         Exponent2: 0x88b2fa027 ... ... d6fcc8bb
%         Coefficient: 0x6a9420bf ... ... 1d2d7000
% \end{Verbatim}
% dove si sono tagliate le righe (che sono troppo lunghe per poter stare nella
% pagina). Si noti che l'output del comando è già indentato e pronto per essere
% inserito dentro \texttt{ipsec.secrets}, che nel caso si sia scelta
% l'autenticazione a chiavi RSA ha la forma:
% \begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm]
% # RSA private key for this host, authenticating it to any other host
% # which knows the public part.  Suitable public keys, for ipsec.conf, DNS,
% # or configuration of other implementations, can be extracted conveniently
% # with "ipsec showhostkey". 
% : RSA   {
%         # yyy
%         }
% # do not change the indenting of that "}"
% \end{Verbatim}
% dove l'output del comando precedente va messo al posto di \texttt{\#yyy}.  Si
% noti inoltre che nel file è presente, commentato nella linea contenente la
% parola chiave \texttt{pubkey}, il valore della chiave pubblica, codificato in
% base-64, a cui è anteposto uno \texttt{0s}, per averlo direttamente nel
% formato usato dentro \texttt{ipsec.conf}. È necessario mantenere i commenti
% quando si fa l'inserimento del valore ottenuto con \texttt{ipsec rsasigkey} in
% quanto questi sono poi utilizzati dal comando \texttt{ipsec showhostkey}.


Con l'uso delle chiavi RSA si ottiene una maggiore robustezza nella gestione
delle singole VPN, in quanto basterà generare una sola di queste chiavi per
ciascun capo di una VPN, e potremo usare detta chiave per tutte le connessioni
con tutti gli altri, distribuendo la relativa chiave pubblica. In questo modo
non sarà necessario distribuire segreti condivisi. L'altro vantaggio è che in
questo caso le configurazioni \textit{road warrior} possono mantenere chiavi
RSA diverse in quanto la scelta di quale chiave usare nella comunicazione sarà
fatta in base alla chiave pubblica che sta sull'altro capo.

Infine se si usa un certificato X.509 per identificare l'altro capo si danno
in sostanza due possibilità. La prima è quella di usare certificati
autofirmati,\footnote{che ad esempio su Debian nel caso di \textit{Openswan}
  vengono generati direttamente dal sistema di \textit{debconf}.} per i quali
occorrerà semplicemente specificare il nome del file nel parametro
\texttt{leftcert}, in forma assoluta o relativa se il certificato è posto
nella directory \texttt{/etc/ipsec.d/certs}. Come per le chiavi RSA si dovrà
aver cura di copiare il proprio certificato anche sull'altro capo e viceversa,
e per entrambi assegnare correttamente sia \texttt{leftcert} che
\texttt{rightcert}.

La comodità dell'uso dei certificati X.509 sta però nella seconda possibilità
che prevede di eseguire l'autenticazione usando una \textit{Certification
  Authority} che garantisce l'autenticità dei certificati senza doverli
trasferire a mano. Se si vuole usare questa funzionalità però occorre definire
quale è il certificato della \textit{Certification Authority} che firma i
certificati usati dalle singole macchine. Questo può essere fatto con il
parametro \texttt{leftca} in \texttt{ipsec.conf}, il cui valore deve essere
assegnato al nome del rispettivo file. In generale però questo non è
necessario, perché se detto parametro non viene definito, verranno usati
automaticamente tutti i certificati che si trovano nella directory
\texttt{/etc/ipsec.d/cacerts}, per cui tutto quel che serve è copiare in tale
directory il certificato della nostra CA.

Questa seconda modalità ha il vantaggio che, come per SSL, basterà distribuire
un solo certificato, quello della CA che ha firmato i certificati dei vari
capi delle connessioni, invece di dover distribuire i singoli certificati
pubblici di ciascuno di essi. In ogni caso si dovrà comunque impostare (con
\texttt{leftcert} o \texttt{rightcert}) quale è il proprio certificato ed
indicare all'interno di \texttt{ipsec.secrets} la corrispondente chiave
privata; cosa che, trattandosi in genere anche in questo caso di chiavi RSA,
si fa esattamente come illustrato in precedenza.



\section{La gestione di VPN con OpenVPN}
\label{sec:fw_openvpn}

Tratteremo in questa sezione una modalità alternativa di realizzare delle VPN
che non si basa su un protocollo che opera direttamente a livello di rete come
IPSEC, e che per questo deve essere implementato nel kernel, ma viene
realizzata a livello di applicazione da un apposito programma in user space.
Pur esistendo diversi programmi in grado di fare questo\footnote{esempi sono
  \texttt{vtun} o \texttt{cipe}, che presentano però presentano mancanze
  notevoli sul lato crittografico, come rilevato da Peter Gutmann in
  \url{http://www.cs.auckland.ac.nz/~pgut001/pubs/linux_vpn.txt}.}  abbiamo
scelto di concentrarci su \textit{OpenVPN} per l'utilizzo di una tecnologia
standard ed ampiamente consolidata come SSL/TLS, da cui deriva una notevole
robustezza ed affidabilità dell'implementazione.


\subsection{Introduzione}
\label{sec:fw_openvpn_intro}

Abbiamo accennato in sez.~\ref{sec:VPN_linux_IPSEC} come l'uso di FreeS/Wan
presentasse delle notevoli complessità sia sul piano dell'installazione che su
quello amministrativo.  FreeS/Wan inoltre implementava direttamente la
gestione del routing dei pacchetti uscenti dal tunnel IPSEC, appesantendo la
configurazione del servizio, ed introducendo una distinzione innaturale fra
connessioni dirette fra i due \textit{security gateway} (che devono essere
impostate a parte) e connessioni fra le reti che stanno dietro di essi.  Anche
se con le implementazioni più recenti tutto questo si è semplificato
notevolmente resta il fatto che si deve gestire esplicitamente la eventuale
presenza di NAT ed una complessità di configurazione non trascurabile.

Per questi motivi l'utilizzo di un programma in user space può risultare
notevolmente semplificato, sia per quanto riguarda l'attraversamento di un
firewall, sia per i dettagli implementativi, che non necessitano più di una
implementazione all'interno del kernel, ma possono appoggiarsi direttamente a
tutte le librerie e le funzionalità che sono disponibili in user space. 

Il principio di \textit{OpenVPN} è quello di utilizzare l'infrastruttura delle
interfacce \texttt{tun/tap} del kernel, una funzionalità che consente di
creare delle interfacce \textsl{virtuali} sulle quali i pacchetti ricevuti,
invece che da un dispositivo fisico, arrivano da un programma, al quale poi
vengono mandati tutti i pacchetti inviati sulla stessa interfaccia. 

In questo modo si può realizzare una VPN utilizzando due applicazioni che
dialogano fra loro con la normale interfaccia dei socket, ed il cui solo
compito è cifrare opportunamente tutto il traffico che vedono arrivare da
questa interfaccia per inviarlo sul socket, e rimandare indietro alla stessa
interfaccia, dopo averlo decifrato, il traffico che invece ricevono dal
socket.  Si otterrà così che i pacchetti inviati in ingresso su una
interfaccia su un capo della VPN compariranno in uscita sulla corrispondente
interfaccia sull'altro capo, secondo lo schema di
fig.~\ref{fig:VPN_openvpn_schema}. 

\begin{figure}[htb]
  \centering \includegraphics[width=10cm]{images/openvpn}
  \caption{Schema di funzionamento di una VPN basata su OpenVPN.} 
  \label{fig:VPN_openvpn_schema}
\end{figure}

Come si vede il concetto è tutto sommato molto semplice, l'unico problema di
questo approccio è quello di una opportuna gestione del canale cifrato. 
OpenVPN ha risolto questo problema utilizzando dei socket UDP per l'invio dei
dati attraverso internet e SSL/TLS come protocollo per la autenticazione degli
estremi del tunnel e per lo scambio delle chiavi per la cifratura degli
stessi. 

La scelta di UDP è naturale in quanto i pacchetti inviati su una VPN
implementano in sostanza una comunicazione a livello di rete facendo passare
sul canale pacchetti IP generici, e UDP è il protocollo del livello di
trasporto più vicino ad IP. L'uso di TCP per un tale lavoro infatti può
portare a dei problemi di prestazione notevoli, in quanto le funzionalità che
ne garantiscono le caratteristiche di affidabilità sono pensate per essere
usate direttamente sopra IP, se queste vengono ripetute all'interno di un
altro stream TCP si possono avere degli effetti di interferenza che possono
portare ad una forte degradazione del traffico e anche alla caduta delle
connessioni.\footnote{una spiegazione molto chiara del perché è una cattiva
  idea fare una trasmissione di pacchetti TCP incapsulati su TCP si trova su
  \url{http://sites.inka.de/sites/bigred/devel/tcp-tcp.html}.}

La scelta di SSL/TLS è quello che rende superiore OpenVPN rispetto a molte
altre implementazioni finora effettuate con lo stesso criterio.  Programmi
come \texttt{vtun} o \texttt{cipe} infatti hanno reimplementato un proprio
modello di sicurezza che in analisi successive si è dimostrato essere molto
debole; SSL/TLS invece è un protocollo di crittografia ed autenticazione la
cui validità è stata verificata sul campo in anni di studio e di utilizzo, che
pertanto rende OpenVPN pienamente affidabile sul piano della sicurezza.

Un'altra caratteristica notevole di OpenVPN è la sua disponibilità per una
grande quantità di piattaforme diverse; in sostanza è stato portato su tutti
gli Unix conosciuti e pure su Windows (a partire da Windows 2000), è pertanto
molto semplice creare VPN anche con macchine che utilizzano sistemi operativi
diversi; questo rende la soluzione estremamente flessibile e facilmente
dispiegabile anche in ambienti eterogenei.

Data la maggiore semplicità dell'implementazione ed anche un sostanziale
vantaggio sul piano della sicurezza non dovendo operare a livello del kernel,
ci si può chiedere che senso abbia utilizzare ancora i derivati di FreeS/Wan
ed un protocollo complesso come IPSEC. Un tempo uno degli svantaggi maggiori
era la necessità di utilizzare una istanza diversa del programma per ciascun
canale cifrato, ciascuna con un suo file di configurazione separato, cosa
assai poco appetibile dal punto di vista dell'amministrazione (è in genere più
gradito avere un singolo file di configurazione per ciascun servizio). Questo
problema però non sussiste più con la versione 2.0 che consente di gestire con
una sola istanza quanti canali si vogliono.

In realtà oggi la sola ragione a favore dei derivati di FreeS/Wan resta quella
dell'interoperabilità. Benché OpenVPN sia ampiamente portabile e sia stato
portato anche su molti router (ad esempio dal progetto OpenWRT), il vantaggio
dell'uso di un protocollo standard come IPSEC consente di interagire con
qualunque apparato che supporti lo standard, comprese implementazioni diverse
dello stesso, come quelle presenti su router e firewall hardware su cui non si
è in grado di installare OpenVPN. Qualora non si abbia questa necessità si può
tranquillamente utilizzare OpenVPN risparmiandosi la complessità di gestione
di IPSEC.


\subsection{Installazione e configurazione di base}
\label{sec:fw_openvpn_config}

L'installazione di OpenVPN è estremamente semplice, anche perché viene fornito
già pacchettizzato dalle principali distribuzioni;\footnote{ad esempio Debian
  fornisce direttamente il pacchetto \texttt{openvpn}.} inoltre il progetto
fornisce pacchetti già pronti e l'installazione dai sorgenti è immediata segue
la procedura standard dei classici \texttt{./configure; make; make install}.

Per quanto riguarda l'utilizzo OpenVPN può essere invocato direttamente a linea
di comando, specificandone le relative opzioni, e, con l'eccezione delle
opzioni utilizzate per la gestione delle chiavi, il programma verrà
automaticamente eseguito in background, funzionando come un qualunque demone.
Per ciascun canale cifrato si dovrà lanciare una istanza del programma,
assegnandone opportunamente le porte da utilizzare. 

Con la versione 2.x è diventato possibile utilizzare il programma in modalità
server (vedi sez.~\ref{sec:VPN_openvpn_server}), in cui più client si
collegano ad una sola istanza dello stesso.  Questo comporta una procedura di
configurazione leggermente diversa rispetto alla configurazione classica
ereditata della versione 1.x, che comunque resta utilizzabile.  Inoltre nel
Novembre 2004 OpenVPN 2.0 ha ottenuto dalla IANA l'assegnazione ufficiale
della porta 1194 per il funzionamento in modalità server.

Tutte le opzioni di configurazione si possono specificare sia direttamente a
linea di comando, come opzioni estese (cioè precedute da un \texttt{-{}-}),
che all'interno di un file di configurazione, in tal caso si potrà usare come
direttiva il nome dell'opzione, omettendo il \texttt{-{}-} iniziale.
L'opzione che permette di specificare un file di configurazione è
\texttt{-{}-config} che richiede si fornisca come parametro il nome dello
stesso, questa può essere ripetuta anche all'interno del file di
configurazione stesso, consentendo una nidificazione (che comunque è limitata
ad un numero ragionevole di livelli). 

Dato che alla fine l'uso di un file di configurazione rende la gestione molto
più semplice rispetto ad dover specificare un gran numero di opzioni a riga di
comando, da qui in avanti faremo riferimento alle opzioni di configurazione
nella loro forma di direttive. 

In genere con il pacchetto \texttt{openvpn} viene installato anche un
opportuno script di avvio che permette di avviare automaticamente più canali,
creati con altrettanti file di configurazione. Lo script legge il contenuto
della directory \index{configurazione!\texttt{/etc/openvpn/}}
\texttt{/etc/openvpn} e lancia una istanza del programma per ogni file con
estensione \texttt{.conf} che trova in tale directory, passandogli lo stesso
come file di configurazione.

L'installazione di default non configura nessun canale e lascia la directory
\texttt{/etc/openvpn} vuota, questo significa che di default il servizio non
verrà attivato. Per poter avviare il servizio occorrerà creare almeno un file
di configurazione. Con il progetto vengono distribuiti una serie di file di
esempio,\footnote{su Debian sono installati in
  \texttt{/usr/share/doc/openvpn/example/sample-config-files/}.} relativi a
diverse configurazioni della rete, che possono essere utilizzati come
scheletri, adattandoli alle proprie esigenze.

Le direttive del comando si possono dividere sommariamente in varie classi, la
prima delle quali è quella delle direttive relative alla gestione del tunnel,
che permettono di controllare le proprietà di quest'ultimo e le modalità della
sua creazione. Alcune di queste sono fondamentali e devono essere sempre
specificate per poter utilizzare il programma.

La direttiva \texttt{dev} indica quale tipo di interfaccia virtuale usare per
creare il canale, ed i valori possibili sono \texttt{tap}, per
l'incapsulamento su Ethernet e \texttt{tun} per l'incapsulamento su IPv4. Il
tipo deve essere lo stesso su entrambi i capi della VPN, e se lo si indica
senza specificare un numero di interfaccia viene utilizzata la prima
disponibile, altrimenti l'assegnazione può essere fatta in maniera statica; ad
esempio con ``\texttt{dev tun0}'' si richiede esplicitamente l'uso
dell'interfaccia \texttt{tun0}.

La direttiva \texttt{ifconfig} permette di configurare le interfacce ai due
capi del tunnel; i parametri da specificare cambiano a seconda che si sia
usato una interfaccia di tipo \texttt{tun} o di tipo \texttt{tap}. Nel primo
caso si devono specificare gli indirizzi IP ai due capi del tunnel, come si
farebbe con le interfacce \texttt{ppp0} per i due capi di un collegamento
punto-punto via modem.

Nel secondo caso invece si va ad operare direttamente a livello di protocollo
Ethernet, e si deve quindi specificare un indirizzo IP e la relativa netmask.
Questi verranno associati all'interfaccia \texttt{tap} esattamente come se si
trattasse una interfaccia Ethernet ordinaria che si affaccia su una rete
locale connessa tramite la VPN. Si tenga presente che questo deve essere fatto
solo per un client che si collega dall'esterno in VPN, che a questo punto
potrà inviare pacchetti ethernet sulla interfaccia \texttt{tap} come se questa
fosse una scheda connessa, tramite OpenVPN, allo switch della LAN.

Perché questo funzioni dal lato del server che si affaccia su una LAN si dovrà
in questo caso adottare una configurazione diversa, in quanto per poter
reinviare i pacchetti che arrivano dall'interfaccia \texttt{tap} sulla rete
locale questa dovrà essere unita alla interfaccia ethernet che su di essa si
affaccia con un \textit{bridge}, scruttando il relativo supporto e creando
quest'ultimo con il comando \texttt{brctl}.  Questo permette ad esempio di
mantenere entrambi i lati della VPN sulla stessa rete, e di far passare sul
canale cifrato quest'ultimo anche i protocolli di livello più basso (ad
esempio si potrà usare un DHCP remoto attraverso la VPN). 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Direttiva}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{local}   & indica l'indirizzo IP locale su cui far ascoltare il
                       tunnel, se non specificato ascolta su tutti gli
                       indirizzi disponibili su tutte le interfacce di rete.\\
    \texttt{remote}  & indica l'indirizzo IP dell'altro capo del tunnel.\\
    \texttt{proto}   & specifica il protocollo da utilizzare per la creazione
                       del canale; il default è \texttt{udp}, ma se si vuole
                       usare TCP allora occorrerà usare \texttt{tcp-client}
                       sul capo del tunnel che inizia la connessione e
                       \texttt{tcp-server} sull'altro capo che resterà in
                       ascolto (è comunque sconsigliabile usare TCP).\\
    \texttt{shaper}  & impone una limitazione, specificata in byte al secondo,
                       sul traffico che può passare attraverso il canale.\\
    \texttt{ifconfig}& specifica due IP assegnati ai due capi del tunnel, il
                       primo è l'IP locale, il secondo quello remoto.\\
    \texttt{port}    & specifica la porta da utilizzare per la comunicazione
                       su internet, qualora si vogliano specificare due porte
                       diverse per il capo locale e quello remoto si possono
                       usare le opzioni \texttt{lport} e \texttt{rport}.\\
    \texttt{nobind}  & non effettua il binding ad una specifica porta usando
                       la porta effimera data dal kernel.\\
    \texttt{dev}     & specifica l'interfaccia di rete da usare per creare il
                       canale (assume i valori \texttt{tun} o \texttt{tap}).\\
    \texttt{user}    & imposta l'utente per conto del quale deve essere
                       eseguito il demone una volta completata
                       l'inizializzazione, in modo da rilasciare i privilegi
                       non necessari. \\
    \texttt{group}   & analoga ad \texttt{user} per impostare il gruppo. \\
%    \texttt{chroot}  & . \\
    \texttt{log}     & imposta un file sul quale eseguire il log dei messaggi
                       del demone. \\
    \texttt{verb}    & imposta la prolissità dei messaggi di log. \\
   \hline
  \end{tabular}
  \caption{Le principali direttive di \texttt{openvpn} relative alla gestione
    del tunnel.} 
  \label{tab:VPN_openvn_tunnel_opt}
\end{table}

Una terza direttiva fondamentale, che deve essere specificata per almeno uno
dei due capi del tunnel, è \texttt{remote}, che serve a indicare l'indirizzo
IP a cui è possibile contattare (passando attraverso internet) l'altro capo.
Non specificarla significa che \texttt{openvpn} accetterà connessioni da
qualunque indirizzo, previa autenticazione dell'altro capo con uno dei vari
metodi supportati, permettendo così configurazioni \textit{road warrior} in
cui un capo della VPN (quello che non la usa) è quello fisso, e l'altro può
porsi in contatto con lui attraverso appunto questa direttiva.

Altre direttive utili sono \texttt{log} che specifica un file su cui salvare i
messaggi del demone e \texttt{verb} che indica un livello di
\textsl{prolissità} degli stessi; in tab.~\ref{tab:VPN_openvn_tunnel_opt} si
sono comunque riportate le direttive per la gestione del tunnel maggiormente
utilizzate; l'elenco completo, insieme ai dettagli dei parametri possibili e
del loro significato si trova al solito nella pagina di manuale del comando,
accessibile con \texttt{man openvpn}.

Una seconda classe di direttive è quella che riguarda le modalità per gestire
l'autenticazione dei due capi della VPN e la trasmissione dei dati cifrati sul
canale. OpenVPN supporta due modalità di funzionamento, la prima è quella più
elementare e prevede dell'uso di una chiave statica condivisa fra i due capi
della connessione, che viene usata sia per autenticare gli stessi che per
cifrare i dati.

In questo caso si ha il vantaggio di una configurazione immediata, basta
infatti indicare nella configurazione di ciascun estremo quale è il file
contenente la chiave condivisa con l'uso della direttiva \texttt{secret}.  Per
gli ovvi motivi affrontati in sez.~\ref{sec:crypto_symmetric} ogni canale avrà
bisogno di una chiave diversa. Data la criticità della chiave questa deve
essere generata direttamente con il programma stesso invocandolo come:
\begin{Command}
monk:~# openvpn --genkey --secret chiave.key
\end{Command}
che genererà un file \texttt{chiave.key} con un contenuto del tipo:
\begin{FileExample}[label=chiave.key]
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
f6703eb17814284ef14df4fb1cf79f42
1b5718e1c86a0c16d06b8a5d4901a88d
4ed0f5fb9393cf858653daa4ed6ab65d
ec6ede77ec657ca11be448b7572ccb0b
... 
... 
6126425a3f4fff2f1f9743c7fd44d647
ce5058749cc4a01caaa9dd7de82fd8e7
-----END OpenVPN Static key V1-----
\end{FileExample}

La configurazione in questo caso è immediata, in quanto basta avere una
modalità sicura di copiare il file su entrambi gli estremi della VPN per avere
un canale cifrato funzionante, questo però indebolisce la sicurezza
complessiva del sistema, in quanto si deve comunque eseguire la copia di un
file che è noto su entrambe le macchine, ed utilizzando una chiave di
cifratura che non viene mai cambiata (se non manualmente) ci espone, in caso
di furto della stessa, alla possibilità che tutto il traffico (compreso quello
precedente al furto) possa essere decifrato. 

Per questo si usa in genere questo metodo in fase di test, e poi si passa al
secondo metodo di autenticazione è quello basato sull'uso di SSL/TLS. In tal
caso tutta la problematica di negoziazione e scambio della chiave per la
cifratura del canale viene gestita da OpenVPN attraverso una sessione TLS, che
permette sia di autenticare i due capi della connessione che di creare un
canale di controllo su cui scambiare le chiavi di sessione usate per cifrare
il canale dei dati.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Direttiva}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{secret}    & specifica il file che contiene la chiave statica
                         condivisa utilizzata per la cifratura del canale.\\
    \texttt{cert}      & specifica il file contenente il certificato locale 
                         firmato (in formato PEM).\\
    \texttt{key}       & specifica il file contenente la chiave del
                         certificato locale (in formato PEM).\\
    \texttt{ca}        & specifica il file contenente il certificato della
                         \textit{Certification Authority} che firma i
                         certificati locali (in formato PEM).\\
    \texttt{dh}        & specifica il file contenente i parametri necessari per
                         la procedura di \itindex{Diffie-Hellman}
                         \textit{Diffie-Hellman} sul lato 
                         \texttt{tls-server} (in formato PEM).\\ 
    \texttt{pkcs12}    & specifica il file che contiene il certificato locale,
                         la relativa chiave ed il certificato della CA che li
                         firma in formato PKCS12.\\
    \texttt{tls-server}& abilita l'uso di SSL/TLS e facendo assumere al capo
                         corrente il ruolo di server nella negoziazione.\\
    \texttt{tls-client}& abilita l'uso di SSL/TLS e facendo assumere al capo
                         corrente il ruolo di client nella negoziazione.\\
    \texttt{tls-auth}  & abilita una protezione da attacchi
                         \itindex{Denial~of~Service~(DoS)} DoS richiedendo
                         una autenticazione (a chiave condivisa) prima di
                         iniziare la negoziazione SSL/TLS.\\
    \texttt{askpass}   & richiede la password della chiave del certificato
                         locale prima di eseguire il demone (solo da riga di
                         comando).\\
    \texttt{reneg-sec} & specifica ogni quanti secondi rinegoziare le chiavi 
                         di sessione (analoghi sono \texttt{reneg-pkts} e
                         \texttt{reneg-bytes}).\\  
    \texttt{comp-lzo}  & abilita un algoritmo di compressione dei dati sul
                         canale. \\ 
    \texttt{status}    & scrive lo stato delle operazioni sul file passato
                         come argomento; prende un secondo argomento opzionale
                         per indicare la frequenza di scrittura in secondi.\\
   \hline
  \end{tabular}
  \caption{Le principali opzioni di \texttt{openvpn} relative alla gestione
    dell'autenticazione e della cifratura.}
  \label{tab:VPN_openvn_crypto_opt}
\end{table}

Per poter utilizzare questa funzionalità ogni capo della comunicazione deve
poter disporre di un suo certificato e della relativa chiave, firmati dalla
stessa \textit{certification authority}. Ciascun capo della connessione
verificherà che il certificato presentato dall'altro capo sia debitamente
firmato, e se il controllo riesce a questo punto l'autenticazione sarà
considerata ottenuta e si procederà con lo scambio delle chiavi di sessione.

Il primo passo per utilizzare la modalità SSL/TLS è quello di designare quale
dei due capi assumerà il ruolo di server e quale quello di client (nella
modalità tradizionale questi ruoli servono solo allo scopo della creazione del
canale di controllo su TLS, la trasmissione dei dati è sempre punto-punto).
Questo deve essere utilizzando rispettivamente le direttive
\texttt{tls-server} e \texttt{tls-client} sui due estremi della VPN.

Il passo successivo è ottenere tutti i certificati necessari per i due capi,
le relative chiavi ed il certificato della \textit{Certification Authority}
usata per stabilirne la validità (per le problematiche relative si consulti
sez.~\ref{sec:pki_certificates}). Una volta che questi siano disponibili
basterà indicarli nella configurazione utilizzando le direttive \texttt{cert},
\texttt{key} e \texttt{ca}, ciascuna delle quali vuole come parametro il nome
del rispettivo file in formato PEM.

Un'altra direttiva necessaria, ma solo sul lato server dell'autenticazione
TLS, è \texttt{dh}, che specifica i parametri di \itindex{Diffie-Hellman}
\textit{Diffie-Hellman}\footnote{sono i parametri necessari ad ottenere la
  chiave di sessione con la procedura di \textit{Diffie-Hellman} attivando il
  meccanismo della \textit{Perfect Forward Security}, che assicura che anche
  se un attaccante venisse in possesso della chiave di uno dei certificati,
  non sarebbe in grado di decifrare il traffico precedente.}, un riassunto
delle altre principali opzioni di configurazione di questa classe è stato
riportato in tab.~\ref{tab:VPN_openvn_crypto_opt}, al solito l'elenco completo
è nella pagine di manuale.

Una terza classe di opzioni riguarda la capacità di eseguire delle operazioni
ausiliarie da compiere nell'atto di attivare la VPN, come la possibilità di
lanciare una serie di script ausiliari. In particolare sono definiti 5 momenti
diversi, lungo la creazione di un canale, in cui il programma può eseguire
degli script esterni in grado di compiere operazioni di appoggio. Questi sono
riportati nell'ordine nelle prime cinque righe di
tab.~\ref{tab:VPN_openvn_other_opt}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Direttiva}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{up}      & esegue il comando di shell passato come parametro una
                       volta aperte con successo le interfacce del tunnel. \\
    \texttt{tls-verify}& esegue il comando shell passato come parametro prima
                       della verifica dell'autenticità dell'altro capo della
                       connessione (eseguita con SSL/TLS).\\
    \texttt{ipchange}& esegue il comando shell passato come parametro dopo
                       l'autenticazione della connessione o quando un
                       indirizzo remoto è cambiato.\\
    \texttt{route-up}& esegue il comando shell passato come parametro dopo
                       che sono state aggiunte le rotte alla tabella di
                       routing.\\ 
    \texttt{down}    & esegue il comando di shell passato come parametro dopo
                       chiusura delle interfacce del tunnel. \\
    \texttt{route-delay}& attende il numero di secondi passato come parametro
                       prima di inserire le rotte nella tabella di routing (un
                       valore nullo, il default, indica l'inserimento
                       immediato).\\
    \texttt{route-gateway}& usa l'indirizzo passato come parametro come valore
                       di default per il gateway di una rotta impostata con
                       \texttt{route}.\\
    \texttt{route}   & aggiunge una voce alla tabella di routing una volta che
                       è stata realizzata una connessione.\\
    \texttt{mktun}   & permette di creare un tunnel persistente (che viene
                       mantenuto anche se OpenVPN non è attivo).\\
    \texttt{rmtun}   & rimuove un tunnel permanente.\\
   \hline
  \end{tabular}
  \caption{Altre opzioni di controllo di \texttt{openvpn}.} 
  \label{tab:VPN_openvn_other_opt}
\end{table}

La configurazione più comune usando OpenVPN nella modalità tradizionale è, una
volta stabiliti gli indirizzi dei due capi del tunnel con \texttt{ifconfig},
quella di utilizzare \texttt{up} per lanciare uno script non appena il canale
si è attivato, che stabilisca le opportune rotte statiche all'avvio della VPN,
in modo da usare i due capi del tunnel come gateway per le rispettive reti
private. Questa, come le altre direttive di esecuzione, prendono come
parametro il nome di un comando esterno che di norma è uno opportuno script di
shell che verrà eseguito nel momento indicato in
tab.~\ref{tab:VPN_openvn_other_opt}.

Al momento dell'esecuzione al comando esterno saranno passati una serie di
argomenti che specificano le proprietà del tunnel; questi dipendono dal tipo
di dispositivo che si è indicato con \texttt{dev}, nel caso di \texttt{tun}
saranno passati nell'ordine: il nome dell'interfaccia del tunnel, la MTU della
stessa, la MTU del collegamento, l'indirizzo IP locale assegnato al tunnel e
l'indirizzo IP remoto; nel caso invece si sia usata una interfaccia
\texttt{tap} saranno passati il nome dell'interfaccia, la MTU della stessa, la
MTU del collegamento, l'indirizzo IP e la netmask del tratto di rete
utilizzato. In entrambi i casi si potranno usare gli argomenti per eseguire
(all'interno dello script) gli opportuni comandi per impostare l'instradamento
dei pacchetti attraverso il tunnel.

Oltre all'uso di comandi esterni OpenVPN supporta anche una serie di direttive
che fanno eseguire alcune operazioni direttamente al programma stesso. Fra
queste una delle più importanti è \texttt{route} che permette di far impostare
direttamente ad \texttt{openvpn} ulteriori rotte statiche una volta che la
connessione viene stabilita, senza dover ricorrere all'uso di un comando
esterno lanciato con \texttt{up}.

La direttiva prende come primo parametro obbligatorio un indirizzo IP, che può
essere di una singola macchina o di una rete, nel qual caso occorrerà
aggiungere come secondo parametro la maschera di rete ed eventualmente un
gateway per la stessa. Se non si specifica un gateway il default è di usare
l'indirizzo associato al tunnel (quello specificato dal secondo parametro di
\texttt{ifconfig}) oppure quello impostato con la direttiva
\texttt{route-gateway}. In questo modo diventa possibile, all'attivazione di
un tunnel, inserire automaticamente la rotta per gli indirizzi della rete che
si trova dietro l'altro capo dello stesso.

Collegata a questa direttiva è anche \texttt{route-delay} che stabilisce il
numero di secondi (passato come parametro) da aspettare prima di aggiungere
una rotta alla tabella di routing. Normalmente queste vengono inserite
immediatamente dopo l'apertura del dispositivo di rete (TAP o TUN che sia) e
l'esecuzione dello script indicato da \texttt{up}, ma prima che vengano ceduti
i privilegi di amministratore secondo quanto specificato dalle direttive
\texttt{user} e \texttt{group}. In certi casi però\footnote{ad esempio quando
  si usa il DHCP per ottenere un indirizzo sul dispositivo TAP, o su Windows
  per l'inizializzazione dell'adattatore TAP-Win32.} è necessario attendere un
certo lasso di tempo, che può essere indicato da questa direttiva.

Un esempio tipico di file di configurazione tradizionale di un tunnel per una
VPN basata su chiavi condivise è il seguente, che fa riferimento al capo
\textsl{statico} della connessione, cioè quello che è posto su un indirizzo
fisso, anche se in realtà non è necessario che l'indirizzo IP sia statico, è
sufficiente che esso sia raggiungibile in maniera certa dalla macchina
sull'altro capo tramite la direttiva \texttt{remote} (cosa che si può ottenere
anche usando un servizio di DNS dinamico):
\begin{FileExample}[label=openvpn.conf]
# Use a dynamic tun device. 
dev tun
# 10.1.0.2 is our local VPN endpoint (home). 
# 10.1.0.1 is our remote VPN endpoint (office). 
ifconfig 10.1.0.2 10.1.0.1
# Our up script will establish routes
# once the VPN is alive. 
up ./simone.up
# Our pre-shared static key
secret simone.key
# OpenVPN 2.0 uses UDP port 1194 by default
; port 1194
# Verbosity level. 
# 0 -- quiet except for fatal errors. 
# 1 -- mostly quiet, but display non-fatal network errors. 
# 3 -- medium output, good for normal operation. 
# 9 -- verbose, good for troubleshooting
verb 3
\end{FileExample}
si noti come con \texttt{dev} si sia scelto l'interfaccia di tipo TUN per
usare l'incapsulamento su IP, poi si siano impostati gli indirizzi del tunnel
con \texttt{ifconfig} ed usato \texttt{up} per invocare uno script di
inizializzazione che si incarichi di impostare la rotta statica per
raggiungere la rete privata dietro la nostra macchina. Con \texttt{secret} si
è indicato il file su cui è salvata la chiave di accesso, e con \texttt{port}
la porta da utilizzare (ogni tunnel dovrà usarne una diversa). Infine si è
abilitato un adeguato livello di logging.

In corrispondenza alla precedente configurazione, quello che segue è
l'estratto del file utilizzato sulla macchina all'altro capo del tunnel, che
le consente di collegarsi (in questo caso da qualunque indirizzo) alla VPN:
\begin{FileExample}[label=openvpn.conf]
# Use a dynamic tun device. 
dev tun
# Our OpenVPN peer is the office gateway. 
remote holland.truelite.it
# 10.1.0.2 is our local VPN endpoint (home). 
# 10.1.0.1 is our remote VPN endpoint (office). 
ifconfig 10.1.0.21 10.1.0.22
# Our up script will establish routes
# once the VPN is alive. 
up ./simone.up
# OpenVPN 2.0 uses UDP port 1194 by default
; port 1194
# Verbosity level. 
# 0 -- quiet except for fatal errors. 
# 1 -- mostly quiet, but display non-fatal network errors. 
# 3 -- medium output, good for normal operation. 
# 9 -- verbose, good for troubleshooting
verb 3
\end{FileExample}
e come si può notare la sola differenza è che gli indirizzi di
\texttt{ifconfig} sono invertiti di ruolo, e che in questo secondo caso,
essendo su una macchina senza indirizzo prestabilito, si è specificato con
\texttt{remote} l'indirizzo dell'altro estremo della connessione. Si noti come
queste configurazioni non facciano uso della direttiva \texttt{route},
affidandosi a degli script esterni.

Quelle appena illustrate sono le configurazioni per la creazione di un tunnel,
ma occorrerà prevedere anche una opportuna configurazione del firewall che
consenta di far passare i pacchetti relativi al traffico eseguito sul canale
cifrato. Per questo, assunto che OpenVPN sia attivo sul firewall stesso, oltre
al traffico diretto del tunnel, si dovrà anche consentire il traffico dalla
rete interna verso le interfacce del tunnel e viceversa. Un insieme di regole
necessarie al funzionamento di OpenVPN in modalità punto-punto è il seguente:
\begin{FileExample}[label=firewall.sh]
iptables -A INPUT -p udp --dport 1194 -m state --state NEW -j ACCEPT
iptables -A INPUT -i tun+ -m state --state NEW  -j ACCEPT
iptables -A FORWARD -i tun+ -m state --state NEW -j ACCEPT
\end{FileExample}
dove è dato per scontato che si accettino i pacchetti in stato
\texttt{ESTABLISHED} e \texttt{RELATED} e si è assunta una sola istanza che
lavora sulla porta standard. La prima regola permette di accettare le
connessioni per il funzionamento del tunnel e le altre due consentono le
connessioni verso la macchina locale e verso la rete locale attraverso il
tunnel.  Ovviamente in presenza di più istanze si dovranno aprire le
ulteriori porte da esse utilizzate.

Come accennato in precedenza quando si opera con OpenVPN in modalità
punto-punto ci sono una serie di operazioni che devono essere compiute al di
fuori dal programma tramite gli opportuni script.  Tratteremo queste
operazioni nel caso particolare di una VPN realizzata con l'interfaccia
\texttt{tun} illustrato dai due estratti di file di configurazione; l'uso di
\texttt{tap} infatti è normalmente più complesso e meno performante dovendo
costruire un livello di incapsulamento in più.

Una volta che si è creato un tunnel IP tutto quello che si ha è una
comunicazione cifrata fra i due estremi della VPN che si scambiano pacchetti
attraverso una interfaccia come \texttt{tun0}; in modalità punto-punto OpenVPN
si limita a questo, per ottenere una vera VPN (cioè una canale di
comunicazione fra due tratti di reti private) sono necessari alcuni passi
ulteriori, che come accennato sono realizzati tramite gli opportuni script
specificati come parametro per la direttiva \texttt{up}.

Una volta che il canale è attivo quello che serve è aggiungere nella tabella
di routing di ciascun estremo della VPN una rotta statica che consenta, dalle
macchine nella rete privata dietro lo stesso, di raggiungere quelle della rete
dietro l'altro estremo, facendo riferimento alla configurazione di esempio di
fig.~\ref{fig:VPN_openvpn_schema}, sull'estremo di destra dovremo avere uno
script del tipo di:
\begin{FileExample}[label=up.sh]
#!/bin/bash
route add -net 192.168.1.0 netmask 255.255.255.0 gw $5
\end{FileExample}
%$

Si noti come si sia usato come gateway per il raggiungimento dell'altra rete
il quinto argomento passato allo script; questo è l'indirizzo IP associato
all'interfaccia \texttt{tun} dell'altro capo del tunnel. In questo modo,
fintanto che la nostra macchina riceve i pacchetti diretti verso la rete al di
là della VPN, questi verranno instradati verso l'interfaccia del tunnel, e
attraverso di questa saranno cifrati e poi trasmessi su internet usando il
socket di collegamento di \texttt{openvpn}. Ovviamente perché il meccanismo
funzioni occorre che la stessa operazione venga ripetuta sull'altro capo della
VPN, altrimenti i pacchetti non avranno una strada per tornare indietro.



\subsection{La configurazione in modalità server}
\label{sec:VPN_openvpn_server}

Le opzioni di configurazione trattate finora sono le stesse sia per la
versione 1.0 che per la versione 2.0 di OpenVPN, quest'ultima però, come
accennato, ha introdotto una nuova modalità di funzionamento che consente di
utilizzare una sola istanza del programma per fare da \textit{server} nei
confronti di un numero arbitrario di client, e che insieme a questo permette
una gestione molto più sofisticata (e comoda) del canale cifrato.

La direttiva che stabilisce quale modalità di operazione utilizzare è
\texttt{mode}, che prende come argomenti il valore \texttt{p2p} per indicare
il meccanismo classico, con una istanza del programma per canale, o il valore
\texttt{server} per indicare la nuova modalità di funzionamento con una unica
istanza che fa da server, introdotta con la versione 2.0. Se non la si
specifica viene assunto come default il comportamento classico, il che
consente di riutilizzare i file di configurazione della versione 1.0 senza
modifiche.

Il principale vantaggio della modalità server è che è sufficiente usare una
sola porta (la 1194 UDP) ed un unico file di configurazione per gestire
l'accesso alla propria rete privata da parte di un numero arbitrario di
client. Essa inoltre supporta un meccanismo che consente al server di inviare
ai client i dati necessari affinché questi possano configurare la rete in
maniera corretta, senza dover ricorrere a degli script ad hoc come fatto in
precedenza. 

La scelta della modalità server però porta in maniera sostanzialmente
obbligata anche all'uso di SSL per la creazione del tunnel, dato che
altrimenti si sarebbe costretti all'uso di una singola chiave segreta identica
per tutti i client, con gli ovvi problemi di sicurezza che questo comporta,
configurazione che pertanto non prenderemo neanche in considerazione.

La direttiva principale per l'uso della modalità server è appunto
\texttt{server}, che richiede due parametri, indirizzo e netmask della
rete all'interno della quale saranno scelti gli indirizzi assegnati nella
creazione dei singoli tunnel. In realtà, come illustrato nella pagina di
manuale, questa non è altro che una direttiva riassuntiva fornita allo scopo
di semplificare la configurazione sul server, che invoca automaticamente una
serie di altre direttive.

In questa modalità infatti è compito dell'istanza che fa da server definire
quali sono gli IP da assegnare ai capi di ciascun tunnel, che vengono scelti
all'interno di un \textit{pool} (la direttiva sottostante è in realtà
\texttt{ifconfig-pool}) analogamente a quanto avviene per il DHCP.
Specificando una rete con la direttiva \texttt{server} quello che accade è
che al server verrà comunque associato il primo indirizzo della rete, e sarà
creata una rotta statica per la suddetta rete in modo che tutti gli indirizzi
dei tunnel siano raggiungibili. Per compatibilità con Windows l'allocazione
degli indirizzi viene comunque effettuata all'interno di reti \texttt{/30},
per cui su una rete di classe C si avranno a disposizione un massimo di 64
tunnel.\footnote{in realtà a partire da OpenVPN 2.1 esiste la possibilità di
  assegnare la rete degli indirizzi interni dei client con diverse metodologie
  tramite la direttiva \texttt{topology}, ma il funzionamento richiede
  versioni aggiornate di tutti i software.}

Come accennato il vantaggio della modalità server è che buona parte delle
configurazioni dei client possono essere amministrate direttamente dal server.
Questo avviene grazie alla direttiva \texttt{push} che consente di inviare ai
client che si collegano al server una serie di direttive di
configurazione. L'insieme delle configurazioni inviabili ad un client è
limitato per motivi di sicurezza e fattibilità, le principali sono:
\texttt{route}, \texttt{route-gateway}, \texttt{route-delay}; per un elenco
più dettagliato si consulti la pagina di manuale. La direttiva \texttt{push}
richiede un singolo parametro, per cui si deve aver cura di proteggere la
direttiva che si intende inviare scrivendone il relativo testo fra virgolette.

Quando un client intende connettersi in modalità server a OpenVPN dovrà a sua
volta utilizzare la direttiva \texttt{pull}, che abilita la ricezione delle
direttive di configurazione dal server; queste ultime saranno poi applicate
come se fossero presenti nel file di configurazione.  In generale si usa al
suo posto la direttiva generica \texttt{client} che oltre ad abilitare
\texttt{pull} qualifica l'istanza di OpenVPN come client anche nella
negoziazione della connessione SSL.

L'uso più comune di \texttt{push} è per inviare ai vari client delle direttive
\texttt{route} che permettono di configurarne automaticamente la tabella di
routing, inserendovi le rotte statiche relative alle varie reti private che
sono raggiungibili attraverso il server. In questo modo se si aggiunge una
nuova rete dietro al server non è più necessario modificare le configurazioni
di tutti i client per aggiornare gli script di \texttt{up}.

Un secondo meccanismo molto utile fornito dalla modalità server è quello che
consente di modificare dinamicamente la configurazione del server stesso in
corrispondenza al collegamento di un client. Questo è governato dalla
direttiva \texttt{client-config-dir}, che permette di indicare una directory
(relativa a \texttt{/etc/openvpn}) in cui sono mantenute le opzioni di
configurazione relative a ciascun client.

Per poter utilizzare questa funzionalità però è obbligatorio usare la gestione
del canale con SSL, infatti per identificare un client il server utilizza il
\textit{Common Name} scritto nel certificato con cui esso si presenta in fase
di connessione. Se all'interno della directory specificata da
\texttt{client-config-dir} viene trovato un file con lo stesso
nome\footnote{si faccia attenzione che alcuni nomi non vengono riconosciuti
  correttamente, ad esempio se si usa un indirizzo di posta (tipo
  \texttt{piccardi@truelite.it}) si possono avere dei problemi.} presente nel
certificato una volta completata la connessione verranno eseguite le direttive
di configurazione in esso contenute; anche in questo caso è disponibile solo
un sottoinsieme limitato di direttive, le principali delle quali sono
\texttt{iroute} e \texttt{push} (per l'elenco completo si faccia riferimento
alla pagina di manuale). Se non viene trovato nessun file corrispondente ma è
presente il file \texttt{DEFAULT}, verranno usate le direttive presenti in
quest'ultimo.

L'uso più comune di questa direttiva è quello che consente di rendere visibili
fra loro la rete dietro il server e una eventuale sottorete presente dietro al
client. In questo caso però non basterà aggiungere (ovviamente usando la
direttiva \texttt{route}) la rete posta dietro il client alla tabella di
routing del server in modo che i relativi pacchetti siano inviati
sull'interfaccia di tunnel;\footnote{si suppone che il server ed il client
  facciano da default gateway per le loro reti, in caso contrario si dovranno
  aggiungere le rotte statiche sulle singole macchine.} si dovrà anche dire ad
\texttt{openvpn} a quale fra i vari client eventualmente connessi esso deve
instradare (internamente) detti pacchetti.\footnote{questo problema non si
  pone con una configurazione punto-punto, in quanto ciascuna istanza usa una
  interfaccia diversa; però in tal caso occorre gestire l'inserimento di tutte
  le rotte su entrambi i capi della comunicazione con degli opportuni script
  da invocare esternamente.}  Questo viene fatto dalla direttiva
\texttt{iroute} che prende come argomenti l'indirizzo IP della rete e la
relativa netmask;\footnote{qualora si intenda inserire una singola macchina
  invece di una rete la netmask può essere tralasciata.} ovviamente questa
direttiva dovrà essere inserita nel file di configurazione specifico del
client dietro il quale detta rete è posta.

La presenza della direttiva \texttt{iroute} è dovuta al fatto che quando opera
in modalità server OpenVPN può ricevere il traffico proveniente da diversi
client su una unica interfaccia, pertanto viene ad assumere, nei confronti di
detto traffico, il ruolo di un router. Il comportamento di default del
programma è quello di non instradare detti pacchetti, per cui ciascun client
sarà in grado di ``vedere'' su tale interfaccia soltanto il server; si può
però far agire OpenVPN come un vero router utilizzando la direttiva
\texttt{client-to-client}. In tal caso infatti OpenVPN si incaricherà di
instradare anche il traffico diretto ad altri client ad esso collegati, e
questi potranno anche comunicare fra di loro attraverso il server.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Direttiva}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{mode}   & Specifica la modalità di funzionamento di OpenVPN, prende
                      come parametro \texttt{p2p}  o \texttt{server}.\\
    \texttt{server} & Configura OpenVPN per operare in modalità server con
                      tunnel di tipo TUN; prende due parametri (numero IP e
                      netmask) che indicano la rete su cui vengono allocati i
                      numeri IP usati per gli estremi dei vari tunnel.\\
%    \texttt{server-bridge}& configura OpenVPN per operare in modalità server
%                      con tunnel di tipo TAP. Prende quattro parametri:
%                      l'indirizzo da assegnare all'interfaccia,  .\\
    \texttt{topology}&Specifica la modalità di assegnazione degli indirizzi
                      dei client nella rete indicata da \texttt{server}; i
                      valori possibili sono \texttt{net30} (il default) per
                      l'uso di una sottorete \texttt{/30} per ciascun client,
                      \texttt{p2p} per un singolo indirizzo per client, non
                      supportata da client Windows, \texttt{subnet} sempre per
                      un singolo indirizzo per client, funzionante anche con
                      versioni recenti di Windows.\\
    \texttt{push}   & Invia ad un client che si connette la direttiva di
                      configurazione passata come parametro.\\
    \texttt{pull}   & Indica ad un client di accettare le direttive di
                      configurazione inviategli da un server con la direttiva 
                      \texttt{push}.\\ 
    \texttt{ifconfig-pool}& Definisce un intervallo di indirizzi IP, i cui
                      estremi sono indicati dai due parametri passati alla
                      direttiva, all'interno dei quali sono scelti
                      dinamicamente gli indirizzi da assegnare i capi di
                      ciascun tunnel.\\
    \texttt{ifconfig-pool-persist}& Definisce un file, passato come parametro,
                      dove sono registrate le corrispondenze fra client ed IP
                      assegnati.\\
    \texttt{client-to-client}& Abilita l'instradamento del traffico fra
                      diversi client così che questi possano vedersi fra loro;
                      non richiede nessun parametro.\\
    \texttt{client-config-dir}& specifica la directory contenente le
                      configurazioni specifiche dei singoli client.\\
    \texttt{iroute}&  Imposta una rotta interna su uno specifico client, viene
                      usata per inviare i pacchetti destinati ad una certa
                      sottorete al tunnel relativo ad uno specifico client;
                      si usa all'interno delle configurazioni specifiche dei
                      client.\\
    \texttt{client} & Indica una configurazione di tipo client, è equivalente
                      all'uso delle due direttive \texttt{pull} e
                      \texttt{tls-client}.\\  
    \texttt{duplicate-cn}& Consente il collegamento anche in presenza di più
                      client che hanno un certificato con lo stesso common
                      name.\\   
    \texttt{max-clients}& Consente il collegamento ad un numero massimo di
                      client passato come parametro.\\   
   \hline
  \end{tabular}
  \caption{Le opzioni di controllo di \texttt{openvpn} per la modalità
    server.}  
  \label{tab:openvn_server_opt}
\end{table}

Con l'uso di questa direttiva diventa anche possibile unire più reti private,
presenti dietro vari client, in modo che esse possano comunicare fra loro.
Questo può sempre essere fatto in modalità punto-punto, ma il costo è quello
di inviare i pacchetti da una istanza all'altra di OpenVPN, e di dover
predisporre per ciascuna istanza gli opportuni script per l'inserimento di
tutte le relative rotte statiche. Lo svantaggio (a parte la minore efficienza)
è che la riconfigurazione va fatta per tutti i client, per cui l'aggiunta di
una nuova rete dietro un nuovo client comporta la modifica delle
configurazioni di tutti gli altri.

La caratteristica interessante della modalità server è che invece, una volta
attivata la direttiva \texttt{client-to-client}, detta configurazione può
essere realizzata operando solo sul server. In tal caso infatti oltre ai passi
precedentemente illustrati per ``pubblicare'' la rete presente dietro il nuovo
client, basterà usare la direttiva \texttt{push} per inviare a tutti i client
la rotta della nuova rete.\footnote{fra questi ovviamente non ci sarà il
  client dietro cui tale rete si trova; questo viene curato automaticamente da
  OpenVPN, che se una rete è citata in una direttiva \texttt{iroute} nella
  configurazione di un client, modifica il comportamento di \texttt{push} in
  modo che essa non gli invii una rotta statica relativa a detta rete.}


In tab.~\ref{tab:openvn_server_opt} si sono riportate le principali opzioni
relative alla configurazione di OpenVPN in modalità server (sia per il server
che per il client). Al solito l'elenco completo delle varie opzioni/direttive
è disponibile sulla pagina di manuale del comando \texttt{openvpn}.

Vediamo allora un esempio tipico di configurazione per OpenVPN in modalità
server.  Partiamo dal file di configurazione sul lato server, per una macchina
che fa da gateway per la rete \texttt{192.168.1.0} (ufficio) cui si collega un
client che fa da gateway per la rete \texttt{192.168.0.0} (casa), una volta
eliminati commenti e righe vuote si avrà:
\begin{FileExample}[label=server.conf]
port 1194
proto udp
dev tun
ca /etc/ssl/certs/Truelite-cacert.pem
cert vpncert.pem
key vpnkey.pem   # This file should be kept secret
dh dh4096.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.1.0 255.255.255.0"
client-config-dir ccd
route 192.168.0.0 255.255.255.0
keepalive 10 120
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3
\end{FileExample}

In questo caso si è usata la porta standard, per il resto le prime 6 direttive
sono analoghe a quelle che sarebbero presenti in modalità punto-punto.
Rispetto agli esempi illustrati in sez.~\ref{sec:fw_openvpn_config} questa
volta si è predisposto un tunnel creato con SSL per cui si sono usate le
direttive \texttt{ca}, \texttt{cert}, \texttt{dh} e \texttt{key} al posto di
\texttt{secret} per dichiarare i file contenenti i dati necessari.

La prima differenza con una configurazione punto-punto è la presenza della
direttiva \texttt{server} che dichiara la rete su cui saranno allocati gli
indirizzi IP dei tunnel. L'impostazione della rete presente dietro il server è
invece effettuata dalla direttiva \texttt{push}, che invierà la relativa
direttiva di configurazione a tutti i client. Per poter accedere alla rete
\texttt{192.168.0.0} invece si usa direttamente la direttiva \texttt{route}
sul server, preceduta dall'impostazione della directory per le configurazioni
dei singoli client con \texttt{client-config-dir}. 

Per potersi collegare al server della configurazione precedente, si potrà
invece usare una configurazione client come quella del seguente esempio, in
cui di nuovo si sono rimosse righe vuote e commenti:
\begin{FileExample}[label=client.conf]
client
dev tun
proto udp
remote holland.truelite.it 1194
resolv-retry infinite
port 1194
user nobody
group nogroup
persist-key
persist-tun
ca  Truelite-cacert.pem
cert havnor-cert.pem
key  havnor-key.pem
comp-lzo
verb 3
\end{FileExample}

Si noti come le direttive per SSL siano (ad eccezione di \texttt{dh})
sostanzialmente analoghe, e come una volta usata la direttiva \texttt{client}
sia stato sufficiente indicare con \texttt{remote} l'indirizzo pubblico del
server, senza avere più la necessità di predisporre script da lanciare con
\texttt{up}. 





\ifwhole\else

\appendix
%\include{ringraziamenti}
\input{../commons/end}

\end{document}

\fi

% LocalWords:  firewall VPN Truelite Srl sez shell WLAN content TCP IDS cap CRL
% LocalWords:  filtering stateless stateful DMZ fig router personal militarized
% LocalWords:  netfilter kernel packet networking options configuration hooks
% LocalWords:  stack iptables connection tracking checksum PREROUTING routing
% LocalWords:  decision DNAT destination translation FORWARD SNAT strongSwan
% LocalWords:  POSTROUTING filesystem proc tables names filter ip FreeS NETKEY
% LocalWords:  nat conntrack mangle masquerading transparent proxing client UDP
% LocalWords:  proxy ICMP IPv MTU transfer Unit always defrag oppish cat tcp Gb
% LocalWords:  SYN SENT src dst dport UNREPLIED three way handshake ACK KAME
% LocalWords:  ESTABLISHED Oskar Andreasson ASSURED netstat RECV WAIT backport
% LocalWords:  RST CLOSE tab LAST LISTEN socket udp echo request reply netmask
% LocalWords:  timestamp information ping icmp type RELATED INVALID of FreeBSD
% LocalWords:  FTP HOWTO IRC patch payload unreachable source host OpenBSD dkms
% LocalWords:  quench exceeded paremeter problem redirect version table new TOS
% LocalWords:  chain delete rename list flush policy line numbers append insert
% LocalWords:  replace AND protocol all DNS CIDR interface ethernet eth ppp tun
% LocalWords:  fragment port smtp ssh flags RFC URG PSH syn option mss segment
% LocalWords:  size limit DoS denial service flood burst second hour mac mark
% LocalWords:  address multiport ports owner uid gid group pid sid session cmd
% LocalWords:  tos minimize maximize throughput reliability TFTP BOOTP to tools
% LocalWords:  cost streaming ttl Live unclean jump ACCEPT QUEUE RETURN IKEv
% LocalWords:  extension robin LOG logging facility syslog kern dmesg log level
% LocalWords:  conf debug prefix sequence MASQUERADE pppd localhost REJECT keep
% LocalWords:  reject with prohibited admin reset DSL expired charon Squeeze
% LocalWords:  dec inc traceroute save counters generated Sun COMMIT completed
% LocalWords:  restore noflush scripting sysctl GaPiL ipv documentation forward
% LocalWords:  bool ignore int broadcast multicast ratelimit jiffie ratemask rp
% LocalWords:  syncookies route forwarding antispoofing spoofing cachecrls self
% LocalWords:  message parameter any info mask needed bad DDoS crlcheckinterval
% LocalWords:  fragmentation failed unknown isolated communication precedence
% LocalWords:  violation cutoff during reassembly header required missing path
% LocalWords:  border discovery LDAP NIS wrapper NFS IKE IPSEC allowed ESP FQDN
% LocalWords:  services dial overhead aliasing virtual road warrior  plutostart
% LocalWords:  authentication encapsulating exchange ISAKMP and strictcrlpolicy
% LocalWords:  association DOI domain interpretation Oakley index gateway cache
% LocalWords:  security traversal OpenVPN WAN tid SSL OE BSD charonstart signed
% LocalWords:  opportunistic encription strongswan openswan KLIPS ipsec modules
% LocalWords:  backporting package APT THE yes make kpkg added patches image an
% LocalWords:  pluto debconf PCMCIA RSA the middle automatic keying manual rsa
% LocalWords:  perfect secrecy secrets certification psk protostack connections
% LocalWords:  pathname dotted decimal ttoaddr insensitive ttodata sample for
% LocalWords:  shared two hosts entry may split across lines but indentation is
% LocalWords:  matters key ranbits anarres umask rsasigkey bits only it never
% LocalWords:  signatures UNSAFE ENCRYPTION pubkey Modulus PublicExponent after
% LocalWords:  this point exponent coefficient authenticating other which knows
% LocalWords:  public part suitable keys implementations can extracted not that
% LocalWords:  conveniently showhostkey change indenting woody config setup hop
% LocalWords:  conn also Sarge conforms specification controls almost lots ethX
% LocalWords:  klipsdebug plutodebug control parsing interfaces ipsecN priority
% LocalWords:  daemon error left right transport passthrough leftsubnet updown
% LocalWords:  rightsubnet leftnexthop leftupdown subnet behind next toward at
% LocalWords:  rightnexthop authorize actually startup uncomment add authby Thu
% LocalWords:  rsasig leftrsasigkey Apr rightrsasigkey leftcert rightcert vtun
% LocalWords:  leftca cipe Peter Gutmann pgut vpn txt TLS Wan stream Windows dh
% LocalWords:  openvpn apt get IANA dev ifconfig brctl DHCP local lport rport
% LocalWords:  nobind binding shaper verb monk genkey static BEGIN cert pem tls
% LocalWords:  certification authority Diffie Hellman auth askpass reneg sec gw
% LocalWords:  pkts bytes comp lzo verify ipchange delay mktun rmtun Win device
% LocalWords:  dynamic our endpoint home will establish routes alive pre uses
% LocalWords:  verbosity quiet except fatal errors mostly good normal operation
% LocalWords:  troubleshooting peer push pull iroute persist cn ipp rightid DER
% LocalWords:  common name clients vpncert vpnkey should kept ccd keepalive 
% LocalWords:  nobody nogroup resolv retry cacert havnor distributed everything
% LocalWords:  PrivateExponent wireless defaultroute direct leftsendcert leftid
% LocalWords:  keyexchange ifasked keygen openssl thread setkey rekeying ECDSA
% LocalWords:  leftauth rightauth EAP XAUTH PIN smartcard filename globbing raw
% LocalWords:  der pingando UNTRACKED NOTRAK SIP NOTRACK connbytes acct min
% LocalWords:  original both packets avgpkt stunnel OpenWRT configure install
% LocalWords:  pkcs


%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "sicurezza"
%%% End: 
 
