La nostra configurazione Prima di andare avanti e definire le regole di firewalling, dobbiamo avere un'idea chiara di cosa vogliamo fare con la nostra rete. Prima di procedere, è quindi fondamentale un minimo di pianificazione. Nel nostro caso, abbiamo una dmz, una lan ed un collegamento ad internet. Abbiamo un firewall con tre interfacce di rete, ognuna collegata ad una rete diversa e abbiamo quindi una connessione ad internet relativamente lenta (rispetto alle altre due reti). L'idea di base è quella di mettere nella dmz i server e di fare in modo da risparmiare banda, inserendo un proxy server. Sulla nostra dmz, ci troveremo quindi: * un web server, ad uso sia interno che esterno * un mail server (pop3 e smtp), ad uso sia interno che esterno * un proxy server, soltanto ad uso interno * un dns, ad uso sia interno che esterno Per quanto riguarda le altre restrizioni da imporre alle comunicazioni tra le varie reti (ad esempio, non vogliamo che gli utenti della lan controllino altre caselle di posta elettronica oltre quelle fornite dal nostro mail server), ne parleremo in ogni specifica sezione. Per andare avanti nella nostra configurazione, dobbiamo quindi indicare cosa invece lasciare passare. Questo si fa aggiungendo delle regole. Una soluzione potrebbe essere quella di aggiungere tutte le regole relative al traffico che vogliamo lasciare passare nelle 3 catene di base. Funzionerebbe, ma vi posso garantire che sarebbe molto facile commettere degli errori e vi posso garantire che altrettanto facilmente diventerebbero così tante da non poter essere più gestibili. Uno degli approcci più semplici nella gestione delle regole di firewalling è quindi quello di dividere il traffico in ``flussi'' di dati dopodichè considerare indipendentemente ogni singolo flusso, evitando così di avere tutte le regole insieme e formalizzandosi in modo da evitare gli errori più comuni. Analizzando il nostro esempio, potremmo quindi dividere il nostro traffico in 6 grandi flussi: * tutto ciò che dalla lan va alla dmz * tutto ciò che dalla lan va su internet * tutto ciò che dalla dmz va su internet * tutto ciò che dalla dmz va sulla lan * tutto ciò che da internet va sulla nostra dmz * tutto ciò che da internet vuole andare sulla nostra lan Possiamo poi, per esempio, creare per ogni flusso una catena e ad ogni catena associare un suo insieme di regole indipendenti da quello di tutte le altre catene. Ma andiamo per gradi: iniziamo a creare delle nuove catene. Per fare questo dobbiamo eseguire iptables seguito da un ``-N'' e da un nome per la catena: 16: iptables -N landmz #dalla scheda di rete eth0 alla scheda di rete eth1 17: iptables -N laninet #dalla scheda di rete eth0 alla scheda di rete eth2 18: iptables -N dmzinet #dalla scheda di rete eth1 alla scheda di rete eth2 19: iptables -N dmzlan #dalla scheda di rete eth1 alla scheda di rete eth0 20: iptables -N inetdmz #dalla scheda di rete eth2 alla scheda di rete eth1 21: iptables -N inetlan #dalla scheda di rete eth2 alla scheda di rete eth0 Per il kernel, però, il nome che abbiamo dato ed il commento non hanno alcun significato. Dobbiamo quindi trovare un modo per indicare quali catene devono essere percorse in quali situazioni. Per fare questo, possiamo specificare 6 semplici regole. Trattandosi di regole per traffico che non è né originato né destinato al firewall, dovremo inserirle nella catena di FORWARD. Per esempio, potremmo dare dei comandi come: 23: iptables -A FORWARD -i eth0 -o eth1 -j landmz 24: iptables -A FORWARD -i eth0 -o eth2 -j laninet 25: iptables -A FORWARD -i eth1 -o eth2 -j dmzinet 26: iptables -A FORWARD -i eth1 -o eth0 -j dmzlan 27: iptables -A FORWARD -i eth2 -o eth1 -j inetdmz 28: iptables -A FORWARD -i eth2 -o eth0 -j inetlan Il significato di queste righe è molto semplice: aggiungi (-A, append) alla catena FORWARD, una regola per cui se un pacchetto proviene dalla scheda di rete eth0 (-i) ed è destinato ad uscire dalla scheda eth1 (-o), la sua sorte deve essere decisa (-j) dalla catena landmz e così via. In pratica, abbiamo diviso tutti i pacchetti in transito nella catena di forward in 6 categorie, dove ogni categoria ha associata una catena e quindi una serie di regole. Riassumendo: * -N crea una nuova catena * -A aggiunge una regola ad una catena * -i consente, in una regola, di discriminare i pacchetti in base all'interfaccia fisica da cui sono entrati * -o in base all'interfaccia fisica da cui usciranno (scelta in base alle tabelle di routing da noi impostate) * -j di mandare i pacchetti ad un'altra catena Abbiamo visto quindi come una regola può identificare dei pacchetti in base alle schede di rete coinvolte. E' però possibile utilizzare molti altri criteri, per esempio: * il protocollo (-p) * l'indirizzo ip sorgente (-s) * l'indirizzo ip destinazione (-d) * se si tratta di un frammento (-f) * o se non lo è (! -f) Dove ogni protocollo può aggiungere dei criteri di classificazione. Per esempio, se specifichiamo ``-p tcp'' per indicare il protocollo tcp, possiamo poi dividere i pacchetti in base anche * alla porta sorgente (--sport) * alla porta destinazione (--dport) * ai flag del tcp (--tcp-flags SYN, ACK, FIN...) * alle opzioni (--tcp-option) Anche in questo caso, oltre alle estensioni fornite dai protocolli, è possibile utilizzare delle estensioni fornite da moduli. A questo punto però, vi sarà venuto spontaneo chiedervi perché effettuare una prima classificazione in base all'hardware e non, ad esempio, in base all'indirizzo ip sorgente o all'indirizzo ip destinazione. Ancora una volta, la risposta è molto semplice: il contenuto di un pacchetto si può falsificare. Il fatto che arrivi su un'interfaccia piuttosto che un'altra, no. Utilizzando almeno per le prime regole le interfacce di input e quelle di output, avremo quindi la certezza che i pacchetti saranno valutati dalle regole contenute nella catena corretta e che nessuno potrà imbrogliarci utilizzando ip fasulli (ancora, cosa succederebbe se basassimo le nostre regole solo sugli indirizzi ip e qualcuno ci mandasse dei pacchetti provenienti da 127.0.0.1 con l'rp_filter disabilitato?). Dalla LAN alla DMZ Ricordandoci della configurazione della nostra ipotetica rete, abbiamo deciso che dalla nostra lan vogliamo che tutte le richieste per pagine web vengano deviate sul nostro server proxy (transparent proxy) in maniera trasparente, che i nostri utenti non controllino altre caselle di posta elettronica se non quelle da noi fornite, che possano collegarsi al nostro server web direttamente e che siano in grado di scaricare file con ftp direttamente da internet. Dall'esterno, vogliamo soltanto rendere accessibile il nostro dns, il server di posta elettronica, il nostro server web ed il server ftp. Ma lavoriamo anche qua per flussi, in modo da semplificare un po' le cose. Iniziamo allora a creare le regole per la nostra lan, lasciando indietro (per ora) ciò che riguarda il ``deviare''. Dalla lan alla dmz, vogliamo quindi consentire: * le connessioni al nostro server web (www) * le connessioni per spedire la posta (smtp) * le connessioni per ricevere la posta (pop3) * le connessioni verso il server proxy (webcache) * nonché le connessioni necessarie per utilizzare il nostro dns (domain) Aggiungiamo quindi le regole corrette, esattamente come indicato qua sopra: 30: iptables -A landmz -s ! 192.168.200.0/24 -j DROP 31: iptables -A landmz -p tcp -d nostro.server.web --dport www -j ACCEPT 32: iptables -A landmz -p tcp -d nostro.server.smtp --dport smtp -j ACCEPT 33: iptables -A landmz -p tcp -d nostro.server.pop3 --dport pop3 -j ACCEPT 34: iptables -A landmz -p tcp -d nostro.server.proxy --dport webcache -j ACCEPT 35: iptables -A landmz -p tcp -d nostro.dns --dport domain -j ACCEPT 36: iptables -A landmz -p udp -d nostro.dns --dport domain -j ACCEPT Prima di tutto, qua dentro sarebbe molto meglio indicare direttamente degli indirizzi ip al posto dei nomi dei computer. Come abbiamo già detto, infatti, il protocollo dei DNS deve essere considerato insicuro. Se proprio volessimo usare i nomi dei computer, potremmo utilizzare il vecchio file degli hosts, in /etc/hosts, dove ogni linea è formata dall'indirizzo ip di un computer seguito dal suo nome (e separati da spazi). Come potete vedere, questa volta le regole le ``appendiamo'' (-A) non più alla catena di FORWARD bensì alla catena landmz, trattandosi di regole che andranno a discriminare il traffico tra la nostra lan e la nostra dmz. Ora, la prima regola indica che non vogliamo che passi niente che non abbia un indirizzo ip proveniente dalla nostra rete interna. Questa regola eviterà quindi che qualcuno dei nostri utenti possa fare spoofing verso la nostra dmz o che comunque tenti di imbrogliarci con dei giochi strani sull'indirizzo ip. E' una regola un po' superflua, avendo già abilitato la protezione del kernel, ma a volte è meglio aggiungere qualche regola in più piuttosto che avere qualche regola in meno (e poi, siete sicuri che nelle prossime versioni del kernel il filtro sarà ancora disponibile o che si comporterà sempre nello stesso modo?). Le altre sono ancora regole molto semplici. Le uniche novità introdotte rispetto prima sono la negazione (il !), che indica che perché una regola venga applicata una certa condizione non deve essere soddisfatta, ed il fatto che finalmente potete vedere diversi criteri messi in pratica. -s, specifica un ip sorgente e può essere seguito da un indirizzo ip o da un indirizzo di rete (indicato come x.x.x.x/y) o dal nome di un host. -p può essere seguito dal nome o dal numero di un protocollo (file /etc/protocols conserva le associazioni). -d, ancora, indica la destinazione di un pacchettino e può essere seguito sempre da un indirizzo ip, da un nome di host o da un indirizzo di rete (con lo stesso formato indicato prima). --dport, invece, indica una porta di destinazione e può essere seguito da un numero o dal nome di una porta (il file /etc/services conserva le associazioni). In tutti i casi, è possibile usare la negazione dopo l'indicazione del criterio. Infine, ACCEPT dice ad iptables di accettare tali pacchetti nel caso in cui la regola risulti applicabile. Per configurare un firewall, è necessaria una buona conoscenza dei vari protocolli di rete: l'ultima riga è stata aggiunta in quanto il protocollo per la comunicazione con i dns utilizza il più delle volte connessioni udp, mentre utilizza connessioni tcp solo in condizioni particolari. Senza questa regola, il dns avrebbe funzionato sempre tranne qualche volta, e sarebbe stato estremamente difficile trovare il problema (se mai ce ne fossimo resi conto). Per chi di voi si fosse invece chiesto come si fa a specificare una rete o che senso ha il /24, basti sapere che si tratta di un sistema estremamente comodo per indicare le netmask. Per esempio, una netmask 255.255.255.0 indica che se i primi 24 bit di due indirizzi ip sono uguali, allora i due si trovano sulla stessa rete (255.255.255.0 scritto in notazione binaria sarebbe 11111111.11111111.11111111.00000000, con 24 uno). 255.255.255.0 è quindi equivalente a /24 (ogni ottetto - 255 - sono 8 bit). Visto però che si tratta delle prime regole ``serie'' della nostra trattazione, vediamo comunque di descriverle a parole, un po' come abbiamo fatto prima: * 30: Butta via ogni pacchetto in transito nella catena landmz che non venga da un indirizzo ip facente parte la nostra lan. * 31: Accetta ogni pacchetto tcp in transito dalla catena landmz destinato alla porta 80 (www) del nostro.server.web * 32: Accetta ogni pacchetto tcp in transito dalla catena landmz destinato alla porta 25 (smtp) del nostro.server.smtp * 33: Accetta ogni pacchetto tcp in transito dalla catena landmz destinato alla porta 110 (pop3) del nostro.server.pop3 * 34: Accetta ogni pacchetto tcp in transito dalla catena landmz destinato alla porta 8080 (webcache) del nostro.server.proxy * 35: Accetta ogni pacchetto udp in transito dalla catena landmz destinato alla porta 53 (dns) del nostro.dns * 36: Accetta ogni pacchetto tcp in transito dalla catena landmz destinato alla porta 53 (dns) del nostro.dns * (Butta via tutto il resto, come definito dalla policy) Ad alcuni di voi sarà venuto spontaneo chiedersi come mai è stata messa come prima regola un ``butta via'' con una negazione, anzichè una più semplice accetta (qualcosa del tipo: accetta ogni pacchetto in transito nella catena landmz che viene da un indirizzo ip facente parte della nostra lan). Il problema è che il controllo delle regole si ferma alla prima regola soddisfatta. Se fosse stata quindi un'accept, la regola sarebbe stata soddisfatta per ogni pacchetto proveniente dalla lan, e la scansione delle regole non sarebbe andata avanti a quelle successive, vanificando buona parte del nostro lavoro. Un'altra possibilità sarebbe stata quella di omettere la prima regola e di specificare ogni volta esplicitamente l'indirizzo ip, aggiungendo alle righe dalla 31 alla 36 qualcosa come ``-s 192.168.200.0/24''. Siccome però sono una persona molto pigra, ho scelto il metodo più veloce da scrivere. L'ultima regola indicata tra parentesi, poi, non è stata da noi scritta: è implicitamente aggiunta dalla policy (DROP) che abbiamo deciso di utilizzare. L'esperienza però mi insegna che a questo punto potrebbe essere conveniente inserire come regola 38 qualcosa di simile a: 38: iptables -A landmz -p tcp -j REJECT --reject-with tcp-reset Questo ha a che vedere con i meandri del tcp. Ma vediamo di spiegarla in poche parole: quando avviene una connessione TCP/IP, ha luogo il solito ``three way handshake''. In pratica, per avere la certezza che i pacchetti arrivino a destinazione, il computer A manda un messaggio del tipo ``questo è il mio numero, e se ci sei, mandami il tuo'', dopodichè il computer B risponde con un messaggio del tipo ``ho ricevuto il tuo numero, questo è il mio'', infine il computer A risponde dicendo ``ho ricevuto il tuo numero'' e la comunicazione ha inizio. Normalmente però, rispettando il protocollo TCP/IP, se il computer A dovesse tentare di collegarsi ad una porta chiusa (ad un servizio non disponibile) su B, allora B dovrebbe rispondere con ``la porta è chiusa''. Ma vediamo cosa succede nel nostro caso: * Tra A e B c'è il nostro firewall F. * A manda il messaggio a B ad una porta non consentita. * senza regola 38, F riceve il messaggio e lo butta via. * A rimane in attesa di una risposta per parecchi secondi e ci riprova, sempre con lo stesso risultato. * A questo punto, A è rimasto in attesa di un tempo valutabile in minuti, mentre B è rimasto inconsapevole di tutto. Bene, la regola 38 dice che per ogni connessione tcp arrivata in fondo alla catena (essendo stata aggiunta per ultima), invece di essere buttato via il pacchetto, deve essere utilizzata l'estensione (modulo esterno) REJECT per mandare un ``tcp-reset'', il messaggio che indica il fatto che la porta è chiusa. Vediamo però che il target REJECT è stato specificato semplicemente con un -j, come per tutti gli altri target. Quando si parla di target, infatti, non c'è alcuna differenza tra ``estensioni'' esterne e target forniti direttamente da iptables, se non la pagina di manuale. Alcuni di voi si potranno chiedere a questo punto ``ma che diavolo, cosa mi interessa se l'altro tentando di accedere ad una porta non consentita rimane in attesa?? Così impara per la prossima volta...''. Beh, ci sono almeno tre buoni motivi per non lasciarlo in attesa: * A volte, quando vi collegate per esempio ad un server di posta elettronica, alcuni sistemi fanno quello che viene definito un ``ident lookup'', cercano cioè di capire chi siete collegandosi alla porta 113 della vostra macchina, dove teoricamente ci dovrebbe essere un demone in ascolto che fornisce questo tipo di informazioni. Il problema è che questi sistemi non vi fanno accedere al servizio fino a quando non scoprono la vostra identità o non appurano che il vostro sistema non offre questo servizio (rispondendo che la porta è chiusa). In entrambi i casi, il sistema remoto rimane in attesa di una risposta, e se questa non arriva, può ipotizzare due cose: 1. che la richiesta sia andata persa 2. che il vostro computer sia improvvisamente morto Proveranno quindi a rimandare il pacchetto per diverse volte prima di arrendersi e farvi entrare (ma come, il vostro computer non era morto? Non ha risposto quando abbiamo tentato di contattarlo...), introducendo spesso dei delay valutabili nell'ordine delle decine di secondi o addirittura dei minuti. L'esempio più classico è questo, ma altri protocolli usano un approccio simile, e vi posso garantire che una regola come la 38 può evitarvi diversi delay nell'utilizzo della rete altrimenti difficilmente spiegabili. * Molti ``scanner'' sono tratti in inganno da questa regola che fa credere loro che la porta sia effettivamente chiusa rendendo quindi più difficile l'identificazione del firewall (vi siete mai chiesti come nmap faccia ad indicare che una porta è ``filtered'' piuttosto che ``closed''?). Attenzione però che scanner più intelligenti potrebbero rilevare le differenze di TTL (il firewall si trova un passo prima del vero client), rendendo vano tale tentativo (se volete divertirvi, date un'occhiata al target TTL, che vi consente di evitare persino quest'effetto). Questa regola la vedrete apparire molto spesso nelle catene seguenti, sempre per lo stesso motivo... Dovremmo quindi aver finito con il traffico dalla LAN alla nostra DMZ. Dalla DMZ alla LAN Ok, qua (a dirsi) le cose sono molto più semplici: dobbiamo consentire soltanto quei pacchettini in risposta alle richieste partite dalla LAN (i server non si devono connettere di loro spontanea volontà ai nostri client -- teoricamente, nessuno dovrebbe usarli). Fare questo in ipchains era una cosa abbastanza complessa: bisognava specificare delle regole per consentire ogni tipo di pacchetto che ci sarebbe potuto tornare in risposta (giocando con l'opzione --syn, che seleziona i pacchetti che stabiliscono nuove connessioni) e si doveva quindi avere una buona conoscenza (se non ottima) dei vari protocolli. iptables facilita molto le cose tramite l'introduzione di ``moduli per il tracciamento delle connessioni'' (conntrack -- uno dei molti vantaggi dei firewall statefull rispetto quelli stateless). Vediamo quindi una delle soluzioni che potremmo adottare: 40: iptables -A dmzlan -s ! 123.45.67.9/29 -j DROP 41: iptables -A dmzlan -m state --state ESTABLISHED,RELATED -j ACCEPT 42: iptables -A dmzlan -p tcp -j REJECT --reject-with tcp-reset Bene, il primo comando è la solita regola per evitare lo spoofing. Il secondo invece, è diverso da ogni altro comando finora incontrato: -m chiede ad iptables di caricare un modulo esterno, in questo caso il modulo state (si ricorda lo stato delle connessioni), per il tracciamento delle connessioni. L'opzione --state relativa al modulo state è quello che ci permette di identificare i pacchetti: in pratica, la regola ha come significato quello di consentire tutti i pacchetti facenti parte connessioni già stabilite (ESTABLISHED, e se sono già stabilite vuol dire che sono state consentite) e tutte quelle connessioni relative a connessioni già esistenti (RELATED). In questo caso, la parolina magica è proprio RELATED. Ci consente cioè di scaricare sul modulo state la responsabilità di identificare i pacchettini che non soltanto sono risposte a pacchetti già inviati, ma anche quelli che fanno parte dello stesso protocollo. Vediamo però qualche esempio: * Quando volete scaricare un file tramite ftp il vostro browser (o qualsivoglia programma stiate utilizzando) apre prima una connessione di controllo sul server remoto, sulla classica porta 21. Dopodiché si mette d'accordo con il computer remoto su una porta da utilizzare per creare una nuova connessione per l'invio dei dati. Ma proprio qui sorge il problema: per passare dal nostro firewall (che ha una politica di DROP), questa connessione dovrebbe essere esplicitamente consentita a priori con una regola che termina con un -j ACCEPT. A priori, però, non possiamo creare questa regola in quanto non sappiamo le porte che verranno utilizzate (possono essere liberamente negoziate sia dal client che dal server). La soluzione normalmente adottata prima dell'introduzione dei moduli di tracciamento era molto semplice: consentire tutte le connessioni salvo quelle a porte problematiche. Il modulo state, invece, ci viene in aiuto aggiungendo e rimuovendo regole dinamicamente secondo quanto necessario. * Il protocollo ip lavora in collaborazione con il protocollo ICMP che viene utilizzato per la segnalazione e la gestione degli errori. Ebbene, senza utilizzare il modulo state con l'opzione RELATED, avremmo dovuto impostare per ogni connessione consentita una regola del tipo ``consenti tutti i messaggi di errore relativi a questa connessione'', oppure consentire l'entrata di tutti i pacchetti ICMP di alcuni tipi. Bene, il modulo state si prende in carico anche di questo aggiungendo e togliendo regole dinamicamente ed in maniera trasparente. La differenza è quindi questa: ESTABLISHED, fa passare tutti i pacchetti che fanno parte di una connessione già stabilita, mentre RELATED fa passare tutti i pacchetti di controllo (errori, piuttosto che...) o connessioni relative alle connessioni conosciute. Se state configurando un firewall, però, e la vostra preoccupazione principale è la sicurezza, vi sarà sorta spontanea una domanda: ``e se qualcuno imbrogliasse il modulo di state, facendo aprire connessioni non volute?''. Bene, in passato qualche problema di questo tipo è stato sollevato, ma il codice del netfilter dovrebbe essere attualmente abbastanza maturo per evitare questo tipo di problemi. Vi consiglio però di seguire le mailing list dedicate, per essere eventualmente prontamente avvisati di possibili problemi, e di leggere qualche documento in più sul funzionamento del protocollo ftp. Attenzione però che perché le regole sopra elencate funzionino, potrebbe essere necessario caricare dei moduli nel kernel, con comandi del tipo ``modprobe ip_conntrack'', ``modprobe ip_conntrack_ftp'', ``modprobe ip_conntrack_altri_moduli_di_protocolli_che_volete_utilizzare''. Per quanto riguarda le prestazioni, il modulo state utilizza un po' più di risorse rispetto alle regole manuali, ma comunque nulla di rilevante se rapportato ai vantaggi che offre (alcune cose, non è proprio possibile farle con firewall stateless, a meno di non aprire migliaia di porte). Un'altra cosa da dire è che prima, nella definizione della catena dalla LAN alla DMZ, ho volutamente dimenticato la regola 37: 37: iptables -A landmz -m state ESTABLISHED,RELATED -j ACCEPT che sarebbe stata troppo prematura da discutere. In pratica, anche dalla lan alla dmz è importante far passare tutti quei dati relativi a connessioni già stabilite o comunque i messaggi di errore. Probabilmente non molto importante per reti di piccole dimensioni, ma rilevante in reti più grosse o con regole più complicate. Anche questa regola la vedrete apparire molto spesso. Dalla LAN ad Internet Dalla nostra lan ad internet vogliamo invece essenzialmente che passi traffico ftp (che non può essere deviato sul proxy), in modo che gli utenti possano scaricare direttamente il loro materiale. Per fare questo, basta aggiungere le regole: 44: iptables -A laninet -s ! 192.168.200.0/24 -j DROP 45: iptables -A laninet -p tcp --dport ftp -j ACCEPT 48: iptables -A laninet -m state ESTABLISHED,RELATED -j ACCEPT 49: iptables -A laninet -p tcp -j REJECT --reject-with tcp-reset Dove però non c'è nulla di nuovo di cui parlare... Da Internet alla LAN Infine, per terminare con la nostra lan: 50: iptables -A inetlan -s 192.168.200.0/24 -j DROP 51: iptables -A inetlan -s 123.15.67.9/29 -j DROP 52: iptables -A inetlan -m state --state ESTABLISHED,RELATED -j ACCEPT 53: iptables -A inetlan -p tcp -j REJECT --reject-with tcp-reset In questo caso, le prime due regole bloccano tutti quei pacchetti che hanno come mittente l'indirizzo di una delle nostre due reti. La terza regola, invece, consente a tutte le connessioni create dall'interno di poter ricevere una risposta, senza dover scrivere troppe regole. All'epoca di ipchains invece, non c'era un modo di ``tenere traccia'' delle connessioni ed era quindi necessario aprire molte più porte per consentire a ftp di funzionare, cosa che diminuiva notevolmente l'efficacia del firewall. Da Internet alla DMZ Andiamo avanti ora con la configurazione della nostra dmz. Abbiamo detto che da internet saranno accessibili i seguenti servizi: * server web * server smtp * server dns * server ftp Che si traduce linearmente in qualcosa del tipo: 54: iptables -A inetdmz -s 192.168.200.0/24 -j DROP 55: iptables -A inetdmz -s 123.15.67.9/29 -j DROP 56: iptables -A inetdmz -p tcp -d nostro.server.web --dport www -j ACCEPT 57: iptables -A inetdmz -p tcp -d nostro.server.smtp --dport smtp -j ACCEPT 58: iptables -A inetdmz -p tcp -d nostro.dns --dport domain -j ACCEPT 59: iptables -A inetdmz -p udp -d nostro.dns --dport domain -j ACCEPT 60: iptables -A inetdmz -p tcp -d nostro.ftpserver --dport ftp -j ACCEPT 61: iptables -A inetdmz -m state --state ESTABLISHED,RELATED 62: iptables -A inetdmz -p tcp -j REJECT --reject-with tcp-reset In questo caso, la prima regola è un po' superflua ma estremamente importante. I nostri server, infatti, potrebbero essere configurati per essere un po' meno restrittivi nei confronti dei nostri utenti. Se qualcun altro riuscisse da internet ad usare i nostri indirizzi ip, sarebbe in grado di usufruire di questi benefici. Dalla DMZ ad Internet Dalla DMZ ad Internet, invece 63: iptables -A dmsinet -s ! 123.15.67.9/29 -j DROP 64: iptables -A dmzinet -p tcp -s nostro.server.smtp --dport smtp -j ACCEPT 65: iptables -A dmzinet -p udp -s nostro.server.dns --dport domain -j ACCEPT 66: iptables -A dmzinet -p tcp -s nostro.server.dns --dport domain -j ACCEPT 67: iptables -A dmzinet -p tcp -s nostro.server.proxy --dport www -j ACCEPT 68: iptables -A dmzinet -m state --state ESTABLISHED,RELATED -j ACCEPT 69: iptables -A dmzinet -p tcp -j REJECT --reject-with tcp-reset Qui qualche commento è doveroso farlo... La prima regola consente al server smtp di inviare la posta elettronica dei nostri utenti. Dello stesso tipo sono la seconda e terza regola, che consentono invece al dns server di effettuare delle query ricorsive ed eventualmente degli zone transfer. La quarta regola, infine, è quella che consente al proxy server di uscire all'esterno a procurarsi le pagine non in cache. Attenzione, però, che a secondo delle configurazioni del vostro proxy server, potrebbe essere necessario aprire più porte (per fare comunicare più proxy tra di loro, per consentire l'utilizzo al proxy del protocollo ftp...). Le ultime due sono le solite regole: consenti le risposte alle richieste effettuate, chiudi le connessioni tcp vietate. Traffico da e per il firewall Come ultima cosa, ci rimane da filtrare il traffico originato o destinato al firewall direttamente. Giusto a titolo esemplificativo, ecco alcune regole: 71: iptables -A INPUT -m limit --limit 10/min -p tcp --syn --dport ssh -j ACCEPT 72: iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT 73: iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 74: iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset 75: iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT Buona norma sarebbe quello di consentire il meno possibile verso il firewall, e di bloccare tutto ciò che può da lui essere originato. In questo caso, viene accettato il traffico ssh ed i ping (non sempre una buona idea) e tutto il traffico relativo, mentre in uscita vengono consentite solo le risposte ai pacchettini ricevuti. Se utilizzate demoni come zebra o simili, potrebbe essere necessario aprire più porte ed allentare un po' la cintura soprattutto per quanto riguarda icmp. Ricordatevi inoltre che se non viene specificata esplicitamente una interfaccia, la catena di INPUT e di OUTPUT determineranno il comportamento di input e output da tutte le interfacce (compreso il loopback!!!). State quindi molto attenti a quello che fate. Potete vedere anche l'utilizzo di un nuovo modulo: il limit, che consente di impostare dei limiti di frequenza, e per la prima volta dell'opzione (tcp) --syn, che seleziona soltanto le nuove connessioni (i famosi pacchettini ``mandami il tuo numero''). Questo per evitare un problema con ssh segnalato diverso tempo fa (e probabilmente già corretto) per cui in determinate condizioni e con reti molto veloci era possibile fare hijacking di una connessione tentando di indovinare alcuni parametri. Ultima cosa importante da dire prima di passare ad altro: a differenza da ipchains, in iptables ciò che non è esplicitamente consentito non passa (o vice versa, a secondo della policy). Per esempio, nel nostro caso un client interno alla rete non potrebbe ``pingare'' alcun server all'esterno né sarebbe in grado di utilizzare altri messaggi ICMP che non siano imparentati (related) con connessioni esistenti. Con questo paragrafo viene chiuso l'argomento filtraggio. Nel prossimo paragrafo si parlerà infatti del NAT e di come fare quelle ``deviazioni'' di cui ci siamo temporaneamente dimenticati. Lo scopo era quello di introdurre l'utente all'uso di iptables e di metterlo nelle condizioni di poter leggere facilmente le pagine del manuale, dove può trovare un elenco di tutti i possibili match che si possono effettuare (divisi per protocollo e modulo) e di tutti i target che si possono utilizzare. Per le target extension installate con il patch-o-matic, riferitevi alla documentazione fornita. NAT con iptables Col paragrafo precedente abbiamo completato la configurazione di una piccola rete per quanto riguarda il filtraggio. Argomento di questa sezione è il NAT, ovvero ``Network Address Translation''. Il NAT consente ad un firewall o router linux di non limitarsi a bloccare o consentire i pacchetti in transito, bensì anche di modficarli secondo delle regole ben definite. Il codice che in linux gestisce il NAT è stato completamente ridisegnato per iptables ed il risultato è stato un sistema molto più pulito e flessibile rispetto quello utilizzato da ipchains. ipchains, per effettuare modifiche ai pacchetti, utilizzava semplicemente dei target diversi come MASQ (per mascherare i pacchetti). Questo però creava molta confusione sul meccanismo di scansione delle regole ed andava ad interferire con le regole di filtraggio. In iptables, invece, la parte di filtraggio dei pacchetti è completamente indipendente da quella di modifica e di gestione delle regole di nat. Per raggiungere questa indipendenza è stato infatti introdotto il concetto di ``tabella'' di cui fin'ora non avevamo parlato. Ebbene, le 3 catene principali di cui abbiamo parlato fin'ora (INPUT, OUTPUT, FORWARD) si trovano nella tabella ``filter''. La tabella di filter è quella che viene scelta in automatico se non viene specificata un'altra tabella (per questioni di compatibilità). Esistono quindi altre tabelle in iptables, ognuna delle quali mette a disposizione diverse catene di base: * la tabella filter, le cui catene principali sono INPUT, OUTPUT, FORWARD * la tabella nat, le cui catene principali sono PREROUTING, OUTPUT, POSTROUTING * la tabella mangle, le cui catene principali sono PREROUTING, OUTPUT Beh, ci sono 3 tabelle in totale. La prima, che normalmente non viene mai indicata esplicitamente, che serve per filtrare i pacchetti. La seconda, quella di nat, che serve normalmente per modificare ciò che ha a che vedere col mittente o il destinatario di un pacchetto, ed infine la tabella di mangle che consente di modificare tutte le altre caratteristiche dei pacchetti. La distinzione tra mangle e nat non è così netta, si tratta soltanto di un criterio di base, ed il manuale vi saprà sicuramente indicare la tabella migliore da utilizzare a secondo delle vostre necessità. Ma guardiamo meglio i nomi delle catene: nella tabella filter, ci troviamo le solite INPUT, OUTPUT, FORWARD, col significato che ormai conosciamo. Nella tabella di nat abbiamo invece 3 nuove catene: la catena di PREROUTING, la catena di OUTPUT e la catena di POSTROUTING. La catena di OUTPUT mantiene lo stesso significato che aveva nella tabella di filter. La catena di PREROUTING e quella di POSTROUTING classificano invece i pacchetti diversamente: non più in base alla direzione dei pacchetti, bensì al fatto che sia già stata presa una decisione di routing su questi pacchetti. Vediamo di spiegare meglio l'idea: quando un pacchetto di qualsiasi protocollo deve uscire da una macchina connessa ad una rete (poco importa la provenienza del pacchetto) deve essere presa una decisione di routing. Deve cioè essere stabilito da che interfaccia dovrà uscire questo pacchetto e con quali caratteristiche dovrà essere mandato (es, il TTL dovrebbe essere decrementato, l'MTU potrebbe essere diverso e necessitare una frammentazione, l'indirizzo hardware specificato potrebbe essere quello di un gateway...). Dal punto di vista logico, quindi, ogni pacchetto che deve uscire da un'interfaccia di rete passa prima dalla catena di PREROUTING, viene presa una decisione sull'interfaccia da cui fare uscire il pacchetto, dopodichè passa dalla catena di POSTROUTING. PREROUTING e POSTROUTING sono state introdotte proprio per consentire di realizzare diversi comportamenti: ad esempio, se si vuole cambiare l'indirizzo di destinazione di un pacchetto sarà importante farlo prima che venga deciso da dove fare uscire il pacchetto (se così non fosse, il pacchetto uscirebbe dall'interfaccia sbagliata, a meno che questo non sia l'effetto desiderato). Mentre, al contrario, quando si cambia il mittente di un pacchetto potrebbe essere importante farlo dopo che una decisione di routing è stata presa (in questo caso però l'errore non sarebbe così palese). Comunque sia, in ognuna di queste tabelle è possibile specificare dei target differenti utilizzando però le stesse opzioni e gli stessi moduli per creare delle regole. Di base, i target più conosciuti per la tabella di NAT sono proprio: * SNAT consente di cambiare l'indirizzo ip sorgente di un pacchetto (POSTROUTING) * DNAT consente di cambiare l'indirizzo ip destinazione di un pacchetto (PREROUTING) * MASQUERADE consente di cambiare l'indirizzo ip sorgente di un pacchetto (verrà spiegata in seguito la differenza - POSTROUTING). * REDIRECT consente di cambiare la porta di destinazione di un pacchetto (PREROUTING) Torniamo ora al nostro esempio: la nostra lan utilizza degli indirizzi ip del tipo 192.168, e come tali non possono viaggiare su internet (192.168 è una classe di indirizzi ip riservati per reti private). Per consentire quindi ai computer della nostra rete di navigare, sarebbe necessario o un proxy (che però gestisca tutti i protocolli) o fare in modo che l'indirizzo ip sorgente dei pacchetti originati dalla nostra rete venga cambiato con un indirizzo ip valido per viaggiare in internet (come quello del nostro firewall, per esempio). Realizzare questo a livello di regole di iptables è estremamente facile. Bisogna però fare una piccola introduzione e dare un minimo di spiegazioni. A molti di voi, ad esempio, sarà sorto spontaneo chiedersi come diavolo può fare un firewall a nascondere 20 computer (per esempio) dietro un unico indirizzo ip. Voglio dire, in uscita funziona bene: il client FOO dietro il firewall manda un pacchettino al gateway (il nostro firewall), il nostro firewall cambia l'indirizzo ip sorgente col suo (valido su internet) e manda avanti il pacchettino, il server remoto risponde, il pacchettino torna indietro, e... il pacchettino che gli torna indietro ha come mittente il server remoto, come destinatario il firewall... non sembra funzionare tanto... come fa il firewall a capire a quale dei nostri client deve rimandare il pacchetto, se l'indirizzo di destinazione è il suo indirizzo esterno? E anche ipotizzando di avere un indirizzo ip solo per i client, come farebbe a mandare la risposta al client corretto? Se guardasse l'indirizzo ip del server remoto, solo un client per volta potrebbe navigare su un determinato sito... non proprio funzionale. Una soluzione potrebbe essere quella di avere tanti ip esterni quanti client. Ma allora perché usare il nat? La sicurezza potrebbe essere un buon motivo, ma normalmente il nat si usa quando ci sono meno (o molti meno) indirizzi esterni a disposizione rispetto ai client della propria rete (attualmente, gli indirizzi ip hanno un costo, e non indifferente). Beh, la soluzione che è stata trovata per risolvere questo problema si basa sull'idea di porta. Quando stabilite una connessione tcp verso un server, l'unica porta veramente importante è quella di destinazione, che identifica univocamente un servizio. Quella mittente, invece, non viene quasi mai guardata e spesso viene scelta a caso. Con il NAT, il nostro firewall linux cambierà (se necessario) la porta sorgente dei pacchetti in uscita ed utilizzerà quella per identificare univocamente un client. Se la soluzione vi convince poco, provate a pensare al flusso dei pacchetti... il client A manda un pacchetto proveniente da A porta x al server B porta 80. Il firewall riceve il pacchetto, cambia x in y (dove x può essere uguale a y, se tale porta non è utilizzata da nessuno), si segna che y è associata solo ad A e cambia l'indirizzo ip sorgente con il suo, il pacchetto arriva al server remoto R porta 80 come proveniente da F:y, e risponde creando un pacchetto proveniente da R:80 e destinato al firewall F porta y. Firewall riceve il pacchetto, vede che la connessione non è stata creata direttamente da lui (ogni sistema operativo sa quali connessioni ha iniziato) cerca nella tabella e vede che la porta y era in origine x ed era associata al client A. Prende il pacchetto, modifica il destinatario in modo che indichi A porta x e rimanda il pacchetto ad A. Sembra funzionare, no? L'idea è abbastanza furba e permette di identificare univocamente un client utilizzando qualche bit in più di informazioni. Il problema è che a volte questa tecnica non funziona: * ad esempio, quando la trasmissione non fa uso del concetto di porta (solo le trasmissioni tcp e udp hanno delle porte associate). Fortunatamente però, oltre all'icmp, non esistono protocolli realmente utilizzati che non usino il concetto di porta, e gli errori sono facilmente associabili (non sono specifici al client: se un server non è raggiungibile, questo non sarà raggiungibile per tutti i client dietro al NAT box). Cioè, questi protocolli esistono ma vengono comunque normalmente gestiti non dal kernel ma da demoni dedicati per cui il problema non si pone. * ad esempio, quando c'è bisogno che i pacchettini provengano da una porta specifica: un client, nascosto dal firewall, non saprà mai in realtà che porta sorgente utilizzerà il firewall per rispedire i suoi pacchetti. * ad esempio, quando il protocollo si basa su connessioni effettuate da un server esterno verso un client interno. Per vedere dove sta il problema, proviamo a vedere un esempio. Ipotizziamo che il solito client FOO si colleghi a uno strano server con uno strano protocollo. Per via di questo strano protocollo, il server deve aprire una connessione verso la porta 789 del client e tenta quindi di collegarsi. Quello che però per lui è l'indirizzo del client è in realtà l'indirizzo del firewall, per via del NAT che ha cambiato l'indirizzo del mittente. Così facendo, il server tenterà di collegarsi al firewall, che però questa volta non avrà nessuna associazione nella sua tabella (l'associazione si crea solo per le connessioni che escono, e non è possibile indovinarle per quelle che entrano, a meno che non vengano stabilite a priori dall'amministratore) e sarà quindi costretto a buttare via il pacchetto rispondendo al server con un messaggio icmp con scritto qualcosa del tipo ``la porta è chiusa e io non so chi tu sia''. Fortunatamente però il primo caso è estremamente raro (non credo sia stato mai nemmeno preso in considerazione il problema), il secondo capita ancora molto raramente, mentre per il terzo esistono delle soluzioni: il tracciamento delle connessioni. Infatti, i moduli del kernel prima caricati che si occupavano di aprire o chiudere dinamicamente le porte sono anche in grado di aggiungere o rimuovere associazioni dalla famosa tabella, o di fare delle piccole modifiche al protocollo in modo che questo possa funzionare. Per fare questo però, se non avete compilato staticamente il kernel, dovete caricare anche i moduli ``ip_nat_ftp'', ``ip_nat_irc'' o ``ip_nat_protocollo_strano_che volete usare'' con il solito ``modprobe''. Il problema che a volte si incontra, però, è che questi moduli non sono proprio facili da scrivere, per cui è relativamente facile trovarne per i protocolli standard, mentre non esistono per quei protocolli inventati dalla fantasia dei venditori di software di turno, che non sentono il dovere morale di rispettare degli standard. Normalmente i problemi si incontrano solo per parti dei vari ``protocolli'' (ad esempio, dietro un firewall linux di questo tipo, col messanger sarebbe difficile farsi mandare dei file da altri utenti, pur funzionando per tutte le altre cose). E se per ftp e IRC (anche netmeeting, ma sperimentale) sono stati scritti dei moduli, per altri protocolli meno utilizzati credo che sarà difficile che qualcuno si occupi di realizzarli. In questi casi, un ``socks server'' vi consentirà il più delle volte di rendere felici i vostri utenti. Il prezzo da pagare è che un socks server di base è molto aperto ed una configurazione errata o superficiale di questo potrebbe vanificare completamente i vostri sforzi. In più, preparatevi a ricevere chiamate a tutte le ore del tipo ``come si fa ad impostare il socks server su fuffolo 3.0 piuttosto che kazzat 2.8''... Passando dalla teoria alla pratica, occorre prima di tutto parlare in maniera un pochettino più approfondita dei target di default messi a disposizione dalla tabella di NAT. * SNAT: serve per modificare il mittente di un pacchetto (l'indirizzo ip sorgente). Viene utilizzato nella catena di POSTROUTING proprio perché il cambiare il mittente non interferisce sulla scelta dell'interfaccia da utilizzare per raggiungere il destinatario. Consente anche di modificare manualmente la porta sorgente di un pacchetto. Attenzione! Funziona solo con indirizzi ip statici! * DNAT: serve per modificare il destinatario di un pacchetto (l'indirizzo ip destinatario). Viene utilizzato nella catena di PREROUTING in quanto la modifica deve essere effettuata prima di decidere da che parte fare uscire il pacchettino. E' possibile inoltre specificare una diversa porta di destinazione. * MASQUERADE: è un tipo particolare di SNAT: fa in modo che i pacchettini abbiano come mittente l'indirizzo IP della interfaccia di rete dalla quale usciranno. Si utilizza nella tabella di POSTROUTING (modifica il mittente) e viene utilizzato al posto dello SNAT su interfacce con IP assegnato dinamicamente, ad esempio tramite dhcp o bootp. * REDIRECT: è una versione semplificata del DNAT mantenuta più che altro per motivi di compatibilità e fa in modo che il pacchettino venga rediretto sulla macchina locale (127.0.0.1) ad una porta specifica. Equivale a qualcosa del tipo: -j DNAT --to 127.0.0.1:porta <--> -j REDIRECT --to-ports porta. Esistono molti altri target che possono essere aggiunti tramite il patch-o-matic adatti a tutte le esigenze. Date un'occhiata al manuale di iptables ed alle informazioni mostrate sullo schermo durante l'aggiornamento di iptables per maggiori informazioni. Tornando invece al nostro esempio (presentato nei paragrafi sul filtraggio), è per noi indispensabile utilizzare il NAT in quanto: * dobbiamo ``deviare'' tutti le connessioni web verso internet sul nostro proxy server che si trova nella dmz (transparent proxy). * dobbiamo fare in modo che la nostra rete interna che utilizza indirizzi ip di classe 192.168.200.x (indirizzi per reti private) possa navigare su internet. Avendo però spesso a che fare con reti di discrete dimensioni dove il dhcp è raramente utilizzato, mi piace aggiungere alcune regole per rendere le macchine ``indipendenti'' dalle modifiche del provider di turno o eventuali riconfigurazioni della rete (vi è mai capitato di dover cambiare l'ip del dns su n macchine diverse, dove n tende ad infinito?). Per fare questo normalmente si possono utilizzare diversi approcci: * Se la rete è divisa in diverse sottoreti (subnet), si possono ``inventare'' due indirizzi ip che non risiedano su nessuna delle nostre reti ed impostare tutti i client per utilizzare quegli indirizzi ip come dns primario e secondario. * Si possono semplicemente deviare tutti i pacchetti destinati ad un dns verso il dns reale (c'è il problema del dns secondario, però). * Semplicemente ignorare il problema inizialmente ed in caso di cambio di ISP aggiungere due regole per deviare il traffico sui nuovi dns. Trattandosi comunque di regole abbastanza semplici ed interessanti dal punto di vista didattico, verranno presentate tutte e tre le soluzioni (la prima è quasi perfettamente equivalente alla terza). Vediamo quindi le nostre prime regole di NAT: 77: iptables -t nat -A PREROUTING -p tcp -i eth0 --dport www -j DNAT --to nostro.proxy.server:8080 78: iptables -t nat -A POSTROUTING -o eth2 -s 192.168.200.0/24 -j SNAT --to 123.45.68.1 Ok, la prima regola dice, a parole, di inserire una regola nella tabella di nat per intercettare tutti i pacchetti provenienti da eth0 e destinati ad un server www (porta 80 -- prima che venga deciso da che interfaccia farli uscire) e di deviarli sul nostro.proxy.server porta 8080. Attenzione però che proxy server come squid devono essere configurati per poter accettare connessioni deviate in questo modo, in quanto non seguono perfettamente lo standard utilizzato dai proxy (leggete la documentazione di squid!). Tornando a parlare delle regole, la seconda dice di modificare il mittente (l'indirizzo ip sorgente) dei pacchetti uscenti da eth2 e provenienti dalla nostra LAN (192.168.200.0/24) con l'indirizzo ip esterno del nostro firewall. A proposito di queste due regole ci sono alcune cose importanti da dire: * Prima di tutto, nella prima regola si è reso necessario indicare la scheda di rete sorgente in modo da non deviare le richieste del nostro proxy server. Per la cronaca: quando facciamo una richiesta al nostro proxy server, questo se non ha le pagine richieste in cache dovrà collegarsi al server web richiesto, e dobbiamo quindi stare attenti a non deviare anche le richieste provenienti dal proxy (si creerebbe una sorta di circolo vizioso (loop) né molto bello né molto positivo per la salute della nostra rete). * Nella seconda regola, invece, è importante fare in modo che soltanto i pacchetti provenienti dalla nostra rete interna (e non dalla DMZ!) vengano modificati e soltanto quelli uscenti verso internet (quelli destinati al nostro proxy non devono essere toccati: saremo così in grado di fare un minimo di statistiche sui siti più interessanti per i nostri utenti). * Nella seconda regola, è fondamentale fare in modo che i pacchetti abbiano come mittente uno degli indirizzi ip esterni del firewall. Per chi si accontenta di poche parole, basti dire che in caso contrario non funzionerebbe. Per tutti gli altri, invece, il motivo sta nell'arp, address resolution protocol. Ovvero, se l'indirizzo ip non fosse uno di quelli del firewall (aggiunti con ip o ifconfig, per intenderci), il firewall non risponderebbe alle query ARP, ed i pacchetti uscirebbero felici dalla rete ma il gateway di default del nostro firewall non sarebbe in grado di rimandare i pacchetti indietro. Come sempre, linux lascia la massima libertà: sta all'amministratore evitare di farsi male con errori di questo tipo. * Riferendosi al funzionamento del SNAT come prima descritto, a volte (in reti particolarmente affollate) potrebbe essere indispensabile utilizzare più indirizzi ip per effettuare lo SNAT (il numero di porte disponibili ed utilizzabili su un host per fare il giochettino descritto è abbastanza limitato). Il target fortunatamente consente di indicare più indirizzi ip (date un'occhiata al manuale di iptables). L'esperienza però mi insegna che in tali reti si supererebbe molto prima il numero massimo di connessioni tracciabili rispetto alle porte disponibili. Per aumentare questo numero, basta dare un: echo 16384 > /proc/sys/net/ipv4/ip_conntrack_max o, in maniera del tutto equivalente, scrivere qualcosa come net.ipv4.ip_conntrack_max=16384 nel file /etc/sysctl.conf. Comunque sia, tenete presente che già una rete di 100-200 computer potrebbe aver bisogno di essere in grado di tracciare più connessioni, mentre non mi è ancora capitato di dover utilizzare più di un indirizzo ip in uscita. Il kernel comunque, vi avviserà in caso fosse necessario aumentare questi limiti, con un messaggio nei log per ogni connessione scartata. * Nell'ultima regola, infine, se avessimo avuto a disposizione una connessione dial-up (come isdn) o tramite adsl con indirizzi ip assegnati dinamicamente, si sarebbe dovuto usare come target ``MASQUERADE'', senza però specificare alcun indirizzo ip sorgente. Attenzione! Lo SNAT proprio non funziona su interfacce con ip dinamici assegnati! Potete vedere un esempio di come utilizzare il target MASQUERADE in uno dei paragrafi introduttivi... * Per quanto riguarda le regole di NAT e filtraggio, è fondamentale notare (per poter ottenere un firewall funzionante) che le regole di firewalling, inserite nella tabella di filter, vedranno i pacchetti con i loro indirizzi reali. Nel caso di DNAT, per esempio, il filtro vedrà pacchetti con la destinazione modificata (in questo caso, il proxy server). In caso invece di SNAT, il filtro vedrà come mittente l'indirizzo reale del mittente (non quello modificato), come se il codice di filtraggio fosse inserito dopo la catena di PREROUTING ma prima della catena di POSTROUTING. Volendo fare il giochettino con il DNS, le due possibilità sono realizzabili utilizzando o queste regole: 80: iptables -t nat -A PREROUTING -p tcp --dport domain -j DNAT --to nostro.dns 81: iptables -t nat -A PREROUTING -p udp --dport domain -j DNAT --to nostro.dns che deviano tutto il traffico verso un qualsiasi dns su nostro.dns, o queste altre, che similmente intercettano il traffico verso un dns da noi specificato e deviano il traffico verso il nostro dns reale: 83: iptables -t nat -A PREROUTING -p tcp -d un.dns --dport domain -j DNAT --to nostro.dns 84: iptables -t nat -A PREROUTING -p udp -d un.dns --dport domain -j DNAT --to nostro.dns