Sveliamo i misteri di Firewalld (Parte 1 di 2)
![]()
N.B. Sono stato costretto a spezzare l'articolo perché, quello originale di 8836 parole (per un totale di 76309 bytes effettivi), veniva troncato dopo il salvataggio a 7533 parole (65.356 bytes), cosa che mi fa sospettare che la grandezza del body non possa superare i 64k.
firewalld fornisce funzionalità firewall fungendo da frontend per netfilter.
Nell'interagire con netfilter, analogamente a ufw con iptables, firewalld usa come backend nftables, un tool nella user-space del kernel linux, che va a sostituire proprio iptables. Entrambi i backend forniscono filtraggio e classificazione dei pacchetti di rete /datagrammi/frame.
- 1. Come ragiona firewalld
- 2. Come procedo nella configurazione di Firewalld?
- 3. Il man di firewall-cmd
- 4. Come configurare firewalld
Attualmente ufw usa ancora iptables ma in modalità legacy, consistente in uno strato software che traduce i comandi iptables nei corrispondenti comandi nftables.
Firewalld supporta le zone di rete/firewall che definiscono il livello di fiducia delle connessioni o delle interfacce di rete.
C'è una separazione fra runtime e configurazione permanente che consente di testare una configurazione prima di renderla effettiva.
firewalld, con nftables, è certamente il frontend ideale per netfilter dal momento che recepisce tutte le sue innovazioni. La possibilità di usare, nella stessa cli, filtraggio, routing, snat e dnat per es. rende l'esperienza certamente più omogenea (con ufw, masquerade e port-forwarding richiedono una gestione aggiuntiva direttamente con iptables per ora).
Sebbene destinato ad essere rimpiazzato, iptables continua ad avere una sua specificità visto che viene ancora usato da docker per agire direttamente su netfilter bypassando eventuali firewall locali quano deve esporre una porta.
Con l'attuale versione di docker, la 29, è stato introdotto il supporto diretto su nftables in via sperimentale.
Ad ogni modo, chi approccia per la prima volta a firewalld (come è successo a me) all'inizio può essere sopraffatto dall'allegro affollamento di opzioni a disposizione.
- zone
- porte
- protocolli
- servizi
- policy objects
- rich-rules
- port forwarding
- masquerade
- ipset
- helper
- ....
La gui (firewall-config) mette certamente ordine ma non aiuta fino in fondo. Oltre a questo la gui non racchiude tutta la logica della cli (ad es. mancano i policy objects).
La cli di firewalld è il riferimento e come tutte le cli, può spaventare.
In realtà la cli, firewall-cmd nello specifico, è una delle più pulite e lineari che conosca, basta conoscere gli la logica a oggetti che governa firewalld.
1. Come ragiona firewalld
Se guardassi firewalld dall'alto, riconoscerei 7 oggetti principali:
- Zone
- Policy Objects
- Services
- IPSet
- ICMP Types
- Helper
- Direct Options (Deprecato)
Zone: è un po' il tratto distintivo di firewalld. Concettualmente rappresenta il livello di fiducia che si ha nei confronti di una rete connessa a una specifica interfaccia (es. eth0) o di un indirizzo IP. Ogni pacchetto dati che entra nel server viene catturato da una zona in base alla sua sorgente o all'interfaccia da cui arriva. È qui che avviene la configurazione del traffico in ingresso.
Policy Objects: è una delle novità di firewalld. I policy object nascono per gestire il traffico inter-zona. Inizialmente il filtraggio avveniva all'interno dell'oggetto (la zona) che accoglie il pacchetto, ora viene disaccoppiato e trasferito in un altro oggetto che gestisce il transito dei pacchetti tra una zona e l'altra (o se stessa). In questo modo cambia profondamente il paradigma di manipolazione dei pacchetti. La zona attiva il filtraggio quando il pacchetto entra da una delle sorgenti associate alla zone. La policy, attiva il filtraggio quando il pacchetto transita tra le zone specifiche definite dalla policy.
Services: rappresenta ciò che esponiamo (o che dobbiamo raggiungere, se filtriamo il traffico in uscita dal nostro host quando si comporta da client).
L'IPSet: permette di definire dei blocchi di ip a cui applicare regole massivamente invece che definirle puntalmente.
ICMP Types: è relativo ai pacchetti ICMP e permette di rendere disponibile il pacchetto scelto al traffico di tipo ipv4 e/o ipv6
Helper: torna comodo invece per quei protocolli che aprono una connessione su una porta e poi negoziano dinamicamente un'altra porta per il trasferimento dei dati (es. ftp, netbios-ns, sip, vecchi protocolli di gaming/streaming ecc.). Invece che aprire un intervallo ampio di porte, l'helper, che è un modulo del kernel, “ascolta” il flusso di controllo, capisce quale porta casuale sta per essere usata e la apre temporaneamente al volo solo per quel trasferimento.
Direct Options: le direct options (ormai deprecate e sostituite dai policy objects) sono la parte legacy di firewalld attraverso cui parla con iptables invece che con nftables.
Questi sono gli oggetti principali su cui si costruiscono le regole per il firewall attraverso una sintassi molto corposa ma ragionata e lineare.
La cli mette a disposizione delle istruzioni per fare praticamente qualunque cosa:
- visualizzare lo stato del firewall;
- istanziare gli oggetti;
- combinare gli oggetti istanziati al fine di creare la nostra logica di firewalling;
- effettuare delle query di verifica esistenziale sugli oggetti;
- effettuare il binding delle zone con interfacce o sorgenti;
Da tenere presente che la configurazione di firewalld, come iptables, può essere effimera. Se la configurazione a caldo non viene resa “permanente”, produce effetti fino a quando il servizio viene riavviato. Quando avviene, lo stato di firewalld ritorna ad essere quello che era prima delle modifiche.
2. Come procedo nella configurazione di Firewalld?
Come abbiamo visto, firewalld ha una logica di funzionamento molto più versatile di iptables, decisamente più rigido al confronto. Questa versatilità però può portare a rendere gli scenari più caotici potendo mescolare diverse tecniche di filtraggio. Come dire, il solito problema della scelta quando ce n'è troppa.
My two cents:
- Se l'esigenza è quella di configurare un firewall personale, è sufficiente configurare opportunamente zone e servizi.
- Se bisogna tenere in considerazione traffico inter-zona (in presenza di più interfacce per es.) ci vengono in aiuto i policy objects.
- Se abbiamo ulteriori esigenze di granularità, la zona permette di definire delle rich-rules.
Un canovaccio del genere aiuta a mantenere la configurazione pulita, altrimenti potrei sporcarla in mille modi differenti rendendo però complicata la manutenzione futura.
Cercando di mettere a fattor comune quello che faccio con firewall-cmd la maggior parte delle volte, se volessi configurare un firewall personale secondo il canovaccio di cui sopra, i passi da fare sono i seguenti:
- creo la zona
- se non sono presenti nel default perché magari le porte dei servizi sono custom, creo anche i servizi (descrizione, porta/e e protocollo/i)
- nella configurazione della zona, faccio il binding con l'interfaccia e con i servizi (eventualmente custom) che ho definito.
Stop.
Non occorre altro.
Ma firewalld permette anche configurazioni molto più borderline.
Nella mia zona potrei non avere alcun oggetto di tipo servizio ma potrei semplicemente assegnare direttamente una sbrodolata di porte e protocolli.
Oppure potrei lavorare direttamente con le rich-rules (approccio simil-ufw).
Oppure potrei affidare la logica direttamente ai policy objects.
Personalmente, tutte queste alternative (a parte l'ultima) le vedo più come un esercizio accademico senza una reale utilità pratica perché in scenari complessi questi approcci possono dar luogo a configurazioni estremamente caoitche.
3. Il man di firewall-cmd
Il man di firewall-cmd è molto chiaro e lineare e sarebbe bene tenerlo presente quando ci si lavora per le prime volte.
È strutturato in 3 grossi blocchi:
Sezioni di carattere generale. Stato firewall, verbosity log, salvataggio configurazioni, ecc
- General Options
- Status Options
- Log Denied Options
- Permanent Options
- Panic Options
Sezioni per la configurazione delle componenti core. Zone , Policy Objects, IPSet, Service, ecc.
- Zone Options
- Policy Options
- IPSet Options
- Service Options
- Helper Options
- ICMP type Options
- Direct Options (deprecato)
Sezioni per l'interrogazione e la configurazione delle combinazioni fra zone, policy objects, interfacce e sorgenti
- Options to Adapt and Query Zones and Policies
- Options to Adapt and Query Zones
- Options to Adapt and Query Policies
- Options to Handle Bindings of Interfaces
- Options to Handle Bindings of Sources
4. Come configurare firewalld
Come anticipato, la configurazione della zona con associati servizi, interfaccia e sorgenti, è tutto ciò che serve.
Se le mie policy sono complesse e ho necessità di centralizzarle, posso usare i policy objects.
Se si deve intervenire chirurgicamente per impedire o abilitare del traffico, ci sono le rich-rules.
In sostanza, tutto ruota attorno a due grossi item, le zone e i policy objects, che, forse in maniera un po' ridondante, combinano una serie di componenti che concorrono a formare la logica di firewalling.
Per entrare nel merito della configurazione partirò da quelle che per me sono le “foglie” di un ipotetico albero che, attraverso una serie di inclusioni, termina con 2 grosse radici: zone o police objects.
Fra gli elementi terminali nella gerarchia di firewalld, per me, ci sono gli helpers che poi concorrono a formare i servizi che insieme a porte e protocolli, IPset, forwarding, masquerade finiranno in zone, policy objects e rich-rules.
4.1. Helpers
Gli helpers sono degli oggetti basati sul modulo nf_conntrack del kernel Netfilter, che permettono di tracciare le connessioni, per la precisione sono delle interfacce che permettono a firewalld di caricare e configurare il relativo modulo nf_conntrack del kernel.
Ci sono protocolli come ftp, tftp, alcuni protocolli di gaming, voip ecc. che, oltre che esporre la porta per essere contattati, in un secondo momento devono negoziare dinamicamente con il client un'altra porta per lo scambio dei dati.
Questo tipo di servizi non è facilmente controllabile senza gli helpers perché la negoziazione dinamica imporrebbe di aprire un set molto ampio di porte.
Con gli helpers le connessioni di questi servizi “anomali” verranno tracciate in modo che, quando dal cliente arriva un pacchetto che richiede l'apertura di una porta random per lo scambio dati, quella connessione verrà marchiata come RELATED, che come tutto il traffico RELATED viene accettata nativamente, invece che come NEW che sarebbe destinata ad essere scartata.
Gli helpers, lista dei quali disponibile con:
firewall-cmd --get-helpers
corrispondono all'incirca ai moduli nf_conntrack presenti nel kernel Netfilter e si trovano in /lib/modules/$(uname -r)/kernel/net/netfilter.
Andranno aggiunti ai servizi, qualora servissero, in modo che firewalld accetti, e solo per quei servizi, connessioni da porte dinamiche.
Un po' di storia
In passato, il kernel linux abilitava (con qualcosa tipo nf_conntrack_helper=1) gli helpers per default su tutto il traffico favorendo attacchi basati sullo spoofing dei pacchetti con cui farsi aprire porte a caso.
Poi quest'opzione è stata prima disabilitata di defautl con nf_conntrack_helper=0 permettendo un'attivazione prudente solo da file di configurazione con AutomaticHelpers=yes/no/system, poi è stata definitivamente rimossa sia dal kernel che dal file di configurazione.
Oggi, per attivare gli helper, basta dichiararli e associarli ad un servizio. Firewalld provvederà a caricare dinamicamente solo i moduli del kernel Netfilter necessari gestendo sia la porta dalla quale il servizio verrà contattato sia le porte dinamiche che verranno negoziate per lo scambio dei dati.
# restituisce tutte le informazioni di un helper
firewall-cmd --permanent --info-helper="<nome_helper>"
# dichiaro un nuovo helper
firewall-cmd --permanent --new-helper="<nome_helper>" --module=nf_conntrack_<nome_modulo>
# restituisce tutti gli helper presenti
firewall-cmd --permanent --get-helpers
# imposta / restituisce una descrizione
firewall-cmd --permanent --helper="<nome_helper>" --set-description="<descrizione>"
firewall-cmd --permanent --helper="<nome_helper>" --get-description
# imposta / restituisce una descrizione breve
firewall-cmd --permanent --helper="<nome_helper>" --set-short="<descrizione>"
firewall-cmd --permanent --helper="<nome_helper>" --get-short
# aggiunge/rimuove la porta o il range di porte dall'helper
firewall-cmd --permanent --helper="<nome_helper>" --add-port=<port>[-<port>]/<protocol>
firewall-cmd --permanent --helper="<nome_helper>" --remove-port=<port>[-<port>]/<protocol>
# restituisce tutte le porte associate all'helper
firewall-cmd --permanent --helper="<nome_helper>" --get-ports
# imposta / restituisce un modulo per l'helper
firewall-cmd --permanent --helper="<nome_helper>" --set-module=nf_conntrack_<nome_modulo>
firewall-cmd --permanent --helper="<nome_helper>" --get-module
# rimuove un helper da sistema
--permanent --delete-helper="<nome_helper>"
4.2. Servizi
Per creare un servizio, si assegna un nome e un insieme di porte e protocolli.
firewall-cmd --permanent --new-service="<nome_servizio>"
firewall-cmd --permanent --service="<nome_servizio>" --set-description="Descrizione del servizio"
firewall-cmd --permanent --service="<nome_servizio>" [--add-port=<port>/tcp | udp | sctp | dccp]+
Di seguito una lista di comandi utili:
# elenco di tutti i servizi
firewall-cmd --get-services
# elenco dei servizi della zona attiva
firewall-cmd --list-services
# elenco dei servizi di una determinata zona
firewall-cmd --permanent --zone="<nome_zona>" --list-services
# restituisce le info di un servizio
firewall-cmd --permanent --info-service="<nome_servizio>"
# imposta / restituisce una descrizione
firewall-cmd --permanent --service="<nome_servizio>" --get-description
firewall-cmd --permanent --service="<nome_servizio>" --set-description="<descrizione>"
# imposta / restituisce una descrizione breve
firewall-cmd --permanent --service="<nome_servizio>" --get-short-description
firewall-cmd --permanent --service="<nome_servizio>" --set-short-description="<descrizione>"
# restituisce tutte le porte del servizio
firewall-cmd --permanent --service="<nome_servizio>" --get-ports
# imposta / restituisce un (o più) protocollo di un servizio
firewall-cmd --permanent --service="<nome_servizio>" --get-protocols
firewall-cmd --permanent --service="<nome_servizio>" [--add-protocol=tcp | udp | sctp | dccp]+
# rimozione (porta, protocollo) / protocollo
firewall-cmd --permanent --service="<nome_servizio>" [--remove-port=<port>/tcp | udp | sctp | dccp]+
firewall-cmd --permanent --service="<nome_servizio>" [--remove-protocol=tcp | udp | sctp | dccp]+
# aggiunge / rimuove un helper da un servizio
firewall-cmd --permanent --service="<nome_servizio>" --add-helper="<nome_helper>"
firewall-cmd --permanent --service="<nome_servizio>" --remove-helper="<nome_helper>"
# restituisce gli helper collegati al servizio
firewall-cmd --permanent --service="<nome_servizio>" --get-service-helpers
# elimina un servizio
firewall-cmd --permanent --delete-service=="<nome_servizio>"
(rif. man service)
4.3. Gestione ICMP
Il traffico ICMP viene impostato a livello di zona o a livello di policy object.
Al solito, agire a livello di zona è più semplice, usare i policy objects permette di guadagnare in modularità e scalabilità.
Di default, ICMP lavora su blacklist. È tutto consentito tranne ciò che viene esplicitamente vietato con le istruzioni --add-icmp-block per aggiungere il tipo icmp che si vuole bloccare o --remove-icmp-block per rimuovere il blocco.
È possibile invertire la logica di funzionamento, a livello globale o di singola zona, passando ad una whitelist. È tutto vietato tranne cio che è consentito con --add-icmp-block (un po' fuorviante, ne convengo). --remove-icmp-block rimuove il consenso.
Di seguito, un elenco dei comandi di utilità disponibili per gli icmptype:
# Elenca tutti gli icmptype
firewall-cmd --get-icmptypes
# inverte / disattiva globalmente la logica del blocco icmp (attiva / disattiva whitelist)
firewall-cmd --permanent --add-icmp-block-inversion
firewall-cmd --permanent --remove-icmp-block-inversion
# Creazione e cancellazione di un icmptype
firewall-cmd --permanent --new-icmptype="<nome icmptype>"
firewall-cmd --permanent --delete-icmptype="<nome icmptype>"
# imposta / restituisce la descrizione di un icmptype
firewall-cmd --permanent --icmptype="<nome icmptype>" --set-description="<descrizione>"
firewall-cmd --permanent --icmptype="<nome icmptype>" --get-description
# imposta / restituisce la descrizione breve di un icmptype
firewall-cmd --permanent --icmptype="<nome icmptype>" --set-short="<descrizione>"
firewall-cmd --permanent --icmptype="<nome icmptype>" --get-short
# imposta/cancella/restituisce la destinazione (ipv4 o ipv6) di un icmptype
firewall-cmd --permanent --icmptype="<nome icmptype>" --add-destination="[ipv4 | ipv6]"
firewall-cmd --permanent --icmptype="<nome icmptype>" --remove-destination="[ipv4 | ipv6]"
firewall-cmd --permanent --icmptype="<nome icmptype>" --get-destinations
(rif. man icmp type)
4.4. Porte e protocolli
Zone e policy objects permettono di fare binding diretto su porte e protocolli.
Non è generalmente una cosa che mi faccia impazzire perché si bypassano i servizi.
Si fa tutto più velocemente, è vero, ma quando le regole sono numerose e si usano porte non canoniche, la probabilità che, al tendere, non si capisca più su quale servizio si stia agendo, è elevatissima. (cfr. 4.8. Zona e 4.9. Policy objects)
4.5. IPset
Gli ipset sono liste di subnet o di ip che definiscono le sorgenti nelle zone, nei policy object o nelle rich-rules. La centralizzazione della dichiarazione delle sorgenti disaccoppia la dichiarazione dal suo utilizzo.
Per gli ipset basta indicarre, nome, tipo e una lista di entry.
firewall-cmd --permanent --new-ipset="<nome_ipset>" --type=<type>
firewall-cmd --permanent --ipset="<nome_ipset>" [--add-entry= subnet | ip]+
Di seguito, un elenco dei comandi di utilità disponibili per gli ipsets:
# Restituisce tutti gli ipsets
firewall-cmd --permanent --get-ipsets
# Restituisce tutte le info di un ipset
firewall-cmd --permanent --info-ipset="<nome_ipset>"
# Restituisce la lista dei tipi di ipset:
firewall-cmd --get-ipset-types
# Restituisce tutte le entry di un ipset
firewall-cmd --permanent --ipset="<nome_ipset>" --get-entries
# Cancella un ipset
firewall-cmd --permanent --ipset="<nome_ipset>" --remove-entry=subnet | ip
# Cancella una (o più) entry da un ipset
firewall-cmd --permanent --ipset="<nome_ipset>" [--delete-entry=subnet | ip]+
# imposta / restituisce la descrizione di un ipset
firewall-cmd --permanent --ipset="<nome_ipset>" --set-description="<descrizione>"
firewall-cmd --permanent --ipset="<nome_ipset>" --get-description
# imposta / restituisce la descrizione breve di un ipset
firewall-cmd --permanent --ipset="<nome_ipset>" --set-short="<descrizione_breve>"
firewall-cmd --permanent --ipset="<nome_ipset>" --get-short-description
(rif. man ipset)
4.6. Rich-Rules
Le rich rules danno quel controllo granulare alle zone che è essenziale se si deve intervenire chirurgicamente per accettare o negare del traffico specifico.
Le rich-rules hanno una sintassi leggermente più corposa dello standard firewalld, è un approccio simil-iptables, o meglio, simil-ufw, e vanno aggiunte o alle zone o alle policy. O a entrambe.
Con le rich-rules possiamo abilitare o negare puntualmente il traffico (a seconda della action scelta),
firewall-cmd --permanent --zone="<nome_zona>" --add-rich-rule='rule family="ipv4 | ipv6" \
source address="<nome_ipset>" | subnet | ip \
destination address="<nome_ipset>" | subnet | ip \
# traffico indicato come servizio o come port:protocol
service name="<nome_servizio>" | port=<port> protocol=tcp|udp|sctp|dccp \
log prefix="<prefix>" \
level="emerg | alert | crit | error | warning | notice | info | debug" \
limit value="rate/duration" \
# azioni
accept | reject | drop | mark'
configurare il masquerade,
firewall-cmd --permanent --zone="<nome_zona>" --add-rich-rule='rule family="ipv4 | ipv6" \
source address="<nome_ipset>" | "subnet" | "ip" \
destination address="<nome_ipset>" | "subnet" | "ip" \
masquerade'
agire di fino sul NAT,
firewall-cmd --permanent --zone="<nome_zona>" --add-rich-rule='rule family="ipv4 | ipv6" \
source address="<nome_ipset>" | "subnet" | "ip" \
destination address="<nome_ipset>" | "subnet" | "ip" \
forward-port port="[port]+" protocol="tcp|udp|sctp|dccp" \
to-port="[port]+" to-addr="<ip>"'
bloccare traffico ICMP.
firewall-cmd --permanent --zone="<nome_zona>" --add-rich-rule='rule family="ipv4 | ipv6" \
source address="<nome_ipset>" | "subnet" | "ip" \
destination address="<nome_ipset>" | "subnet" | "ip" \
[icmp-block name="<nome_icmptype>" [drop | reject]]+
Di seguito una lista di comandi utili:
# Rimozione di una rich-rule
firewall-cmd --permanent [--zone="<nome_zona>" | --policy="<nome_policy>"] --remove-rich-rule='rule'
# Elenca tutte le rich-rules di una policy
firewall-cmd --permanent [--zone="<nome_zona>" | --policy="<nome_policy>"] --list-rich-rules
(rif. man rich-rules)
4.7. Forwarding e Masquerade
Firewalld gestisce il nat attraverso dei costrutti all'interno delle zone, dei policy objects o delle rich-rules.
In particolare, zone e policy consentono di configurare velocemente casi particolari di DNAT e SNAT, port forwarding e masquerade nello specifico, mentre per una gestione del DNAT più granulare si ricorre alle rich-rules, a livello di zona o di policy a seconda che si vogliano, al solito, manipolare i pacchetti quando entrano nella zona o quando il pacchetto transita tra le zone specifiche definite dalla policy.
Esempio Port forwarding statico:
# inoltra a 192.168.2.10:22, tutto ciò che la zona riceve sulla
# porta 2222
firewall-cmd --permanent --zone=esterna --add-forward-port=port=2222:proto=tcp:to-port=22:to-addr=192.168.2.10
In questo modo inoltro tutto il traffico relativo alla zona.
Se voglio un controllo più fine, devo ricorrere alla combo policy (o zona) + rich-rules. In questo modo posso arrivare a determinare quale sia l'ip (o il gruppo di ip) client per il quale è abilitato l'inoltro ed eventualmente verso quale ip pubblico server, potendone scegliere diversi, effettuare l'inoltro.
Esempio DNAT generico:
# inoltro di tutto il traffico proveniente da un ip fisso
# verso un ip privato, con remapping delle porte.
firewall-cmd --permanent --policy="esterna-interna" \
--add-rich-rule='rule family="ipv4" \
source address="93.12.34.56" \
forward-port port="5001-6000" protocol="udp" to-port="15001-16000" to-addr="192.168.1.100"'
# stesso esempio di prima in cui il sorgente client è un gruppo
# di ip (ipset) fissi
firewall-cmd --permanent --policy="esterna-interna" \
--add-rich-rule='rule family="ipv4" \
source ipset="my_ipset" \
forward-port port="80" protocol="tcp" to-port="8080" to-addr="192.168.1.100"'
# In questo caso suppongo che il fw esponga più indirizzi pubblici.
# Solo un ip specifico può inoltrare il suo traffico
# richiedendolo ad uno degli indirizzi pubblici del firewall
firewall-cmd --permanent --policy="esterna-interna" \
--add-rich-rule='rule family="ipv4" \
source address="151.12.13.14" # ip client \
destination address="9.10.20.31" # ip pubblico fw \
forward-port port="53947" protocol="tcp" to-port="3306" to-addr="192.168.1.100"'
Esempio Masquerade:
firewall-cmd --permanent --zone=esterna --add-masquerade
Come nell'esempio del port forwarding statico, il nat a livello di zona o di policy altera qualunque pacchetto che transita nella zona o nella policy.
Anche qui, per avere un controllo migliore l'approccio policy (o zona) + rich-rules risulta vincente. In questo modo posso arrivare a scegliere quali dei server interni deve essere nattato ed eventualmente verso quali ip (snat condizionale).
# nat di un singolo ip interno
firewall-cmd --permanent --policy="interna-esterna" \
--add-rich-rule='rule family="ipv4" \
source address=192.168.10.10 masquerade'
# nat di un gruppo di ip interni (ipset)
firewall-cmd --permanent --policy="interna-esterna" \
--add-rich-rule='rule family="ipv4" \
source ipset="my_ipset" masquerade'
# nat di tutta la zona interna quando la destinazione è un ip
# (o gruppo di ip) specifico
firewall-cmd --permanent --policy="interna-esterna" \
--add-rich-rule='rule family="ipv4" \
destination ipset="my_ipset" masquerade'
# o, al contrario, si vuole nattare tutta la rete interna, o un
# suo segmento, TRANNE il traffico destinato ad UN'ALTRA rete
# specifica (es. una vpn o altro).
firewall-cmd --permanent --policy="interna-esterna" \
--add-rich-rule='rule family="ipv4" \
source address="my_ipset"
destination not address="10.4.10.0/24" masquerade'
# nat di un gruppo di ip solo per il servizio web
firewall-cmd --permanent --new-service="navigazione_web"
firewall-cmd --permanent --service="navigazione_web" \
--add-include="http" \
--add-include="https" \
--add-include="dns"
firewall-cmd --permanent --policy="interna-esterna" \
--add-rich-rule='rule family="ipv4" \
source ipset="my_ipset" \
service name="navigazione_web" masquerade'
4.8. Zona
Per creare una zona basta assegnarle un nome e associarle una o più interfacce e/o una o più sorgente di indirizzi ip.
Una zona senza alcun binding non è attiva.
firewall-cmd --permanent --new-zone="<nome_zona>"
# aggiunge un'interfaccia
firewall-cmd --permanent --zone="<nome_zona>" [--add-interface="<nome_interfaccia>"]+
# aggiunge sorgenti
firewall-cmd --permanent --zone="<nome_zona>" [--add-source=subnet | ip | "<nome_ipset>"]+
Se nella configurazione sono presenti sia l'interfaccia che le sorgenti di ip, sto dichiarando che tutto ciò che transita per l'interfaccia o che rientra nelle sorgenti indicate, ricadrà nelle regole della zona.
Faccio notare che Il binding (sorgenti o interfacce) funziona in aggiunta, non restringe ciò che ad es. transita dall'interfaccia. Tenete bene a mente che nella gestione del routing dei pacchetti verso le zone che fa firewalld, vengono valutate prima le sorgenti e dopo l'interfaccia.
Se avessi l'esigenza di restringere il traffico nella zona, si potrebbe pensare di limitare il binding alle sole sorgenti, escludendo l'interfaccia, in modo che qualunque pacchetto che non provenga dagli ip o dalle subnet, a prescindere dall'interfaccia, indicate venga respinto (in base alla politica della zona).
Va tenuto presente che configurazioni di questo tipo, per quanto pulite e semplici da realizzare, possono dare luogo ad errori estremamente subdoli e pericolosissimi (vedremo un esempio in seguito).
Tutti i pacchetti che, transitando per l'host, non vengono assorbiti da alcuna zona, saranno gestiti dalla zona di default.
Di seguito una lista di comandi utili:
# restituisce la zona di default
firewall-cmd --get-default-zone
# setta la zona di default
firewall-cmd --set-default-zone="<nome_zona>"
# restituisce tutte le zone attive (tutte quelle con un binding ad un'interfaccia e/o ad un sorgente)
firewall-cmd --get-active-zones
# restituisce tutte le zone accoppiate ad una specifica interfaccia/sorgente
firewall-cmd --permanent --get-zone-of-interface="<nome_interfaccia>"
firewall-cmd --permanent --get-zone-of-source=subnet | ip | "<nome_ipset>"
# restituisce info dettagliate sulla zone
firewall-cmd --permanent --info-zone="<nome_zona>"
# elenca tutte le zone
firewall-cmd --permanent --list-all-zones
# cancella una zona
firewall-cmd --permanent --delete-zone="<nome_zona>"
###########
# Servizi #
###########
# aggiungi / cancella servizi da una zona o dalla zona attiva (se il nome zona non è specificato)
firewall-cmd --permanent --zone="<nome_zona>" [--add-service="<nome_servizio>"]+
firewall-cmd --permanent --zone="<nome_zona>" [--remove-service="<nome_servizio>"]+
######################
# porte e protocolli #
######################
# elencare tutte le porte e i protocolli della zona
firewall-cmd --permanent --zone="<nome_zona>" --list-ports
firewall-cmd --permanent --zone="<nome_zona>" --list-protocols
# aggiungere/cancellare una porta alla zona
firewall-cmd --permanent --zone="<nome_zona>" [--add-port=<port>/tcp | udp | sctp | dccp]+
firewall-cmd --permanent --zone="<nome_zona>" [--remove-port=<port>/tcp | udp | sctp | dccp]+
# aggiungere/cancellare un protocollo alla zona
firewall-cmd --permanent --zone="<nome_zona>" --add-protocol=<protocol>
firewall-cmd --permanent --zone="<nome_zona>" --remove-protocol=<protocol>
##############
# Rich-rules #
##############
# aggiungere/cancellare un protocollo alla zona
firewall-cmd --permanent --zone="<nome_zona>" --add-rich-rule="<nome_rich-rule>"
firewall-cmd --permanent --zone="<nome_zona>" --remove-rich-rule="<nome_rich-rule>"
#############
# ICMP Type #
#############
# inverte / disattiva la logica del blocco icmp nella zona (attiva / disattiva whitelist)
firewall-cmd --permanent --zone="<nome_zona>" --add-imcp-block-inversion
firewall-cmd --permanent --zone="<nome_zona>" --remove-imcp-block-inversion
# aggiunge un tipo icmp alla whitelist/blacklist
firewall-cmd --permanent --zone="<nome_zona>" [--add-imcp-block="<tipo_icmp>"]+
# rimuove un tipo icmp dalla whitelist/blacklist
firewall-cmd --permanent --zone="<nome_zona>" [--remove-imcp-block="<tipo_icmp>"]+
##############
# Masquerade #
##############
# aggiunge / rimuove il masquerade
firewall-cmd --permanent --zone="<nome_zona>" --add-masquerade
firewall-cmd --permanent --zone="<nome_zona>" --remove-masquerade
###########################
# Port forwarding statico #
###########################
# aggiunge / rimuove il port forwarding
firewall-cmd --permanent --zone="<nome_zona>" --add-forward-port=port=<port>[-<port>]:proto=[tcp|udp|sctp|dccp]:to-port=<port>[-<port>][:to-addr=<ip>[/<mask>]
firewall-cmd --permanent --zone="<nome_zona>" --remove-forward-port=port=<port>[-<port>]:proto=[tcp|udp|sctp|dccp]:to-port=<port>[-<port>][:to-addr=<ip>[/<mask>]
# es. di inoltro veerso un ip interno di un range di porte con offset deterministico
firewall-cmd --permanent --zone="esterna" --add-forward-port=port=2501-3000:proto=tcp:to-port=5001-5500:to-addr=192.168.10.20
firewall-cmd --permanent --zone="esterna" --remove-forward-port=port=2501-3000:proto=tcp:to-port=5001-5500:to-addr=192.168.10.20
(rif. man zone)
4.9. Policy Objects
I policy objects, presenti dall'ormai lontano 2020 con la versione 0.9.0, hanno posto le basi per il futuro di firewalld. È il posto in cui si concentrano le policy di filtraggio sia per il traffico intra-zona che, soprattutto, per il traffico inter-zona.
I policy objects cambiano radicalmente il disegno delle regole che, come detto in precedenza, vengono disaccoppiate dalla dichiarazione della zona che rimane il luogo in cui viene effettuato principalmente il trust delle sorgenti.
Conseguenza immediata è una notevole flessibilità perché ho la possibilità di variare dinamicamente le regole da applicare alle zone semplicemente aggiungendo le policy opportune.
Lavorare sulle zone è più immediato ma più lo scenario diventa articolato, più le configurazioni si complicano, oltre al fatto che alcune cose come il routing e l'inoltro, con le sole zone non sono proprio realizzabili
Le policy, al contrario, richiedono una maggiore complessità iniziale ma ha il vantaggio di mantenere il disegno generale più pulito nei casi in cui le configurazioni cambino con una certa frequenza o tendano a diventare via via più articolate.
Nel seguito mostrerò degli esempi di configurazioni fatte in modalità zone-oriented e policy-oriented.
Gli elementi costitutivi del policy object sono il nome, il target policy (di base, “default”), la specifica della direzione del traffico, uno o più servizi da abilitare.
firewall-cmd --permanent --new-policy="<nome_policy>"
firewall-cmd --permanent --policy="<nome_policy>" --set-target=DROP | REJECT | ACCEPT | CONTINUE
# definizione della direzione del traffico
firewall-cmd --permanent --policy="<nome_policy>" [--add-ingress-zone=HOST | "<nome_zona>" | ANY]+
firewall-cmd --permanent --policy="<nome_policy>" [--add-egress-zone=HOST | "<nome_zona>" | ANY]+
# traffico consentito
firewall-cmd per --permanent --policy="<nome_policy>" [--add-service="<nome_servizio>"]+
Di seguito, una lista di comandi utili:
# elenco, sintetico o dettagliato, di tutti i policy objects
firewall-cmd --get-policies
firewall-cmd --permanent --list-all-policies
# estrae tutti i componenti della policy
firewall-cmd --permanent --policy="<nome_policy>" --list-all
# restituisce le ingress / egress zone
firewall-cmd --permanent --policy="<nome_policy>" --list-egress-zones
firewall-cmd --permanent --policy="<nome_policy>" --list-ingress-zones
# restituisce i servizi
firewall-cmd --permanent --policy="<nome_policy>" --list-services
# restituisce le rich-rules
firewall-cmd --permanent --policy="<nome_policy>" --list-rich-rules
# info di un policy object
firewall-cmd --permanent --info-policy="<nome_policy>"
# cambiare target di un policy object
firewall-cmd --permanent --policy="<nome_policy>" --set-target=DROP | REJECT | ACCEPT | CONTINUE
# eliminare un policy object
firewall-cmd --permanent --delete-policy="<nome_policy>"
###########
# Servizi #
###########
# aggiungi / cancella servizi dal policy object specificato
firewall-cmd --permanent --policy="<nome_policy>" [--add-service="<nome_servizio>"]+
firewall-cmd --permanent --policy="<nome_policy>" [--remove-service="<nome_servizio>"]+
######################
# Porte e protocolli #
######################
# elencare tutte le porte e i protocolli del policy object specificato
firewall-cmd --permanent --policy="<nome_policy>" --list-ports
firewall-cmd --permanent --policy="<nome_policy>" --list-protocols
# aggiungere/cancellare una porta dal policy object specificato
firewall-cmd --permanent --policy="<nome_policy>" [--add-port=<port>/tcp | udp | sctp | dccp]+
firewall-cmd --permanent --policy="<nome_policy>" [--remove-port=<port>/tcp | udp | sctp | dccp]+
# aggiungere/cancellare un protocollo dal policy object specificato
firewall-cmd --permanent --policy="<nome_policy>" --add-protocol=[tcp | udp | sctp | dccp]
firewall-cmd --permanent --policy="<nome_policy>" --remove-protocol=[tcp | udp | sctp | dccp]
##############
# Rich-rules #
##############
# aggiungere/cancellare una (o più) rich-rule dal policy object specificato
firewall-cmd --permanent --policy="<nome_policy>" [--add-rich-rule="<nome_rich-rule>"]+
firewall-cmd --permanent --policy="<nome_policy>" [--remove-rich-rule="<nome_rich-rule>"]+
##############
# ICMP Types #
##############
# Aggiunge un tipo icmp alla whitelist/blacklist
firewall-cmd --permanent --policy="<nome_policy>" [--add-imcp-block="<tipo_icmp>"]+
# Rimuove un tipo icmp dalla whitelist/blacklist
firewall-cmd --permanent --policy="<nome_policy>" [--remove-imcp-block="<tipo_icmp>"]+
##############
# Masquerade #
##############
# aggiunge / rimuove il masquerade
firewall-cmd --permanent --policy="<nome_policy>" --add-masquerade
firewall-cmd --permanent --policy="<nome_policy>" --remove-masquerade
###########################
# Port forwarding statico #
###########################
# aggiunge / rimuove il port forwarding
firewall-cmd --permanent --policy="<nome_policy>" --add-forward-port=port=<port>[-<port>]:proto=[tcp | udp | sctp | dccp]:to-port=<port>[-<port>][:to-addr=<ip>[/<mask>]
firewall-cmd --permanent --policy="<nome_policy>" --remove-forward-port=port=<port>[-<port>]:proto=[tcp | udp | sctp | dccp]:to-port=<port>[-<port>][:to-addr=<ip>[/<mask>]
# es. di inoltro veerso un ip interno di un range di porte con offset deterministico
firewall-cmd --permanent --policy="wan-to-lan" --add-forward-port=port=2501-3000:proto=tcp:to-port=5001-5500:to-addr=192.168.10.20
firewall-cmd --permanent --zone="wan-to-lan" --remove-forward-port=port=2501-3000:proto=tcp:to-port=5001-5500:to-addr=192.168.10.20
(rif. man policy, man policies)
4.10. Comandi di utilità generale
Di seguito, un elenco dei comandi di utilità generale disponibili per firewalld:
# Restituisce lo stato di firewalld
firewall-cmd --state
# Riavvia firewalld
firewall-cmd --reload
# Riavvia firewalld ricaricando anche i moduli netfilter del kernel
firewall-cmd --complete-reload
# Restituisce il log level di firewalld
firewall-cmd --get-log-denied
# Imposta il log level di firewalld
firewall-cmd --set-log-denied=all | unicast | broadcast | multicast | off
# Rende permanente tutte le configurazioni effimere di firewalld. Necessario il reload.
firewall-cmd --runtime-to-permanent
# Kill switch ON /OFF
firewalld --panic-on
firewalld --panic-off
# Stato Kill switch [0 | 1]
firewalld --query-panic
#firewall #firewallcmd #firewalld #iptables #netfilter #nftables #ufw