<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Hardening on My personal blog</title>
        <link>https://www.matteobianchi.eu/tags/hardening/</link>
        <description>Recent content in Hardening on My personal blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Tue, 06 Oct 2026 09:00:00 +0200</lastBuildDate><atom:link href="https://www.matteobianchi.eu/tags/hardening/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Un homelab per la sicurezza</title>
        <link>https://www.matteobianchi.eu/p/building-a-security-homelab/</link>
        <pubDate>Tue, 06 Oct 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/building-a-security-homelab/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/building-a-security-homelab/cover.png" alt="Featured image of post Un homelab per la sicurezza" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;Questa serie ha usato un lab fin dal primo capitolo. L&amp;rsquo;ultimo passo è renderlo &lt;strong&gt;permanente&lt;/strong&gt;: un
ambiente che sta su un PC, si accende quando serve, si descrive in file versionabili e permette di
rifare — e inventare — attacchi e difese senza rischi per nessuno. Un homelab non è un lusso: è il
posto dove la teoria dei nove capitoli diventa pratica.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;obiettivo è un lab che copra tutta la serie, su un solo PC, a costo zero di software.&lt;/p&gt;
&lt;h2 id=&#34;requisiti&#34;&gt;Requisiti
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Un PC Linux con &lt;strong&gt;16 GB di RAM&lt;/strong&gt; e qualche decina di GB di disco. Funziona anche con 8 GB per i
lab più piccoli.&lt;/li&gt;
&lt;li&gt;Virtualizzazione attiva nel BIOS (per la VM del firewall).&lt;/li&gt;
&lt;li&gt;Nessun hardware di rete particolare: tutto è virtuale.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il principio guida: &lt;strong&gt;container dove bastano, VM dove servono davvero&lt;/strong&gt;. I container condividono il
kernel dell&amp;rsquo;host, quindi decine di nodi di rete stanno in pochi GB; una VM intera (il firewall) ne
occupa uno o due da sola.&lt;/p&gt;
&lt;h2 id=&#34;architettura&#34;&gt;Architettura
&lt;/h2&gt;&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart TD
    subgraph HOST[&amp;#34;PC host (Linux)&amp;#34;]
        subgraph CLAB[&amp;#34;containerlab — topologie di rete&amp;#34;]
            ATT[&amp;#34;attacker&amp;lt;br/&amp;gt;(scapy, nmap, ...)&amp;#34;]
            VIC[&amp;#34;victim&amp;#34;]
            SRV[&amp;#34;server / DMZ&amp;#34;]
            SW[&amp;#34;sw0&amp;lt;br/&amp;gt;Open vSwitch&amp;#34;]
            ATT --- SW
            VIC --- SW
            SRV --- SW
        end
        GW[&amp;#34;VM OPNsense&amp;lt;br/&amp;gt;firewall + DHCP + router&amp;#34;]
        IDS[&amp;#34;Suricata&amp;lt;br/&amp;gt;+ EveBox&amp;#34;]
        LOG[&amp;#34;Log centralizzati&amp;lt;br/&amp;gt;(syslog / EVE JSON)&amp;#34;]
        SW --- GW
        SW -. port mirror .-&amp;gt; IDS
        IDS --&amp;gt; LOG
        GW --&amp;gt; LOG
    end
    GW -. uplink NAT .-&amp;gt; Internet((Internet))
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;containerlab&lt;/strong&gt; ospita i nodi di rete (attaccante, vittime, server) e lo switch Open vSwitch.&lt;/li&gt;
&lt;li&gt;Una &lt;strong&gt;VM OPNsense&lt;/strong&gt; fa da gateway: firewall stateful, DHCP, routing tra le VLAN. È l&amp;rsquo;unico pezzo
che conviene tenere come VM intera, perché è un sistema operativo completo con la sua interfaccia.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Suricata&lt;/strong&gt; riceve il traffico da una porta mirror dello switch (modalità IDS del
&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/ids-ips-suricata/&#34; &gt;capitolo 05&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;I &lt;strong&gt;log&lt;/strong&gt; di firewall e IDS confluiscono in un punto solo: così si risponde alla minaccia T6 del
&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/threat-modeling-networks/&#34; &gt;threat model&lt;/a&gt; e si impara a correlare gli eventi.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;la-topologia-della-serie-in-un-file&#34;&gt;La topologia della serie in un file
&lt;/h2&gt;&lt;p&gt;Tutti i capitoli partono dalla stessa base, estesa di volta in volta. Il cuore è il file
containerlab, qui con l&amp;rsquo;aggiunta delle VLAN per i capitoli 02-03:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;homelab-secnet&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;topology&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;nodes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;sw0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;{&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;ovs-bridge }                &lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# switch reale, gestisce le VLAN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;gateway&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;{&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;kind: linux, image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;alpine:3.20 } &lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# oppure l&amp;#39;uplink verso la VM OPNsense&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;victim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;{&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;kind: linux, image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;alpine:3.20 }&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;{&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;kind: linux, image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;nginx:alpine }&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# il &amp;#34;server in DMZ&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;attacker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;{&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;kind: linux, image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;local/attacker }&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# immagine con i tool preinstallati&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;links&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;endpoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gateway:eth1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sw0:p-gw&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;endpoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;victim:eth1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sw0:p-victim&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;endpoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;server:eth1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sw0:p-srv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;endpoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;attacker:eth1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sw0:p-att&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le righe evidenziate sono i punti da personalizzare: lo switch OVS (riga 4), che va pre-creato, e i
collegamenti (righe 13-14), che mappano ogni nodo a una porta nominata dello switch — gli stessi
nomi che si usano per assegnare VLAN e trunk.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# una tantum: crea lo switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo ovs-vsctl add-br sw0 &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo ip link &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; sw0 up
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# avvio / spegnimento del lab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo containerlab deploy  -t homelab-secnet.clab.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo containerlab destroy -t homelab-secnet.clab.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;limmagine-dellattaccante&#34;&gt;L&amp;rsquo;immagine dell&amp;rsquo;attaccante
&lt;/h2&gt;&lt;p&gt;Per non reinstallare i tool ogni volta, conviene un&amp;rsquo;immagine container con tutto pronto. Il
&lt;code&gt;Dockerfile&lt;/code&gt; è parte del lab, quindi versionato e licenziato insieme al resto:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; debian:stable-slim&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;RUN&lt;/span&gt; apt-get update &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install -y --no-install-recommends &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    python3-scapy nmap tcpdump dsniff iproute2 iputils-ping &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    tshark hping3 &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/lib/apt/lists/*&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;I file di configurazione del lab (&lt;code&gt;.clab.yml&lt;/code&gt;, &lt;code&gt;Dockerfile&lt;/code&gt;, regole Suricata, ruleset nftables)
hanno una licenza diversa dai testi del blog. Vanno pubblicati con una licenza per codice, ad
esempio MIT, così chiunque può riusarli; i testi restano sotto la licenza del sito (CC BY-NC-SA).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;cosa-fa-ciascun-capitolo-in-questo-lab&#34;&gt;Cosa fa ciascun capitolo in questo lab
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capitolo&lt;/th&gt;
&lt;th&gt;Nel lab&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;02 ARP/DHCP/MAC&lt;/td&gt;
&lt;td&gt;nodi Linux + sw0; scapy, dsniff, macof&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;03 VLAN&lt;/td&gt;
&lt;td&gt;porte OVS access/trunk; double tagging con scapy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;04 nftables&lt;/td&gt;
&lt;td&gt;ruleset sul nodo gateway o sulla VM OPNsense&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05 Suricata&lt;/td&gt;
&lt;td&gt;container Suricata su porta mirror di sw0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;06-07 TLS/DNS&lt;/td&gt;
&lt;td&gt;CA di test, unbound con DNSSEC+DoT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08 DDoS&lt;/td&gt;
&lt;td&gt;hping3 tra i nodi (dimostrativo)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09 VPN&lt;/td&gt;
&lt;td&gt;WireGuard tra due nodi su rete &amp;ldquo;non fidata&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 Wireshark&lt;/td&gt;
&lt;td&gt;tshark cattura sulle porte di sw0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Un solo strumento base (containerlab) per quasi tutto; la VM OPNsense e, dove serve, GNS3 con
immagini Cisco per DTP, sono le uniche aggiunte.&lt;/p&gt;
&lt;h2 id=&#34;lab-il-primo-avvio&#34;&gt;Lab: il primo avvio
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Installate containerlab e Open vSwitch sull&amp;rsquo;host.&lt;/li&gt;
&lt;li&gt;Costruite l&amp;rsquo;immagine attaccante (&lt;code&gt;docker build -t local/attacker .&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;sw0&lt;/code&gt; e fate il &lt;code&gt;deploy&lt;/code&gt; della topologia.&lt;/li&gt;
&lt;li&gt;Verificate la connettività di base: da &lt;code&gt;attacker&lt;/code&gt;, &lt;code&gt;ping&lt;/code&gt; gli altri nodi.&lt;/li&gt;
&lt;li&gt;Rifate l&amp;rsquo;esercizio del &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/layer2-attacks-arp-spoofing/&#34; &gt;capitolo 02&lt;/a&gt; per
confermare che il lab è pronto.&lt;/li&gt;
&lt;/ol&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; perché tenere OPNsense come VM invece di usare un container anche per il firewall?&lt;/summary&gt;
&lt;p&gt;Per due motivi. Primo, OPNsense è basato su FreeBSD: non gira come container Linux, serve una VM.
Secondo, e più importante, il valore didattico sta proprio nell&#39;usare un firewall &#34;vero&#34;, con la sua
interfaccia web, le sue regole stateful, il DHCP e l&#39;IDS integrati — lo stesso tipo di apparato che
si trova in produzione. Per i soli esercizi nftables del capitolo 04 basterebbe un nodo Linux
container; ma avere un firewall completo nel lab permette di collegare i concetti della serie a uno
strumento che si userà davvero. È un compromesso RAM contro realismo, e per un homelab permanente il
realismo vince.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;Un homelab trasforma una serie di articoli in una palestra permanente. Con containerlab, Open
vSwitch, una VM OPNsense e Suricata — tutto open source, su un solo PC — si ricostruisce ogni
scenario della serie e se ne inventano di nuovi, in un ambiente isolato dove sbagliare non ha
conseguenze.&lt;/p&gt;
&lt;p&gt;Qui finisce &amp;ldquo;Network Security dal cavo in su&amp;rdquo;. Dal cavo e dallo switch (capitoli 02-03), su per il
firewall e l&amp;rsquo;IDS (04-05), fino a TLS, DNS e le VPN (06-09), e infine l&amp;rsquo;analisi (10) e il lab (11):
undici capitoli, un solo filo conduttore. La difesa in profondità non è uno slogan, è questo —
ogni strato che regge quando quello sotto cede.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/network-security-roadmap/&#34; &gt;Torna alla roadmap&lt;/a&gt; per la mappa completa della serie.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>802.1X e NAC: autenticare chi si collega alla porta</title>
        <link>https://www.matteobianchi.eu/p/nac-8021x/</link>
        <pubDate>Fri, 02 Oct 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/nac-8021x/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/nac-8021x/cover.png" alt="Featured image of post 802.1X e NAC: autenticare chi si collega alla porta" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;Nel &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/layer2-attacks-arp-spoofing/&#34; &gt;capitolo sugli attacchi L2&lt;/a&gt; la port security
limitava quanti MAC può usare una porta. Ma un MAC si falsifica in un secondo: non prova &lt;strong&gt;chi&lt;/strong&gt; sei,
solo che usi un certo indirizzo. In una rete seria — un ufficio, un campus — serve che un dispositivo
si &lt;strong&gt;autentichi&lt;/strong&gt; prima di ottenere accesso alla LAN. Questo è 802.1X, il cuore del Network Access
Control (NAC): la porta dello switch resta chiusa finché non sai dimostrare di avere diritto a
entrare.&lt;/p&gt;
&lt;h2 id=&#34;i-tre-attori&#34;&gt;I tre attori
&lt;/h2&gt;&lt;p&gt;802.1X definisce un dialogo a tre:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart LR
    S[&amp;#34;Supplicant&amp;lt;br/&amp;gt;(il dispositivo)&amp;#34;] &amp;lt;--&amp;gt;|EAPOL| A[&amp;#34;Authenticator&amp;lt;br/&amp;gt;(lo switch / AP)&amp;#34;]
    A &amp;lt;--&amp;gt;|RADIUS| R[&amp;#34;Authentication Server&amp;lt;br/&amp;gt;(RADIUS)&amp;#34;]
    R -.decide.-&amp;gt; A
    A -.apre o chiude la porta.-&amp;gt; S
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Supplicant&lt;/strong&gt;: il client che vuole entrare (un PC, un telefono).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authenticator&lt;/strong&gt;: lo switch o l&amp;rsquo;access point. Non decide: fa da tramite. Tiene la porta in stato
&amp;ldquo;non autorizzato&amp;rdquo; e inoltra solo il traffico di autenticazione (EAPOL) finché non riceve il via
libera.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authentication Server&lt;/strong&gt;: tipicamente &lt;strong&gt;RADIUS&lt;/strong&gt;. È lui che verifica le credenziali e dice allo
switch sì o no.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La separazione è il punto di forza: lo switch non conserva credenziali, le centralizza nel server.
Aggiungere o revocare un utente si fa in un posto solo.&lt;/p&gt;
&lt;h2 id=&#34;eap-il-metodo-dentro-il-protocollo&#34;&gt;EAP: il metodo dentro il protocollo
&lt;/h2&gt;&lt;p&gt;802.1X trasporta &lt;strong&gt;EAP&lt;/strong&gt;, che non è un singolo metodo ma un contenitore. Il metodo scelto decide
&lt;em&gt;come&lt;/em&gt; ci si autentica:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metodo EAP&lt;/th&gt;
&lt;th&gt;Credenziale&lt;/th&gt;
&lt;th&gt;Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EAP-TLS&lt;/td&gt;
&lt;td&gt;certificato client&lt;/td&gt;
&lt;td&gt;il più sicuro; richiede una PKI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PEAP / EAP-TTLS&lt;/td&gt;
&lt;td&gt;utente + password in un tunnel TLS&lt;/td&gt;
&lt;td&gt;più semplice da distribuire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EAP-MD5&lt;/td&gt;
&lt;td&gt;hash della password&lt;/td&gt;
&lt;td&gt;obsoleto, nessuna protezione: da non usare&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;EAP-TLS lega l&amp;rsquo;accesso a un &lt;strong&gt;certificato&lt;/strong&gt; per dispositivo: niente password da rubare, e si integra
con una PKI interna. È la scelta migliore dove si può gestire l&amp;rsquo;emissione dei certificati.&lt;/p&gt;
&lt;h2 id=&#34;il-flusso-di-autenticazione&#34;&gt;Il flusso di autenticazione
&lt;/h2&gt;&lt;pre class=&#34;mermaid&#34;&gt;
  sequenceDiagram
    participant S as Supplicant
    participant A as Authenticator (switch)
    participant R as RADIUS
    Note over A: porta in stato &amp;#34;non autorizzato&amp;#34;
    S-&amp;gt;&amp;gt;A: EAPOL-Start
    A-&amp;gt;&amp;gt;S: EAP-Request Identity
    S-&amp;gt;&amp;gt;A: EAP-Response Identity
    A-&amp;gt;&amp;gt;R: RADIUS Access-Request
    R-&amp;gt;&amp;gt;S: sfida EAP (via switch)
    S-&amp;gt;&amp;gt;R: risposta EAP (certificato o credenziali)
    R-&amp;gt;&amp;gt;A: RADIUS Access-Accept (+ VLAN assegnata)
    Note over A: porta autorizzata, traffico consentito
&lt;/pre&gt;

&lt;p&gt;Un dettaglio potente: nell&amp;rsquo;&lt;code&gt;Access-Accept&lt;/code&gt; il server può indicare &lt;strong&gt;quale VLAN&lt;/strong&gt; assegnare alla
porta. Così un dipendente finisce nella VLAN uffici, un dispositivo ospite in quella ospiti, un
telefono VoIP nella sua — tutto deciso dall&amp;rsquo;identità, non dalla porta fisica. È la segmentazione
dinamica, vicina al principio &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/zero-trust-architecture/&#34; &gt;Zero Trust&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;configurazione-lo-switch-e-radius&#34;&gt;Configurazione: lo switch e RADIUS
&lt;/h2&gt;&lt;p&gt;Lato switch (sintassi tipo Cisco):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;! abilita 802.1X globalmente e sulla porta
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dot1x system-auth-control
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;interface Gi0/1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  authentication port-control auto      ! la porta richiede autenticazione
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  dot1x pae authenticator
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  spanning-tree portfast
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;La riga &lt;code&gt;authentication port-control auto&lt;/code&gt; è il fulcro: mette la porta in modalità controllata,
dove l&amp;rsquo;accesso dipende dall&amp;rsquo;esito di 802.1X.&lt;/p&gt;
&lt;p&gt;Lato FreeRADIUS, un client (lo switch) in &lt;code&gt;clients.conf&lt;/code&gt; e gli utenti/certificati nel backend. Il
server valuta le richieste e risponde Accept/Reject, opzionalmente con gli attributi VLAN.&lt;/p&gt;
&lt;h2 id=&#34;il-problema-dei-dispositivi-senza-supplicant&#34;&gt;Il problema dei dispositivi senza supplicant
&lt;/h2&gt;&lt;p&gt;Non tutto parla 802.1X: stampanti, telecamere IP, vecchi apparati. Per loro esistono ripieghi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MAB (MAC Authentication Bypass)&lt;/strong&gt;: la porta autentica in base al MAC (debole, ma almeno
centralizzato e tracciato).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guest VLAN&lt;/strong&gt;: chi non si autentica finisce in una VLAN isolata con accesso minimo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MAB eredita la debolezza del MAC spoofing: va usato solo dove 802.1X è impossibile, e limitando
pesantemente ciò che quella VLAN può raggiungere.&lt;/p&gt;
&lt;h2 id=&#34;lab&#34;&gt;Lab
&lt;/h2&gt;&lt;p&gt;Con FreeRADIUS e uno switch (o &lt;code&gt;hostapd&lt;/code&gt; in modalità wired 802.1X, o Open vSwitch con un supplicant
&lt;code&gt;wpa_supplicant&lt;/code&gt;):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Configurate FreeRADIUS con un utente di test (PEAP) e lo switch come client RADIUS.&lt;/li&gt;
&lt;li&gt;Sul client, configurate &lt;code&gt;wpa_supplicant&lt;/code&gt; per 802.1X e collegatevi.&lt;/li&gt;
&lt;li&gt;Osservate la porta passare da &amp;ldquo;non autorizzato&amp;rdquo; ad &amp;ldquo;autorizzato&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Provate a collegare un dispositivo senza credenziali: deve restare bloccato o finire nella guest
VLAN.&lt;/li&gt;
&lt;/ol&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; 802.1X autentica la porta all&#39;inizio; cosa impedisce a un attaccante di staccare il cavo del PC autenticato e collegare il proprio?&lt;/summary&gt;
&lt;p&gt;È un limite reale di 802.1X &#34;classico&#34;. Se la porta autentica una volta e poi resta aperta, un
attaccante che si inserisce fisicamente dopo l&#39;autenticazione (o con un hub tra PC e presa) può
sfruttare la sessione. Le contromisure sono: la &lt;strong&gt;ri-autenticazione periodica&lt;/strong&gt; (il
server forza nuove verifiche a intervalli), il legame con MACsec (802.1AE) che cifra e autentica
ogni frame a livello 2, e il monitoraggio del link-down sulla porta (se il cavo si stacca, la porta
torna non autorizzata). È anche il motivo per cui 802.1X è un controllo d&#39;accesso, non una garanzia
assoluta: va accompagnato dalla segmentazione e dal monitoraggio.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;802.1X sposta il controllo d&amp;rsquo;accesso dalla porta fisica all&amp;rsquo;identità: nessuno entra in rete senza
autenticarsi presso un server RADIUS centrale, e la VLAN può essere assegnata in base a chi sei. È
il passo che la port security da sola non può fare. I punti aperti — dispositivi senza supplicant,
sessioni dopo l&amp;rsquo;autenticazione — si coprono con MAB limitato, ri-autenticazione e, dove serve,
MACsec.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Sicurezza Wi-Fi e WPA3: cosa cambia davvero</title>
        <link>https://www.matteobianchi.eu/p/wpa3-wifi-security/</link>
        <pubDate>Thu, 01 Oct 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/wpa3-wifi-security/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/wpa3-wifi-security/cover.png" alt="Featured image of post Sicurezza Wi-Fi e WPA3: cosa cambia davvero" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;La rete Wi-Fi è l&amp;rsquo;unico mezzo trasmissivo che chiunque, dal parcheggio, può ascoltare senza
collegare un cavo. Per vent&amp;rsquo;anni la protezione è stata WPA2, solido ma con due debolezze diventate
celebri: l&amp;rsquo;attacco &lt;strong&gt;KRACK&lt;/strong&gt; del 2017 e, soprattutto, la possibilità di catturare l&amp;rsquo;handshake e
provare le password &lt;strong&gt;offline&lt;/strong&gt;, senza limiti di velocità. WPA3, obbligatorio nei dispositivi
certificati Wi-Fi 6, cambia proprio queste regole.&lt;/p&gt;
&lt;h2 id=&#34;il-problema-di-wpa2-lhandshake-catturabile&#34;&gt;Il problema di WPA2: l&amp;rsquo;handshake catturabile
&lt;/h2&gt;&lt;p&gt;In WPA2-Personal la chiave di sessione deriva dalla password condivisa tramite un handshake a 4 vie.
Un attaccante non ha bisogno della password per catturare l&amp;rsquo;handshake: gli basta ascoltare un
client che si connette (o forzarne la riconnessione con un frame di deautenticazione). Poi, offline,
prova miliardi di password al secondo contro quella cattura.&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart LR
    A[&amp;#34;Attaccante&amp;lt;br/&amp;gt;in ascolto&amp;#34;] --&amp;gt;|deauth| C[Client]
    C --&amp;gt;|si riconnette| AP[Access Point]
    A -.cattura il 4-way handshake.-&amp;gt; H[(Handshake)]
    H --&amp;gt; Crack[&amp;#34;Cracking offline&amp;lt;br/&amp;gt;miliardi di tentativi/s&amp;#34;]
    style A fill:#fde2e4,stroke:#e63946
&lt;/pre&gt;

&lt;p&gt;Il tempo per rompere una password dipende solo dalla sua entropia. Con un alfabeto di dimensione
$N$ e lunghezza $L$, lo spazio da provare è:&lt;/p&gt;
&lt;p&gt;$$
S = N^{L}
$$&lt;/p&gt;
&lt;p&gt;Una password di 8 caratteri minuscoli ($N=26$, $L=8$) ha circa $2 \times 10^{11}$ combinazioni:
poche ore per hardware moderno. È per questo che in WPA2 la sicurezza dipende interamente dalla
forza della password.&lt;/p&gt;
&lt;h2 id=&#34;cosa-cambia-con-wpa3-sae&#34;&gt;Cosa cambia con WPA3: SAE
&lt;/h2&gt;&lt;p&gt;WPA3-Personal sostituisce l&amp;rsquo;handshake con &lt;strong&gt;SAE (Simultaneous Authentication of Equals)&lt;/strong&gt;, basato
sullo scambio Dragonfly. La differenza chiave: SAE è un &lt;strong&gt;PAKE&lt;/strong&gt; (Password-Authenticated Key
Exchange). La password non viene più usata in un modo che permetta di verificarla offline su una
cattura passiva.&lt;/p&gt;
&lt;p&gt;Conseguenze pratiche:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Niente cracking offline&lt;/strong&gt;: catturare lo scambio SAE non dà all&amp;rsquo;attaccante nulla da attaccare
offline. Ogni tentativo richiede una &lt;strong&gt;nuova interazione&lt;/strong&gt; con l&amp;rsquo;access point, che può essere
limitata (rate limiting) e rilevata.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward secrecy&lt;/strong&gt;: ogni sessione usa una chiave fresca. Rubare la password domani non decifra
il traffico catturato oggi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protezione anche con password deboli&lt;/strong&gt;: non è un invito a usarle, ma una password mediocre non
crolla più in poche ore come in WPA2.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;protected-management-frames&#34;&gt;Protected Management Frames
&lt;/h2&gt;&lt;p&gt;WPA3 rende obbligatori i &lt;strong&gt;Protected Management Frames (PMF, 802.11w)&lt;/strong&gt;. I frame di gestione — tra
cui la deautenticazione — sono ora autenticati. L&amp;rsquo;attacco di deauth che forzava la riconnessione
(il primo passo dello schema qui sopra) non funziona più: l&amp;rsquo;access point ignora i frame di deauth
falsificati.&lt;/p&gt;
&lt;h2 id=&#34;la-configurazione-hostapd&#34;&gt;La configurazione (hostapd)
&lt;/h2&gt;&lt;p&gt;Su un access point Linux con &lt;code&gt;hostapd&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# WPA3-Personal
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wpa=2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wpa_key_mgmt=SAE                 # SAE invece di WPA-PSK
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ieee80211w=2                     # PMF obbligatorio
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sae_require_mfp=1                # SAE richiede i frame di gestione protetti
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rsn_pairwise=CCMP
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le righe evidenziate attivano SAE (&lt;code&gt;wpa_key_mgmt=SAE&lt;/code&gt;) e rendono obbligatorio PMF (&lt;code&gt;ieee80211w=2&lt;/code&gt;),
i due pilastri di WPA3.&lt;/p&gt;
&lt;h3 id=&#34;modalità-di-transizione&#34;&gt;Modalità di transizione
&lt;/h3&gt;&lt;p&gt;Molti dispositivi vecchi non parlano WPA3. La &lt;strong&gt;transition mode&lt;/strong&gt; (&lt;code&gt;wpa_key_mgmt=WPA-PSK SAE&lt;/code&gt;)
permette a client WPA2 e WPA3 di coesistere. Ma attenzione: in questa modalità un attaccante può
tentare un &lt;strong&gt;downgrade&lt;/strong&gt;, forzando il client a usare WPA2 e riaprendo il cracking offline. La
transizione è un compromesso per la compatibilità, non una configurazione pienamente sicura: dove
possibile, SAE puro.&lt;/p&gt;
&lt;h2 id=&#34;lab&#34;&gt;Lab
&lt;/h2&gt;&lt;p&gt;Con una scheda Wi-Fi che supporta AP mode e &lt;code&gt;hostapd&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Configurate un AP in WPA2-PSK e uno in WPA3-SAE.&lt;/li&gt;
&lt;li&gt;In WPA2, catturate un handshake (&lt;code&gt;airodump-ng&lt;/code&gt;) e osservate che è acquisibile offline.&lt;/li&gt;
&lt;li&gt;In WPA3-SAE, verificate che lo stesso approccio non produce materiale attaccabile offline.&lt;/li&gt;
&lt;li&gt;Provate un frame di deauth con PMF attivo: l&amp;rsquo;AP deve ignorarlo.&lt;/li&gt;
&lt;/ol&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; se WPA3 protegge anche le password deboli, serve ancora una password lunga?&lt;/summary&gt;
&lt;p&gt;Sì. SAE elimina il cracking &lt;em&gt;offline&lt;/em&gt;, ma non l&#39;attacco &lt;em&gt;online&lt;/em&gt;: un attaccante può
ancora provare password contro l&#39;access point, un tentativo alla volta, interagendo con lui. È molto
più lento e rilevabile (e limitabile con rate limiting), ma una password banale come &#34;password1&#34;
cadrebbe comunque in un attacco a dizionario online. WPA3 alza enormemente il costo dell&#39;attacco, non
lo azzera: una password lunga e casuale resta la base. La differenza è che con WPA2 anche una password
discreta cadeva offline, con WPA3 solo quelle davvero deboli cadono, e solo online.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;WPA3 non è un ritocco di WPA2: cambia il modello di attacco. SAE toglie il cracking offline degli
handshake, la forward secrecy protegge il traffico passato, PMF chiude gli attacchi di deauth. Il
punto debole residuo è la modalità di transizione, dove il downgrade a WPA2 riapre i vecchi
problemi. Dove i dispositivi lo permettono, SAE puro; e, come sempre, una password robusta.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>SSH hardening: chiavi, cifrari e difesa dagli accessi</title>
        <link>https://www.matteobianchi.eu/p/ssh-hardening/</link>
        <pubDate>Wed, 30 Sep 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/ssh-hardening/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/ssh-hardening/cover.png" alt="Featured image of post SSH hardening: chiavi, cifrari e difesa dagli accessi" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;SSH è il modo in cui si amministra praticamente ogni server Linux. È anche il primo servizio che
una botnet prova a forzare: su qualunque IP pubblico, i log mostrano migliaia di tentativi di
login al giorno. Un SSH mal configurato — password deboli, root abilitato, cifrari vecchi — è una
delle vie d&amp;rsquo;ingresso più comuni in assoluto. L&amp;rsquo;hardening di SSH è il singolo intervento con il
miglior rapporto tra sforzo e sicurezza guadagnata.&lt;/p&gt;
&lt;h2 id=&#34;il-modello-chiavi-non-password&#34;&gt;Il modello: chiavi, non password
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;autenticazione a chiave pubblica sostituisce la password con una coppia crittografica. La chiave
privata resta sul client e non lascia mai la macchina; il server conserva solo la pubblica.&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  sequenceDiagram
    participant C as Client (chiave privata)
    participant S as Server (chiave pubblica in authorized_keys)
    C-&amp;gt;&amp;gt;S: richiesta di login per l&amp;#39;utente X
    S-&amp;gt;&amp;gt;C: sfida (un nonce casuale)
    Note over C: firma la sfida con la chiave privata
    C-&amp;gt;&amp;gt;S: firma
    Note over S: verifica con la chiave pubblica
    S-&amp;gt;&amp;gt;C: accesso consentito
&lt;/pre&gt;

&lt;p&gt;Una password può essere indovinata o intercettata; una chiave Ed25519 no, in pratica. E poiché il
server non riceve mai un segreto riutilizzabile, non c&amp;rsquo;è nulla da rubare dal lato server.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# generare una chiave moderna (Ed25519) sul client&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh-keygen -t ed25519 -C &lt;span class=&#34;s2&#34;&gt;&amp;#34;matteo@laptop&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# installarla sul server (aggiunge la pubblica ad authorized_keys)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh-copy-id -i ~/.ssh/id_ed25519.pub utente@server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;la-configurazione-del-server&#34;&gt;La configurazione del server
&lt;/h2&gt;&lt;p&gt;Il cuore dell&amp;rsquo;hardening è &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;. Le righe che contano:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# /etc/ssh/sshd_config
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PasswordAuthentication no        # niente password: solo chiavi
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PermitRootLogin no               # root non accede via SSH; si usa sudo
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;KbdInteractiveAuthentication no  # chiude anche la via interattiva/PAM alle password
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PubkeyAuthentication yes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AllowUsers matteo                # solo questo utente può entrare
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;MaxAuthTries 3                   # pochi tentativi per connessione
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;LoginGraceTime 20                # finestra breve per autenticarsi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le tre righe evidenziate sono le decisive: eliminano del tutto l&amp;rsquo;autenticazione a password, che è
il bersaglio del brute force. Con &lt;code&gt;PasswordAuthentication no&lt;/code&gt;, i milioni di tentativi delle botnet
falliscono prima ancora di iniziare, perché il server non accetta quel metodo.&lt;/p&gt;
&lt;p&gt;Dopo ogni modifica, validare e ricaricare:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sshd -t                  &lt;span class=&#34;c1&#34;&gt;# verifica la sintassi: se sbagli, non ricaricare!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemctl reload sshd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Attenzione irreversibile: prima di impostare &lt;code&gt;PasswordAuthentication no&lt;/code&gt;, verificate di poter
entrare con la chiave in una &lt;strong&gt;seconda&lt;/strong&gt; sessione già aperta. Un errore qui può chiudervi fuori
dal server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;cifrari-e-algoritmi-moderni&#34;&gt;Cifrari e algoritmi moderni
&lt;/h2&gt;&lt;p&gt;SSH negozia algoritmi di scambio chiavi, cifratura e MAC. Le versioni vecchie permettevano opzioni
oggi deboli. Si restringono alle moderne:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;I MAC in modalità &lt;em&gt;Encrypt-then-MAC&lt;/em&gt; (&lt;code&gt;-etm&lt;/code&gt;) sono preferibili. Queste liste tolgono dalla
negoziazione CBC, i MAC SHA-1 e lo scambio Diffie-Hellman su gruppi deboli.&lt;/p&gt;
&lt;h2 id=&#34;ridurre-la-superficie&#34;&gt;Ridurre la superficie
&lt;/h2&gt;&lt;p&gt;Oltre alla configurazione, due misure riducono l&amp;rsquo;esposizione:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rate limiting / ban&lt;/strong&gt;: &lt;code&gt;fail2ban&lt;/code&gt; o una regola nftables che limita le nuove connessioni alla
porta 22. Non sostituisce le chiavi, ma riduce il rumore nei log.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Niente SSH su internet quando evitabile&lt;/strong&gt;: dietro una VPN (vedi
&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/ipsec-vs-wireguard/&#34; &gt;IPsec vs WireGuard&lt;/a&gt;) o con accesso limitato a IP noti.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# limita i nuovi tentativi SSH a 10 al minuto per IP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table inet filter {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    chain input {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        tcp dport 22 ct state new meter ssh { ip saddr limit rate 10/minute } accept
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        tcp dport 22 ct state new drop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Spostare SSH su una porta diversa dalla 22 (&amp;ldquo;security through obscurity&amp;rdquo;) riduce solo il rumore dei
log, non il rischio reale: non è hardening, è cosmesi.&lt;/p&gt;
&lt;h2 id=&#34;lab&#34;&gt;Lab
&lt;/h2&gt;&lt;p&gt;Su una VM o un container:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate una chiave Ed25519 e installatela sul server.&lt;/li&gt;
&lt;li&gt;Verificate l&amp;rsquo;accesso con la chiave, poi impostate &lt;code&gt;PasswordAuthentication no&lt;/code&gt; e ricaricate.&lt;/li&gt;
&lt;li&gt;Da un altro terminale, provate a forzare la password (&lt;code&gt;ssh -o PubkeyAuthentication=no ...&lt;/code&gt;):
deve essere rifiutato.&lt;/li&gt;
&lt;li&gt;Aggiungete la regola nftables e osservate i tentativi scartati.&lt;/li&gt;
&lt;/ol&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; se uso le chiavi, perché dovrei comunque disattivare la password invece di lasciarla come ripiego?&lt;/summary&gt;
&lt;p&gt;Perché finché la password è accettata, la superficie d&#39;attacco del brute force resta aperta, a
prescindere dal fatto che voi usiate le chiavi. Un attaccante non sa (e non gli importa) che voi
preferite le chiavi: tenterà comunque le password, e se un qualsiasi account del sistema ne ha una
debole, entra. Le chiavi come metodo aggiuntivo non proteggono: proteggono solo quando sono
l&#39;&lt;em&gt;unico&lt;/em&gt; metodo. Il &#34;ripiego&#34; a password è esattamente il buco che l&#39;hardening chiude.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;hardening di SSH si riduce a pochi principi: solo chiavi, niente root diretto, cifrari moderni,
superficie ridotta. La singola riga &lt;code&gt;PasswordAuthentication no&lt;/code&gt; elimina da sola la categoria di
attacco più comune contro i server esposti. È cinque minuti di lavoro che chiude una delle porte
più battute di internet.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>TLS 1.3 in profondità</title>
        <link>https://www.matteobianchi.eu/p/tls-deep-dive/</link>
        <pubDate>Tue, 01 Sep 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/tls-deep-dive/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/tls-deep-dive/cover.png" alt="Featured image of post TLS 1.3 in profondità" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;Tutti gli attacchi dei capitoli precedenti — ARP spoofing, DHCP rogue, uomo nel mezzo — hanno lo
stesso punto debole come bersaglio: il traffico in chiaro. TLS è la risposta. Risolve un problema
che sembra impossibile: due macchine che non si sono mai parlate devono accordarsi su una chiave
segreta, mentre un attaccante registra ogni byte che si scambiano. E devono anche essere sicure di
parlare con chi credono, non con l&amp;rsquo;uomo nel mezzo.&lt;/p&gt;
&lt;p&gt;TLS 1.3 (RFC 8446, 2018) ha ripulito vent&amp;rsquo;anni di debolezze. Vediamo come funziona.&lt;/p&gt;
&lt;h2 id=&#34;il-problema-dello-scambio-di-chiavi&#34;&gt;Il problema dello scambio di chiavi
&lt;/h2&gt;&lt;p&gt;La cifratura simmetrica è veloce ma richiede una chiave condivisa. Come la si concorda su un canale
che l&amp;rsquo;attaccante ascolta? La risposta è lo scambio &lt;strong&gt;Diffie-Hellman&lt;/strong&gt;, in TLS 1.3 nella variante
su curve ellittiche (&lt;strong&gt;ECDHE&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idea, semplificata: client e server scelgono ciascuno un segreto privato ($a$ e $b$) e si
scambiano un valore pubblico derivato. Grazie alla proprietà matematica dello scambio, entrambi
calcolano lo stesso segreto condiviso $S$ senza mai trasmetterlo:&lt;/p&gt;
&lt;p&gt;$$
S = g^{ab} \bmod p
$$&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;attaccante vede passare $g^a$ e $g^b$, ma per ricavare $S$ dovrebbe risolvere il problema del
logaritmo discreto, computazionalmente proibitivo con i parametri usati. La chiave non viaggia mai
sul filo: viene &lt;strong&gt;calcolata&lt;/strong&gt; alle due estremità.&lt;/p&gt;
&lt;h2 id=&#34;lhandshake-tls-13&#34;&gt;L&amp;rsquo;handshake TLS 1.3
&lt;/h2&gt;&lt;p&gt;La novità più visibile di TLS 1.3 è la velocità: l&amp;rsquo;handshake si completa in &lt;strong&gt;un solo giro&lt;/strong&gt;
(1-RTT), contro i due di TLS 1.2. Il client azzarda i parametri già nel primo messaggio.&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  sequenceDiagram
    participant C as Client
    participant S as Server
    C-&amp;gt;&amp;gt;S: ClientHello (versioni, cifrari, key_share g^a)
    Note over S: sceglie i parametri, calcola S = (g^a)^b
    S-&amp;gt;&amp;gt;C: ServerHello (key_share g^b)
    S-&amp;gt;&amp;gt;C: {Certificate, CertificateVerify, Finished} (già cifrati)
    Note over C: calcola S = (g^b)^a, verifica il certificato
    C-&amp;gt;&amp;gt;S: {Finished} (cifrato)
    Note over C,S: canale cifrato stabilito in 1-RTT
&lt;/pre&gt;

&lt;p&gt;Dal &lt;code&gt;ServerHello&lt;/code&gt; in poi &lt;strong&gt;tutto è già cifrato&lt;/strong&gt;, inclusi il certificato del server. In TLS 1.2 il
certificato viaggiava in chiaro.&lt;/p&gt;
&lt;h2 id=&#34;autenticazione-la-catena-di-certificati&#34;&gt;Autenticazione: la catena di certificati
&lt;/h2&gt;&lt;p&gt;Lo scambio ECDHE protegge dall&amp;rsquo;ascolto, ma non dall&amp;rsquo;uomo nel mezzo: un attaccante potrebbe fare un
proprio scambio con il client fingendosi il server. Serve &lt;strong&gt;autenticazione&lt;/strong&gt;, e la dà la PKI.&lt;/p&gt;
&lt;p&gt;Il server presenta un &lt;strong&gt;certificato&lt;/strong&gt; che lega il suo nome di dominio a una chiave pubblica,
firmato da una &lt;strong&gt;Certificate Authority (CA)&lt;/strong&gt;. Il client verifica la firma risalendo la catena
fino a una CA radice di cui si fida già (sono preinstallate nel sistema).&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart TD
    Root[&amp;#34;CA radice&amp;lt;br/&amp;gt;(preinstallata, fidata)&amp;#34;] --&amp;gt;|firma| Inter[&amp;#34;CA intermedia&amp;#34;]
    Inter --&amp;gt;|firma| Leaf[&amp;#34;Certificato del server&amp;lt;br/&amp;gt;esempio.it&amp;#34;]
    Leaf -.verificato dal.-&amp;gt; Client
&lt;/pre&gt;

&lt;p&gt;In &lt;code&gt;CertificateVerify&lt;/code&gt; il server firma l&amp;rsquo;handshake con la chiave privata corrispondente al
certificato: prova di possedere la chiave, non solo di esibire il certificato. Un uomo nel mezzo
non ha quella chiave privata, quindi non può produrre quella firma.&lt;/p&gt;
&lt;h2 id=&#34;due-proprietà-che-contano&#34;&gt;Due proprietà che contano
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Forward secrecy.&lt;/strong&gt; In TLS 1.3 ogni connessione usa una coppia ECDHE &lt;strong&gt;effimera&lt;/strong&gt;, nuova ogni
volta e cancellata dopo. Se un attaccante registra oggi il traffico cifrato e tra un anno ruba la
chiave privata del server, &lt;strong&gt;non&lt;/strong&gt; può decifrare quel traffico: la chiave di sessione non derivava
da quella del server, ed è sparita. TLS 1.2 lo permetteva solo con i cifrari giusti; 1.3 lo rende
obbligatorio.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Niente cifrari deboli.&lt;/strong&gt; TLS 1.3 ha rimosso dalla negoziazione RC4, 3DES, MD5, lo scambio RSA
statico e la rinegoziazione. Molti attacchi storici (BEAST, POODLE, downgrade) sfruttavano proprio
quelle opzioni: toglierle dal protocollo le chiude per costruzione.&lt;/p&gt;
&lt;h2 id=&#34;vederlo-nel-lab&#34;&gt;Vederlo nel lab
&lt;/h2&gt;&lt;p&gt;Con &lt;code&gt;openssl&lt;/code&gt; si ispeziona un handshake reale:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# handshake completo verso un server, con dettagli&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;openssl s_client -connect esempio.it:443 -tls1_3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# guardare il certificato e la sua catena&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;openssl s_client -connect esempio.it:443 -showcerts &amp;lt;/dev/null 2&amp;gt;/dev/null &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; openssl x509 -noout -subject -issuer -dates
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Nel lab containerlab si può generare una CA di test, emettere un certificato per un server interno
e osservare la verifica della catena, senza toccare internet.&lt;/p&gt;
&lt;h2 id=&#34;la-configurazione-lato-server&#34;&gt;La configurazione lato server
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# solo TLS 1.2 e 1.3; niente versioni vecchie
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ssl_protocols&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;TLSv1.2&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;TLSv1.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;off&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;         &lt;span class=&#34;c1&#34;&gt;# in 1.3 la lista cifrari è già sicura
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ssl_session_tickets&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;off&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;               &lt;span class=&#34;c1&#34;&gt;# i ticket possono indebolire la forward secrecy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le due righe evidenziate sono il minimo: disattivare le versioni obsolete e lasciare a TLS 1.3 la
scelta dei cifrari, che sono già tutti robusti.&lt;/p&gt;
&lt;h2 id=&#34;lab&#34;&gt;Lab
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Nel lab, create una CA di test (&lt;code&gt;openssl req -x509 ...&lt;/code&gt;) ed emettete un certificato per un
server interno.&lt;/li&gt;
&lt;li&gt;Avviate un server TLS 1.3 (&lt;code&gt;openssl s_server&lt;/code&gt;) e collegatevi con &lt;code&gt;openssl s_client&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Osservate con quale &lt;code&gt;key_share&lt;/code&gt; e cifrario si conclude l&amp;rsquo;handshake.&lt;/li&gt;
&lt;li&gt;Provate a forzare &lt;code&gt;-tls1_1&lt;/code&gt;: il server deve rifiutare.&lt;/li&gt;
&lt;/ol&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; se tutto è cifrato, l&#39;IDS del capitolo 05 serve ancora a qualcosa?&lt;/summary&gt;
&lt;p&gt;Sì, ma vede meno. Con TLS, un IDS passivo non legge il contenuto HTTP: vede solo i metadati —
indirizzi IP, dimensioni e tempi dei pacchetti, e il nome del server nell&#39;estensione SNI (in chiaro
anche in TLS 1.3, salvo ECH). Può ancora rilevare schemi (scan, beaconing di malware, destinazioni
note come malevole), ma non il payload. Per ispezionare il contenuto cifrato servirebbe la
decifratura TLS (un proxy che termina e ri-origina la connessione), che però rompe la forward
secrecy end-to-end e introduce un punto in cui il traffico è di nuovo in chiaro. È un compromesso
di sicurezza serio, non una funzione da attivare a cuor leggero.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;TLS 1.3 risolve due problemi distinti con due meccanismi distinti: ECDHE per la segretezza
(nessuno ascolta), la PKI per l&amp;rsquo;autenticazione (parli con chi credi). La forward secrecy
obbligatoria e l&amp;rsquo;eliminazione dei cifrari deboli chiudono per costruzione gli attacchi che
affliggevano le versioni precedenti.&lt;/p&gt;
&lt;p&gt;TLS protegge il &lt;em&gt;trasporto&lt;/em&gt;. Ma prima ancora di aprire una connessione, il client deve sapere
quale IP ha &lt;code&gt;esempio.it&lt;/code&gt;: lo chiede al DNS. E il DNS, per impostazione predefinita, è in chiaro e
senza autenticazione — il prossimo bersaglio.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prossimo nella serie:&lt;/strong&gt; &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/dns-security-dnssec-doh/&#34; &gt;07 · Sicurezza del DNS: DNSSEC e DoH&lt;/a&gt; ·
&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/network-security-roadmap/&#34; &gt;Torna alla roadmap&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Firewall stateful con nftables</title>
        <link>https://www.matteobianchi.eu/p/stateful-firewalls-nftables/</link>
        <pubDate>Tue, 18 Aug 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/stateful-firewalls-nftables/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/stateful-firewalls-nftables/cover.png" alt="Featured image of post Firewall stateful con nftables" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;Il &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/threat-modeling-networks/&#34; &gt;threat model&lt;/a&gt; ha prodotto regole come &amp;ldquo;dalla
DMZ nessuna connessione verso la LAN&amp;rdquo; (T5) e &amp;ldquo;la rete ospiti non raggiunge la LAN&amp;rdquo; (T1). Un
firewall è lo strumento che le mette in pratica. Ma un firewall scritto male è peggio di nessun
firewall: dà un falso senso di sicurezza. La differenza tra un firewall fragile e uno solido sta
in una parola: &lt;strong&gt;stato&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Su Linux lo strumento moderno è &lt;strong&gt;nftables&lt;/strong&gt;, che dal 2014 sostituisce iptables. Qui vediamo
perché lo stato cambia tutto e come scrivere un ruleset leggibile.&lt;/p&gt;
&lt;h2 id=&#34;stateless-contro-stateful&#34;&gt;Stateless contro stateful
&lt;/h2&gt;&lt;p&gt;Un firewall &lt;strong&gt;stateless&lt;/strong&gt; giudica ogni pacchetto da solo, senza memoria. Per permettere al PC
della LAN di navigare, deve consentire sia i pacchetti in uscita verso la porta 443, sia quelli
in ingresso dalla porta 443. Ma &amp;ldquo;permettere l&amp;rsquo;ingresso dalla 443&amp;rdquo; apre la porta a chiunque abbia
quella porta di origine: un attaccante la usa per entrare.&lt;/p&gt;
&lt;p&gt;Un firewall &lt;strong&gt;stateful&lt;/strong&gt; ricorda le connessioni aperte. Permette l&amp;rsquo;uscita, e lascia entrare
&lt;strong&gt;solo&lt;/strong&gt; le risposte che appartengono a una connessione che l&amp;rsquo;host ha iniziato. Non serve nessuna
regola di ritorno. Su Linux questa memoria è &lt;strong&gt;conntrack&lt;/strong&gt;, e ogni connessione attraversa stati
precisi:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  stateDiagram-v2
    [*] --&amp;gt; NEW: primo pacchetto (SYN)
    NEW --&amp;gt; ESTABLISHED: risposta vista (SYN-ACK)
    ESTABLISHED --&amp;gt; ESTABLISHED: traffico nei due sensi
    ESTABLISHED --&amp;gt; [*]: chiusura / timeout
    NEW --&amp;gt; INVALID: pacchetto che non ha senso
    note right of ESTABLISHED
        RELATED: connessione nuova ma legata
        a una esistente (es. dati FTP, errori ICMP)
    end note
&lt;/pre&gt;

&lt;p&gt;La regola d&amp;rsquo;oro di ogni firewall stateful sta in una riga: &lt;strong&gt;accetta ciò che è &lt;code&gt;established&lt;/code&gt; o
&lt;code&gt;related&lt;/code&gt;, scarta ciò che è &lt;code&gt;invalid&lt;/code&gt;, e giudica con attenzione solo i pacchetti &lt;code&gt;new&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;un-ruleset-nftables-commentato&#34;&gt;Un ruleset nftables commentato
&lt;/h2&gt;&lt;p&gt;Questo è il firewall di un host o di un gateway. nftables usa un unico file, con una sintassi più
leggibile di iptables.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#!/usr/sbin/nft -f
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;flush ruleset
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table inet filter {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    chain input {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        type filter hook input priority 0; policy drop;   # default: scarta tutto
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ct state established,related accept                 # le risposte alle connessioni aperte
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ct state invalid drop                               # pacchetti incoerenti: via subito
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        iif lo accept                                       # il traffico di loopback è sempre ok
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ip protocol icmp icmp type echo-request limit rate 5/second accept
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        tcp dport 22 ct state new accept                    # SSH: solo pacchetti nuovi
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    chain forward {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        type filter hook forward priority 0; policy drop;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ct state established,related accept
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ct state invalid drop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        # DMZ (10.0.1.0/24) non deve raggiungere la LAN (10.0.10.0/24) -&amp;gt; minaccia T5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ip saddr 10.0.1.0/24 ip daddr 10.0.10.0/24 drop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    chain output {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        type filter hook output priority 0; policy accept;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le righe che contano:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;policy drop&lt;/code&gt; (riga 8 e la gemella nella catena forward): il default è &lt;strong&gt;negare&lt;/strong&gt;. Tutto ciò che
non è esplicitamente permesso viene scartato. È l&amp;rsquo;opposto di &amp;ldquo;apri e poi chiudi i buchi&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ct state established,related accept&lt;/code&gt; (riga 9): è la riga che rende il firewall stateful.
Le risposte passano senza regole di ritorno.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ct state invalid drop&lt;/code&gt; (riga 10): scarta pacchetti che non appartengono a nessuna connessione
valida, come certi scan.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcp dport 22 ct state new accept&lt;/code&gt; (riga 15): SSH è permesso solo come &lt;strong&gt;nuova&lt;/strong&gt; connessione.
Nota che non serve nessuna regola per far tornare le risposte: le gestisce già la riga 9.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si carica e si ispeziona così:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nft -f firewall.nft        &lt;span class=&#34;c1&#34;&gt;# carica il ruleset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nft list ruleset           &lt;span class=&#34;c1&#34;&gt;# lo mostra&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;conntrack -L               &lt;span class=&#34;c1&#34;&gt;# elenca le connessioni tracciate in tempo reale&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;lattacco-che-lo-stato-ferma&#34;&gt;L&amp;rsquo;attacco che lo stato ferma
&lt;/h2&gt;&lt;p&gt;Un classico scan &lt;code&gt;nmap -sA&lt;/code&gt; (ACK scan) invia pacchetti ACK senza una connessione sottostante, per
capire quali porte sono filtrate. Su un firewall stateless mal scritto, che accetta gli ACK
&amp;ldquo;perché sembrano risposte&amp;rdquo;, lo scan mappa la rete. Su quello sopra, quei pacchetti cadono in
&lt;code&gt;ct state invalid&lt;/code&gt; o non trovano una connessione &lt;code&gt;established&lt;/code&gt;, e vengono scartati. Lo scan non
ottiene informazioni.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# dal nodo attacker, contro il gateway: lo scan non deve rivelare nulla&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nmap -sA 10.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;nftables-contro-iptables&#34;&gt;nftables contro iptables
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;iptables&lt;/th&gt;
&lt;th&gt;nftables&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tabelle&lt;/td&gt;
&lt;td&gt;separate per IPv4/IPv6 (&lt;code&gt;iptables&lt;/code&gt;/&lt;code&gt;ip6tables&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;una sola (&lt;code&gt;inet&lt;/code&gt;) per entrambi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sintassi&lt;/td&gt;
&lt;td&gt;una regola per riga, verbosa&lt;/td&gt;
&lt;td&gt;insiemi, mappe, sintassi compatta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Più condizioni&lt;/td&gt;
&lt;td&gt;più regole&lt;/td&gt;
&lt;td&gt;un&amp;rsquo;unica regola con &lt;code&gt;set&lt;/code&gt; e &lt;code&gt;map&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stato del progetto&lt;/td&gt;
&lt;td&gt;in manutenzione&lt;/td&gt;
&lt;td&gt;successore ufficiale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Non c&amp;rsquo;è motivo di scrivere nuovi firewall in iptables nel 2026. Chi ha ruleset iptables esistenti
può convertirli con &lt;code&gt;iptables-translate&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;lab&#34;&gt;Lab
&lt;/h2&gt;&lt;p&gt;Nel lab containerlab, sul nodo &lt;code&gt;gateway&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Caricate il ruleset con &lt;code&gt;nft -f firewall.nft&lt;/code&gt; e verificate &lt;code&gt;nft list ruleset&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Da &lt;code&gt;victim&lt;/code&gt;, aprite una connessione in uscita (&lt;code&gt;curl&lt;/code&gt; verso un servizio sul gateway) e guardate
&lt;code&gt;conntrack -L&lt;/code&gt; sul gateway: la connessione appare come &lt;code&gt;ESTABLISHED&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Da &lt;code&gt;attacker&lt;/code&gt;, provate &lt;code&gt;nmap -sA 10.0.0.1&lt;/code&gt; e poi &lt;code&gt;nmap -sS 10.0.0.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Osservate quali pacchetti incrementano il contatore &lt;code&gt;invalid&lt;/code&gt; (&lt;code&gt;nft list ruleset&lt;/code&gt; mostra i
contatori se aggiungete &lt;code&gt;counter&lt;/code&gt; alle regole).&lt;/li&gt;
&lt;/ol&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; perché la catena output ha policy accept e non drop?&lt;/summary&gt;
&lt;p&gt;È una scelta, non un obbligo. Per un host singolo, filtrare anche l&#39;output è più sicuro (limita
cosa un processo compromesso può contattare), ma rende il ruleset molto più lungo e rischia di
rompere servizi legittimi. Per un firewall didattico si parte con output in accept e si filtra solo
input e forward. In un ambiente ad alta sicurezza si mette anche output in &lt;code&gt;policy drop&lt;/code&gt;
e si elencano le destinazioni permesse: è lo stesso principio Zero Trust del
&lt;a href=&#34;https://www.matteobianchi.eu/p/zero-trust-architecture/&#34;&gt;post dedicato&lt;/a&gt;, applicato al traffico in uscita.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;Un firewall solido si regge su tre scelte: default &lt;code&gt;drop&lt;/code&gt;, stato con conntrack, e regole che
dicono &lt;em&gt;solo&lt;/em&gt; cosa è nuovo e permesso. Lo stato elimina intere categorie di errori — le regole di
ritorno — e con esse intere categorie di attacchi.&lt;/p&gt;
&lt;p&gt;Il firewall blocca ciò che riconosce come vietato. Ma cosa succede quando il traffico è permesso e
contiene comunque un attacco? Serve qualcosa che guardi &lt;em&gt;dentro&lt;/em&gt; i pacchetti. È il compito di un
IDS/IPS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prossimo nella serie:&lt;/strong&gt; &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/ids-ips-suricata/&#34; &gt;05 · IDS/IPS con Suricata&lt;/a&gt; ·
&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/network-security-roadmap/&#34; &gt;Torna alla roadmap&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>VLAN hopping e hardening degli switch</title>
        <link>https://www.matteobianchi.eu/p/vlan-hopping-and-switch-hardening/</link>
        <pubDate>Tue, 11 Aug 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/vlan-hopping-and-switch-hardening/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/vlan-hopping-and-switch-hardening/cover.png" alt="Featured image of post VLAN hopping e hardening degli switch" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;La segmentazione in VLAN è la risposta alla minaccia T1 del
&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/threat-modeling-networks/&#34; &gt;threat model&lt;/a&gt;: la rete ospiti e la LAN uffici
sulla stessa infrastruttura fisica, ma su VLAN diverse, senza rotte tra loro. Funziona finché un
attaccante non riesce a &lt;strong&gt;uscire dalla propria VLAN&lt;/strong&gt;. Il VLAN hopping fa esattamente questo, e
nei due casi classici non sfrutta un bug: sfrutta configurazioni lasciate ai valori di default.&lt;/p&gt;
&lt;h2 id=&#34;ripasso-tag-access-e-trunk&#34;&gt;Ripasso: tag, access e trunk
&lt;/h2&gt;&lt;p&gt;Un frame che viaggia in una VLAN porta un tag 802.1Q: 12 bit che dicono a quale VLAN appartiene.
Le porte dello switch sono di due tipi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;access&lt;/strong&gt;: appartiene a una sola VLAN; i frame entrano ed escono senza tag.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;trunk&lt;/strong&gt;: porta più VLAN tra switch; i frame viaggiano con il tag, tranne quelli della &lt;strong&gt;VLAN
nativa&lt;/strong&gt;, che per compatibilità storica vanno &lt;strong&gt;senza tag&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Quest&amp;rsquo;ultima eccezione — la VLAN nativa non taggata — è la porta d&amp;rsquo;ingresso di entrambi gli
attacchi.&lt;/p&gt;
&lt;h2 id=&#34;attacco-1-switch-spoofing-dtp&#34;&gt;Attacco 1: switch spoofing (DTP)
&lt;/h2&gt;&lt;p&gt;Sugli switch Cisco il &lt;strong&gt;Dynamic Trunking Protocol (DTP)&lt;/strong&gt; negozia automaticamente se una porta
diventa trunk. Di default molte porte sono in &lt;code&gt;dynamic auto&lt;/code&gt; o &lt;code&gt;dynamic desirable&lt;/code&gt;: se l&amp;rsquo;altro
lato chiede un trunk, lo switch glielo concede.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;attaccante finge di essere uno switch e chiede un trunk. Se la porta accetta, da quel momento
l&amp;rsquo;attaccante riceve il traffico di &lt;strong&gt;tutte&lt;/strong&gt; le VLAN che passano sul trunk.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# yersinia fa la negoziazione DTP fingendosi uno switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;yersinia dtp -attack &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; -interface eth1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Nota sul lab: DTP è un protocollo proprietario Cisco. Open vSwitch non lo parla, quindi questo
attacco si riproduce solo in GNS3 con un&amp;rsquo;immagine Cisco IOSvL2 (o IOU). Le immagini Cisco non
sono redistribuibili: per il resto della serie restiamo su containerlab.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;attacco-2-double-tagging&#34;&gt;Attacco 2: double tagging
&lt;/h2&gt;&lt;p&gt;Questo funziona anche senza DTP, su qualunque switch 802.1Q, ed è il motivo per cui la VLAN
nativa non va mai usata per host reali. L&amp;rsquo;attaccante, su una porta access della VLAN nativa (VLAN
1), costruisce un frame con &lt;strong&gt;due&lt;/strong&gt; tag: uno esterno (VLAN 1, quella nativa) e uno interno (la
VLAN bersaglio, es. VLAN 20).&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart LR
    A[&amp;#34;attacker&amp;lt;br/&amp;gt;VLAN nativa 1&amp;#34;] --&amp;gt;|frame con 2 tag:&amp;lt;br/&amp;gt;outer=1, inner=20| S1[Switch 1]
    S1 --&amp;gt;|toglie il tag nativo 1,&amp;lt;br/&amp;gt;resta inner=20| S2[Switch 2 / trunk]
    S2 --&amp;gt;|consegna in VLAN 20| V[&amp;#34;victim&amp;lt;br/&amp;gt;VLAN 20&amp;#34;]
    style A fill:#fde2e4,stroke:#e63946
&lt;/pre&gt;

&lt;p&gt;Il primo switch toglie il tag esterno — è la VLAN nativa, va rimossa — e inoltra il frame sul
trunk. A quel punto resta solo il tag interno, VLAN 20: il secondo switch lo consegna nella VLAN
bersaglio. Il frame ha saltato la VLAN. È &lt;strong&gt;monodirezionale&lt;/strong&gt; (la risposta non torna indietro
allo stesso modo), ma basta per iniettare pacchetti, ad esempio un DHCP rogue in un&amp;rsquo;altra VLAN.&lt;/p&gt;
&lt;p&gt;Nel lab con Open vSwitch si riproduce configurando le porte e inviando un frame a doppio tag:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# porta attaccante: access sulla VLAN nativa 1; porta vittima: trunk con VLAN 20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ovs-vsctl &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; port p-attacker &lt;span class=&#34;nv&#34;&gt;tag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ovs-vsctl &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; port p-victim   &lt;span class=&#34;nv&#34;&gt;trunks&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;1,20
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;scapy.all&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ether&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dot1Q&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ICMP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sendp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# doppio tag: outer VLAN 1 (nativa), inner VLAN 20 (bersaglio)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;frame&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ether&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dot1Q&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vlan&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Dot1Q&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vlan&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;10.0.20.10&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ICMP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sendp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iface&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;eth1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;la-difesa-hardening-dello-switch&#34;&gt;La difesa: hardening dello switch
&lt;/h2&gt;&lt;p&gt;Quattro regole chiudono entrambi gli attacchi. Le prime due riguardano il double tagging, le
ultime due lo switch spoofing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;! 1. spegni esplicitamente DTP su tutte le porte di accesso
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;switchport mode access
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;switchport nonegotiate
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;! 2. la VLAN nativa del trunk deve essere una VLAN &amp;#34;morta&amp;#34;, non usata da nessun host
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;switchport trunk native vlan 999
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;! 3. consenti sul trunk solo le VLAN che servono davvero
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;switchport trunk allowed vlan 10,20,30
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;! 4. metti in shutdown le porte inutilizzate e assegnale a una VLAN inesistente
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Le due righe evidenziate sono le decisive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;switchport nonegotiate&lt;/code&gt; spegne DTP: la porta non negozia più nulla, lo switch spoofing fallisce.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;switchport trunk native vlan 999&lt;/code&gt; sposta la VLAN nativa su una VLAN che non contiene host.
Il double tagging ha bisogno che l&amp;rsquo;attaccante sia &lt;strong&gt;sulla&lt;/strong&gt; VLAN nativa: se la nativa è una VLAN
morta, nessun attaccante ci si trova, e l&amp;rsquo;attacco non parte.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La regola generale: &lt;strong&gt;la VLAN nativa non deve mai coincidere con una VLAN di dati&lt;/strong&gt;, e DTP va
sempre spento a mano.&lt;/p&gt;
&lt;h2 id=&#34;lab&#34;&gt;Lab
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Con Open vSwitch, configurate &lt;code&gt;p-attacker&lt;/code&gt; come access VLAN 1 e &lt;code&gt;p-victim&lt;/code&gt; come trunk con VLAN 20.&lt;/li&gt;
&lt;li&gt;Da &lt;code&gt;victim&lt;/code&gt;, catturate il traffico sulla VLAN 20 (&lt;code&gt;tcpdump -i eth1.20&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Da &lt;code&gt;attacker&lt;/code&gt;, inviate il frame a doppio tag con lo script scapy.&lt;/li&gt;
&lt;li&gt;Verificate che l&amp;rsquo;ICMP arrivi sulla VLAN 20, pur partendo dalla VLAN 1.&lt;/li&gt;
&lt;li&gt;Cambiate la VLAN nativa del trunk (&lt;code&gt;ovs-vsctl set port p-victim ... tag&lt;/code&gt;) e ripetete.&lt;/li&gt;
&lt;/ol&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; perché il double tagging è monodirezionale?&lt;/summary&gt;
&lt;p&gt;Il trucco funziona solo all&#39;andata, perché sfrutta il fatto che il &lt;em&gt;primo&lt;/em&gt; switch rimuove
il tag della VLAN nativa. La vittima, rispondendo, invia un frame normale a singolo tag nella VLAN
20: quando arriva allo switch non c&#39;è nessun tag nativo da togliere che la rimandi magicamente nella
VLAN 1 dell&#39;attaccante. Per questo il double tagging si usa per &lt;em&gt;iniettare&lt;/em&gt; (un DHCP rogue, un
pacchetto malevolo), non per instaurare una sessione bidirezionale.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;Il VLAN hopping non buca la cifratura né sfrutta un difetto del protocollo: sfrutta due default.
DTP che negozia da solo e la VLAN nativa condivisa con gli host. Spegnere DTP e isolare la VLAN
nativa sono due righe di configurazione che molti dimenticano.&lt;/p&gt;
&lt;p&gt;Finora abbiamo lavorato sotto il livello 3. Dal prossimo capitolo saliamo: un firewall stateful
che decide quale traffico IP può attraversare i confini di fiducia disegnati nel threat model.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prossimo nella serie:&lt;/strong&gt; &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/stateful-firewalls-nftables/&#34; &gt;04 · Firewall stateful con nftables&lt;/a&gt; ·
&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/network-security-roadmap/&#34; &gt;Torna alla roadmap&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
