6.2 Configurazioni astratte esprimibili
6.2.2 Coerenza
La coerenza `e la propriet`a di un firewall astratto λ, rispetto a un diagramma di controllo C e a un assegnamento di etichette v, secondo la quale per nessuna coppia (p, t) tale che t = λ(p), imporre che la configurazione del firewall f sia tale che (C, f )(p) = t causa delle restrizioni sulla configurazione stessa che siano contraddittorie con altre coppie (p0, t0) tali che t0 = λ(p0). Formalmente 1(λ, C, v)
pu`o essere espressa considerando i percorsi del diagramma nella seguente maniera: 1(λ, C, v) = (∀p ∈ P. ∃π ∈ Π(C). (p, λ(p)) ∈ E(π, C, v))
⇒ (∃f ∈ M3(C, v). ∀p ∈ P. ∃π ∈ Π(C). ∆((C, f ), p) = π ∧ (π, f )(p) = λ(p))
dove ci siamo concessi un piccolo abuso di notazione e abbiamo scritto (π, f ) per intendere la concatenazione delle funzioni P → T (P) ∪ {⊥} associate ai nodi del percorso π da f . Formalmente:
(π, f )(p) = (π0, f )(p0) n t se π = q · π0∧ t 6= ⊥ ⊥ se π = q · π0∧ t = ⊥ id altrimenti dove t = f (q)(p) e p0= t(p)
In effetti, dato che abbiamo a disposizione la funzione P(C, v, p, t), possiamo sfruttarla per limitare la scelta del percorso π ∈ Π(C) scrivendo:
1(λ, C, v) = (∀p ∈ P. ∃π ∈ Π(C). (p, λ(p)) ∈ E(π, C, v))
⇒ (∃f ∈ M3(C, v). ∀p ∈ P. ∃π ∈ P(C, v, p, λ(p)). ∆((C, f ), p) = π ∧ (π, f )(p) = λ(p))
Inoltre, se la funzione P(C, v, p, λ(p)) restituisce un singoletto, allora la condizione ∆((C, f ), p) `e automaticamente soddisfatta e possiamo riscrivere la coerenza come:
1(λ, C, v) = (∀p ∈ P. ∃π ∈ Π(C). (p, λ(p)) ∈ E(π, C, v))
L’algoritmo di generazione, che realizza la fase 3. della pipeline di transcompilazione, si occupa sostanzialmente di trovare una f che verifichi la seconda parte del predicato, possibilmente generandola ad hoc perch´e verifichi (π, f )(p) = λ(p), tenendo f ∈ M3(C, v) come vincolo.
L’idea `e quella di calcolare per ogni coppia (p, t), le restrizioni cui un firewall del sistema studiato `e soggetto accettando il pacchetto p con trasformazione t. Una policy `e esprimibile solo se le restrizioni causate da ciascuna delle coppie non impedisce il firewall dal realizzare il resto della funzione λ.
La formula proposta non `e la pi`u vantaggiosa per il confronto dell’espressivit`a di diversi sistemi, ma fornisce un predicato che data una funzione λ : P → T (P) ∪ {⊥} consente in teoria di verificare se questa pu`o o meno essere la semantica di un firewall del sistema in esame.
Forniamo un esempio di firewall astratto λ che nel sistema pf verifica la condizione di fattibi- lit`a locale 0(λ, Cpf, vpf) ma che non `e esprimibile in quanto non verifica la condizione di coerenza
1(λ, Cpf, vpf). Supponiamo L = {192.168.0.0, 127.0.0.0}, si consideri la funzione λ : P → T (P) ∪ {⊥}
definita come: λ(p) =
(cost(1.2.3.4) : id, id : id) se p = (192.168.0.0 : 22, 192.168.0.0 : 23) (1)
(id : id, cost(4.3.2.1) : id) se p = (1.2.3.4 : 22, 192.168.0.0 : 23) (2)
⊥ altrimenti
Riguardo al caso (1), ¨π4 `e l’unico percorso che il pacchetto (192.168.0.0 : 22, 192.168.0.0 : 23) pu`o
percorrere se gli deve essere associata la trasformazione (cost(1.2.3.4) : id, id : id); formalmente: P(Cpf, vpf, (192.168.0.0 : 22, 192.168.0.0 : 23), (cost(1.2.3.4) : id, id : id)) = {π4}
Quindi `e necessario, perch´e 1(λ, Cpf, vpf) sia verificato, che esista una configurazione f tale che
(π4, f )(192.168.0.0 : 22, 192.168.0.0 : 23) = (cost(1.2.3.4) : id, id : id). Nel percorso π4 esiste
un solo nodo con etichetta SN AT , adatto ad applicare la trasformazione cost(1.2.3.4) al campo sIP del pacchetto, questo nodo `e q2. Dunque il nodo q2 applicher`a questa trasformazione e il resto dei
nodi del percorso assocer`a la trasformazione identit`a al risultato:
f (q2)(192.168.0.0 : 22, 192.168.0.0 : 23) = (cost(1.2.3.4) : id, id : id)
f (q3)(1.2.3.4 : 22, 192.168.0.0 : 23) = (id : id, id : id)
f (q0)(1.2.3.4 : 22, 192.168.0.0 : 23) = (id : id, id : id)
f (q1)(1.2.3.4 : 22, 192.168.0.0 : 23) = (id : id, id : id)
Nel caso (2) invece, ¨π1`e l’unico percorso che il pacchetto (1.2.3.4 : 22, 192.168.0.0 : 23) pu`o percorrere
se deve essergli associata la trasformazione (id : id, cost(4.3.2.1) : id); formalmente: P(Cpf, vpf, (1.2.3.4 : 22, 192.168.0.0 : 23), (id : id, cost(4.3.2.1) : id)) = {π1}
`
E quindi necessario, perch´e 1(λ, Cpf, vpf) sia verificato, che la stessa configurazione f del caso prece-
dente sia tale che (π3, f )(1.2.3.4 : 22, 192.168.0.0 : 23) = (id : id, cost(4.3.2.1) : id). Nel percorso
π3 esiste un solo nodo con etichetta DN AT , adatto ad applicare la trasformazione cost(4.3.2.1) al
campo dIP del pacchetto, questo nodo `e q0. Dunque il nodo q0 applicher`a questa trasformazione e il
resto dei nodi del percorso assocer`a la trasformazione identit`a al risultato: f (q0)(1.2.3.4 : 22, 192.168.0.0 : 23) = (id : id, cost(4.3.2.1) : id)
Il firewall astratto λ non `e esprimibile dunque, dato che non `e possibile che la funzione di trasforma- zione associata al nodo q0sia tale che f (q0)(1.2.3.4 : 22, 192.168.0.0 : 23) = (id : id, cost(4.3.2.1) : id)
e contemporaneamente f (q0)(1.2.3.4 : 22, 192.168.0.0 : 23) = (id : id, id : id).
In particolare il problema di questo firewall astratto in pf `e legato al fatto che se un pacchetto p viene accettato con trasformazione t dal percorso π4, allora il pacchetto p0 tale che p0.sIP = t(p).sIP ,
p0.sP ort = t(p).sP ort, p0.dIP = p.dIP e p0.dP ort = p.dP ort deve essere accettato con trasformazione t0= (id : id, t.dIP : t.dP ort). Altri vincoli simili possono essere individuati dall’analisi del predicato 1(λ, Cpf, vpf), sulla base del percorso associato a una coppia (p, t).
Capitolo 7
Generazione di un firewall
La generazione `e la terza fase della pipeline di transcompilazione, relativa alla creazione di un firewall
IFCL, del tipo designato, che abbia una semantica equivalente a quella del firewall astratto di partenza. Dato un firewall astratto sintetizzato ˜λ, l’obiettivo `e dunque quello di produrre una configurazione
IFCLΣ per il sistema k tale che:
L
$
(Ck, Σ)%
M(sNEW) = i(˜λ)Nonostante avvenga in un’altra fase della pipeline, dobbiamo occuparci anche della concretizzazione: cio`e la procedura che, a partire dalla configurazione per il firewallIFCL, restituisce il file di configura- zione del sistema target. La quarta ed ultima fase della pipeline `e realizzata per mezzo di una funzione conk; questa funzione non pu`o essere definita su tutte le possibili configurazioneIFCLassegnabili al
diagramma di controllo del sistema target, Ck. In effetti per poter implementare la fase finale della
pipeline `e necessario che la configurazione Σ prodotta dall’algoritmo di sintesi appartenga al dominio della funzione conk. Alcune configurazione potrebbero non essere compilabili perch´e la loro semantica
non `e esprimibile dal sistema target, come abbiamo dimostrato nel capitolo precedente infatti non
tutti i sistemi possono esprimere tutte le funzioni P → T (P) ∪ {⊥}. In questo caso non possiamo fare niente, il fallimento non dipende dall’algoritmo che scegliamo per la fase 3. della pipeline o dalla funzione di concretizzazione. Tuttavia, se la funzione di concretizzazione conk non `e definita su tutte
le configurazioni Σ tali cheL(Ck, Σ)M `e una funzione esprimibile dal sistema k, `e possibile produrre dei firewallIFCLche non possono essere concretizzati anche quando la funzione di partenza `e esprimibile dal sistema target.
Per prima cosa forniremo qualche dettaglio sulla funzione di concretizzazione, specificando quali tipi
di configurazioniIFCL sono concretizzabili nei vari sistemi; successivamente forniremo due approcci
alternativi per la fase di generazione: uno che segue passo passo le fasi intermedie della pipeline proposta nel capitolo 4; l’altro proposto inizialmente in [4] basato sulla generazione in un passo solo della configurazioneIFCLper il sistema target, basato sull’uso intensivo del campo tag dei pacchetti.
Dato un firewall astratto sintetizzato ˜λ e un sistema k, vorremmo verificare in anticipo se sia
possibile ottenere un firewall con semantica equivalente a λ = i(˜λ) per il sistema k, cio`e λ ∈ Λk, ma
come abbiamo visto la procedura per un controllo `e tanto complessa quanto tentare la generazione
in s´e. Verifichiamo comunque la condizione necessaria 0(λ, Ck, vk), se questa non `e verificata allora
sicuramente non potremo generare il firewall target, in caso contrario c’`e comunque la possibilit`a che la generazione non vada a buon fine, nel qual caso ce ne accorgeremo durante l’applicazione dell’algoritmo e la generazione terminer`a segnalando errore.
Come detto decidiamo di analizzare i sistemi solo per quanto riguarda il modo di trattare pacchetti appartenenti a nuove connessioni, pertanto assumeremo sempre che il firewall sia nello stato sNEW.
7.1
Concretizzazione
L’ultima traduzione effettuata dalla pipeline `e la concretizzazione del firewall IFCLcome file di con- figurazione del sistema target. Concettualmente la funzione conk `e l’inversa della funzione di forma-
lizzazione f ork, ma questo non `e strettamente vero a livello funzionale. Non vale infatti in genere
che f ork(conk(Σ)) = Σ; quello che abbiamo `e che data un configurazioneIFCLΣ, per il sistema k, la
sua concretizzazione restituisce un file di configurazione file.conf la cui semantica sia equivalente a quella di Σ. Formalmente:
L
$
(Ck, f ork(conk(Σ)))%
M ≡ L$
(Ck, Σ)%
MPer una funzione di concretizzazione chiamiamo correttezza la propriet`a di produrre sempre un file di configurazione legale e la cui semantica sia equivalente a quella della configurazione di partenza.
La funzione conk non pu`o essere definita su ogni possibile configurazione, si tratta di una funzione
parziale. Ad esempio tutte le configurazioni per le quali la semantica del firewall non `e esprimibile dal sistema k non saranno concretizzabili in file di configurazione per k. Chiamiamo Γ0k l’insieme delle configurazioni Σ sulle quali `e definita la funzione conk. Si noti che Γk non `e affatto equivalente a Γ0k.
Idealmente vorremmo poter concretizzare ogni configurazione con semantica esprimibile. Chiamiamo conk completa se e solo se:
∀λ ∈ Λk. ∀Σ.L
$
(Ck, Σ)%
M = λ ⇒ Σ ∈ Γ0 k
In realt`a ci accontentiamo di una propriet`a pi`u debole:
∀λ ∈ Λk. ∃Σ. L
$
(Ck, Σ)%
M = λ ∧ Σ ∈ Γ0 k
E ci sincereremo che la configurazione prodotta dall’algoritmo di generazione sia proprio una dei Σ che appartengono a Γ0k. In particolare la funzione conkper k ∈ {iptables, pf, ipfw} `e definita sull’insieme
Γ0k= M2(Ck, vk).
La concretizzazione per i sistemi supportati `e relativamente banale se ci limitiamo a supportare le configurazioni in M2(Ck, vk). Trattandosi di configurazioni normalizzate infatti, e non dovendo quindi
trattare salti, tag e chiamate, `e sufficiente applicare una trasformazione sintattica immediatamente derivabile dalla definizione delle funzioni di formalizzazione f ork.