<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>crittografia &amp;mdash; Cyberdyne Systems</title>
    <link>https://noblogo.org/aytin/tag:crittografia</link>
    <description>&#34;Fare o non fare. Non c&#39;è provare!&#34;</description>
    <pubDate>Thu, 30 Apr 2026 09:59:16 +0000</pubDate>
    <item>
      <title>fwknop: proteggere servizi con Single Packet Authorization (SPA)</title>
      <link>https://noblogo.org/aytin/fwknop-proteggere-servizi-con-single-packet-authorization-spa</link>
      <description>&lt;![CDATA[fwknop&#xA;Cos&#39;è fwknop&#xA;fwknop è un software di port knocking che usa uno schema di autenticazione chiamato &#34;Single Packet Authorization&#34; ipotizzato e formalizzato dallo stesso autore per risolvere le debolezze più comuni del classico port-knocking.&#xA;!--more--&#xA;&#xA;Cos&#39;è fwknop&#xA;Installazione client e server&#xA;Configurazione client&#xA;   Generazione della sola chiave&#xA;   Generazione chiave + configurazione complessa&#xA;Configurazione server&#xA;Scenari&#xA;    Protezione di un servizio con SPA&#xA;       Configurazione lato server&#xA;       Configurazione lato client&#xA;    Ghost locale sullo spaserver&#xA;       Configurazione lato server&#xA;       Invocazione client&#xA;    SPA attraverso gateway NAT&#xA;       Configurazione lato server&#xA;       Invocazione client&#xA;    SPA Ghost Service&#xA;       Invocazione client&#xA;E se volessi usare la crittografia asimmetrica?&#xA;Osservazioni su access.conf&#xA;   Configurazione stanze con spa server come bastion host &#xA;   Alice&#xA;   Bob&#xA;   Carol&#xA;&#xA;fwknop, come il port knocking, unisce la comunicazione passiva di informazioni di autenticazione al filtraggio di tutti i pacchetti che non rispettano le sequenze di knock.&#xA;&#xA;Il classico approccio di port-knocking sfrutta le intestazioni dei pacchetti (2 byte) e non il loro payload, per cui è necessario mandare un certo numero di pacchetti per mappare una porta senza generare falsi positivi. Questo però comporta inevitabilmente almeno due problemi:&#xA;&#xA;suscettibilità ad attacchi di spoofing&#xA;se le sequenze di knocking sono eccessivamente articolate (magari per inviare più informazioni), data l&#39;imprevedibilità della rete e l&#39;assenza di costrutti che garantiscano lo stesso ordine d&#39;arrivo dei pacchetti, c&#39;è la possibilità che il server non riesca a ricostruire la sequenza corretta. &#xA;&#xA;Il client fwknop (SPA Client) invia al server (SPA Server) un singolo pacchetto di dimensioni relativamente maggiori (possibile sfruttando il payload) per comunicare informazioni di accesso e interi comandi destinati al filtraggio dei pacchetti.&#xA;&#xA;Il tutto viene protetto da una cifratura simmetrica con autenticazione (aes256-cbc + hmac-sha256, che sarà quella usata nel prosieguo perché più semplice da gestire) o asimmetrica che, al costo di una maggiore complessità di gestione, aggiunge la caratteristica di non ripudio alle caratteristiche di confidenzialità, integrità e autenticazione possedute anche dal primo schema di cifratura.&#xA;&#xA;Installazione client e server&#xA;fwknop client e server sono pacchettizzati per ogni distro linux (su Mac OS è possibile ricorrere a brew).&#xA;Sistemi rpm-based&#xA;Installa il client (fwknop) e il server (fwknopd)&#xA;dfn install fwknop&#xA;Sistemi debian-based&#xA;Installa il client (fwknop)&#xA;apt install fwknop-client&#xA;&#xA;Installa il server (fwknopd)&#xA;apt install fwknop-server&#xA;Configurazione client&#xA;La configurazione lato client viene conservata nel file .fwknoprc che può essere editato a a mano oppure attraverso il client fwknop salvando nel file .fwknoprc quelle che vengono definite &#34;stanze&#34;.&#xA;&#xA;Nella configurazione è molto importante la generazione della chiave. Se la chiave è simmetrica, la si può generare con fwknop.&#xA;&#xA;Di seguito, due esempi di creazione di stanze con fwknop, una minimale (che useremo nel resto del documento) e una più complessa.&#xA;Generazione della sola chiave&#xA;Genero la chiave usando il default: aes256-cbc + hmac-sha256.&#xA;fwknop -n test -k --use-hmac --save-rc-stanza&#xA;E in .fwknoprc troverò una nuova sezione [test]&#xA;[test]&#xA;KEYBASE64                  dRYAH2O9FCUpNz1aMmlke9/AkGVdcLrnWxDy7jZC1wg=&#xA;HMACKEYBASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==&#xA;USEHMAC                    Y&#xA;Generazione chiave + configurazione complessa&#xA;fwknop -n test -k -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306 --save-rc-stanza&#xA;che ha  il corrispondente .fwknoprc:&#xA;[test]&#xA;ACCESS                      tcp/80&#xA;SPASERVER                  107.23.186.49&#xA;KEYBASE64                  0d/VcRXnf2si7hvfDsPN3YIG4Q7aPLU9Ndd5Pe+eMIQ=&#xA;HMACKEYBASE64             EEXu0VCPQKPGp8FC8tYS6I/p56nWlot93BV3CPVf3De9FkM04z1SBWTUEJejHpq45+at7VQirgTYvSxeLoZkKQ==&#xA;NATACCESS                  10.0.0.132:3306&#xA;RESOLVEIPHTTPS            Y&#xA;WGETCMD                    /usr/bin/wget&#xA;La spiegazione di questa configurazione specifica la troveremo più avanti nel par. 4. SPA Ghost Service. È solo per far vedere che il file di configurazione .fwknoprc può essere rimpiazzato in toto dall&#39;invocazione via cli del client. Chiave compresa, se è il caso.&#xA;&#xA;Affinché la &#34;stanza&#34; venga creata, deve necessariamente essere presente almeno uno fra valori dei flag -D e -n. Quest&#39;ultimo costituirà anche il nome alla sezione corrispondente, altrimenti sarà il valore di -D .&#xA;&#xA;Per usare il cient con le preimpostazioni di .fwinoprc, basterà indicare il nome della sezione:&#xA; fwknop -n test&#xA;Ne consegue che i nomi di sezione devono essere univoci.&#xA;&#xA;Da ricordare che quando si usa il client  quello che è importante specificare nel file .fwknoprc o nei parametri è:&#xA;&#xA;ALLOW\IP (-a): che indica l&#39;ip da cui sto facendo la richiesta e che deve rientrare nel SOURCE specificato nel server. Se l&#39;ip non è noto magari perché lo spaclient viene nattato, si può ricorrere alla risoluzione dell&#39;ip che viene instradato esternamente (chiamando un servizio esterno):&#xA;   RESOLVE\IP\HTTPS (-R): booleano [Y|N] per abilitare lo spaclient a richiedere la risoluzione del proprio ip;&#xA;   WGET\CMD (-w): path del comando wget che chiamerà lo script di risoluzione&#xA;ACCESS (-A): benché non sia obbligatorio per il server, il client deve necessariamente specificare a quali porte/protocolli intende accedere. Se specificati anche nel server, devono appartenere alla sua lista&#xA;SPA\SERVER (-D): indica l&#39;ip o l&#39;url dello spaserver&#xA;KEY: la chiave simmetrica per AES-CBC (default: aes256);&#xA;HMAC\KEY: la chiave per HMAC (default: sha256)&#xA;&#xA;Configurazione server&#xA;Il server si compone di due file:&#xA;&#xA;fwknopd.conf: configura il servizio.&#xA;È il punto in cui si imposta la porta su cui il servizio sarò in ascolto per ricevere il pacchetto, l&#39;interfaccia, le configurazioni, anche complesse, dei firewall da manipolare in seguito al port-knocking (iptables, firewalld, ipf);&#xA;access.conf: regola gli accessi degli utenti.&#xA;È il punto in cui si indicano quegli elementi  necessari ad autenticare ed autorizzare gli utenti, elementi che dovranno coincidere con ciò che contiene il pacchetto.&#xA;È possibile creare una cartella, da indicare in fwknopd.conf, contenente singole configurazioni di accesso, per utente o per policy, piuttosto che creare un unico, lungo elenco in access.conf.&#xA;&#xA;Anche access.conf è un elenco di &#34;stanze&#34;, i punti d&#39;accesso per i client contenenti come minimo la rete abilitata all&#39;accesso e la chiave con cui si presenta l&#39;utente, come visto in Configurazione client: &#xA;&#xA;SOURCE: gli ip o le subnet del client da abilitare all&#39;accesso&#xA;KEY: la chiave simmetrica per AES-CBC (default: aes256)&#xA;HMAC\KEY: la chiave per HMAC (default: sha256)&#xA;&#xA;Altri parametri utili a rafforzare ulteriormente il legame con le richieste client, ma non obbligatori per l&#39;avvio del servizio, sono:&#xA;&#xA;OPEN\PORTS: specifica quali porte e quali protocolli abilitare&#xA;REQUIRE\USERNAME: specifica un nome utente col quale il client si deve presentare&#xA;REQUIRE\SOURCE\ADDRESS: impone che il client specifichi l&#39;ip da cui sta facendo la richiesta in modo da mitigare la possibilità di attacchi MITM&#xA;&#xA;Quando queste opzioni sono presenti sul server, dovranno essere obbligatoriamente specificate anche nel client.&#xA;Dopo aver visto le configurazioni di client e server, vedremo fwknop in azione in alcuni casi &#34;reali&#34;. &#xA;&#xA;Scenari&#xA;Grazie alla sua capacità sia di manipolare, anche in maniera piuttosto articolata, i firewall che concedono l&#39;accesso alle risorse che ad eseguire interi comandi che fwknop mostra tutta la sua versatilità.&#xA;&#xA;In particolare è col NAT che riesce ad andare oltre la sua natura di port knocking dove, grazie ad una combinazione di DNAT e SNAT, riesce a:&#xA;&#xA;girare richieste su server, che normalmente non sarebbero raggiungibili, posti nel backend insieme allo stesso spaserver o dietro di esso&#xA;presentare un servizio su una porta diversa rispetto a quella su cui è in ascolto&#xA;&#xA;diventando a tutti gli effetti un bastion host per l&#39;esposizione autenticata e sicura di servizi critici.&#xA;&#xA;Riassumendo, fwknop può:&#xA;&#xA;essere messo direttamente sul server a protezione di uno o più servizi (caso classico);&#xA;può nattare un servizio sullo stesso spaverser con un inoltro delle porte locali e, contestualmente, ghostare un servizio con un altro&#xA;può nattare un servizio posto nel backend;&#xA;come prima, traslare porte e/o &#34;ghostare&#34; servizi &#xA;&#xA;Gli scenari che andrò a mostrare, copriranno i casi più comuni:&#xA;&#xA;Protezione di un servizio con SPA&#xA;Ghost locale sullo spaserver&#xA;SPA attraverso Gateway NAT&#xA;SPA Ghost Service&#xA;&#xA;Lato client, fwknop usi baserà sempre sulla configurazione minimale vista prima nel paragrafo &#34;Configurazione client&#34;/u. Il resto delle configurazioni verrà passato via cli.&#xA;&#xA;1. Protezione di un servizio con SPA&#xA;La cosa più semplice da fare è mettere lo spaserver a protezione diretta del servizio insieme ad un firewall che implementa una policy default-drop.&#xA;Ipotizziamo ad es. di proteggere l&#39;accesso in ssh sul nodo centrale (192.168.100.10) di una rete a stella.&#xA;&#xA;fwknop spa server&#xA;&#xA;Configurazione lato server&#xA;&#xA;fwknopd.conf:&#xA;PCAPINTF                   eth1;&#xA;PCAPFILTER                 udp port 62201;&#xA;&#xA;access.conf:&#xA;%includefolder /etc/fwknop/access.conf.d&#xA;&#xA;test.conf:&#xA;SOURCE                      192.168.100.0/24&#xA;REQUIRESOURCE              Y&#xA;KEYBASE64                  dRYAH2O9FCUpNz1aMmlke9/AkGVdcLrnWxDy7jZC1wg=&#xA;HMACKEYBASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==&#xA;&#xA;Configurazione lato client&#xA;&#xA;.fwknoprc:&#xA;[test]&#xA;KEYBASE64                  dRYAH2O9FCUpNz1aMmlke9/AkGVdcLrnWxDy7jZC1wg=&#xA;HMACKEYBASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==&#xA;USEHMAC                    Y&#xA;&#xA;fwknop:&#xA;fwknop -n test -a 192.168.100.15 -A tcp/22 -D 192.168.100.10&#xA;ssh 192.168.100.10&#xA;&#xA;Supponiamo adesso di voler proteggere l&#39;accesso ssh di una macchina dove però il client , caso molto frequente, sia in una rete privata e nattato con un ip pubblico (rete domestica o rete mobile per es.).&#xA;&#xA;Non possiamo sapere con certezza quale sarà l&#39;ip del client per cui, lato server, dovrò essere disposto ad accettare qualunque sorgente e lato client lascerò che l&#39;ip venga risolto dinamicamente. &#xA;&#xA;fwknop con client nat&#xA;&#xA;fwknop -n test -R -w /usr/bin/wget -A tcp/22 -D 107.23.186.49&#xA;ssh 107.23.186.49&#xA;L&#39;opzione:&#xA;&#xA;-R permette di risolvere il proprio ip pubblico usando wget ( di cui va dato il path) che richiamerà uno script posto di default in https://www.cipherdyne.org/cgi-bin/myip, altrimenti se ne può specificare un altro analogo con --resolve-url url. Questo perché l&#39;ip reale del client viene nattato con l&#39;ip pubblico 154.23.162.98, quindi il pacchetto inviato allo spaserver deve contenere questo IP come richiedente, non quello privato (che altrimenti non riceverebbe mai risposta)&#xA;-D serve sempre per specificare l&#39;ip, stavolta pubblico, dello spaserver  (107.23.186.49) &#xA;&#xA;N.B.  Non sapendo quale sarà l&#39;ip richiedente, la clausola  SOURCE nel file test.conf non potrà contenere un ip o una subnet, quanto piuttosto:&#xA;...&#xA;SOURCE                      ANY&#xA;...&#xA;2.  Ghost locale sullo spaserver&#xA;Assumiamo che la topologia di rete sia semplice come quella del caso precedente ma ipotizziamo che il client che si autentichi con SPA, acceda ad un servizio protetto la cui porta sia associata contemporaneamente ad un altro servizio esposto pubblicamente.&#xA;&#xA;In questo modo qualunque un altro client (anche attori malevoli) che volesse connettersi a quella porta, continuerebbe a vedere solo il servizio pubblico e non quello protetto.&#xA;&#xA;Questa magia viene resa possibile grazie ad un DNAT locale che mappa temporaneamente, e solo per quell&#39;ip, la porta pubblica con quella del servizio da proteggere.&#xA;&#xA;Nel nostro esempio vogliamo accedere in ssh alla macchina ma sulla porta 80, corrispondente ad un servizio web esposto pubblicamente.&#xA;&#xA;fwknop con server local nat&#xA;&#xA;Configurazione lato server&#xA;&#xA;fwknopd.conf:&#xA;PCAPINTF                   enp0s8;&#xA;ENABLEIPTFORWARDING       Y;&#xA;ENABLEIPTLOCALNAT        Y;&#xA;&#xA;access.conf:&#xA;Rimane invariato.&#xA;&#xA;Invocazione client&#xA;&#xA;fwknop: &#xA;&#xA;fwknop -n test -R -w /usr/bin/wget -A tcp/22 -D 107.23.186.49 --nat-local --nat-port 80&#xA;ssh 107.23.186.49 -p80&#xA;&#xA;3. SPA attraverso gateway NAT&#xA;In questo caso lo spa server verrà usato come gateway per accedere a servizi posti sulla rete interna. ad es. un db mybsql su una macchina (10.0.0.132) posta dietro lo spa server.&#xA;&#xA;Per ottenere tutto questo, bisogna abilitare il port forwarding e il SNAT nel file fwknopd.conf in modo che vengano create le regole DNAT e MASQUERADE su iptables affinché le richieste vengano inoltrate rispettivamente verso la macchina  che eroga il servizio (mysql) e che i pacchetti di ritorno viaggino correttamente verso lo spa server e quindi verso il client. Il file access.conf rimane invariato&#xA;&#xA;fwknop con gateway nat&#xA;&#xA;Configurazione lato server&#xA;&#xA;fwknopd.conf:&#xA;&#xA;PCAPINTF                   enp0s8;&#xA;ENABLEIPTFORWARDING       Y;&#xA;ENABLEIPTSNAT             Y;&#xA;&#xA;Invocazione client&#xA;fwknop: &#xA;&#xA;fwknop -n test -R -w /usr/bin/wget -A tcp/3306 -D 107.23.186.49 -N 10.0.0.132&#xA;mysql -h 107.23.186.49 -u user -p&#xA;4. SPA Ghost Service&#xA;Adesso vogliamo che l&#39;accesso a mysql venga &#34;nascosto&#34; da un servizio legittimo esposto pubblicamente (un servizio http sulla porta 80).&#xA;&#xA;fwknop con ghost service&#xA;&#xA;La configurazione lato server (fwknopd.conf, access.conf) rimane invariata rispetto a prima.&#xA;&#xA;Invocazione client&#xA;fwknop: &#xA;&#xA;fwknop -n test -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306&#xA;mysql -h 107.23.186.49:80 -u user -p &#xA;E se volessi usare la crittografia asimmetrica?&#xA;La crittografia asimmetrica usata con hmac costituisce un ulteriore enhancement di sicurezza.&#xA;&#xA;Mentre con la crittografia simmetrica+hmac si ha una sorta di implicito mutuo riconoscimento, con la crittografia asimmetrica è sufficiente che il client sia riconosciuto dal server.&#xA;&#xA;Affinché ciò avvenga, il client inva il pacchetto spa firmato con la sua chiave privata e lo cifra con la chiave pubblica dello spaserver.&#xA;Lo spaserver riceve il pacchetto, verifica la firma con la chiave pubblica del client, lo decifra con la sua chiave privata, proseguendo poi col resto del processo di autorizzazione e accesso.&#xA;&#xA;È consigliata la creazione di chiavi apposite per fwknop, non quelle personali. Per il client creeremo una chiave di sola firma e per il server una chiave completa. Le corrispondenti chiavi private possono anche essere lasciate prive di password. Se non lo fossero, dovranno essere inserite nel file di configurazione in mancanza delle quali, soprattutto lato server, finirebbero per richiedere a runtime una poco gestibile interazione con l&#39;utente. &#xA;&#xA;The last but not the least, bisogna tenere presente che, come riportato dalla documentazione (https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html#fwknop-gpg) la scelta delle chiavi è un&#39;operazione critica.&#xA;&#xA;La cifratura asimmetrica, a differenza di quella simmetrica, tende a produrre dei payload decisamente più cicciotti.&#xA;Quindi, per non correre il rischio di avere un payload che superi il default dell&#39;MTU ethernet (1500 byte), bisogna &#34;vincolare&#34; la scelta della chiave del server (di cifratura) a quella del client (di firma).&#xA;&#xA;Le chiavi a curva ellittica sarebbero una buona soluzione. Purtroppo funzionano solo per la firma, non per la cifratura. Quindi vanno bene per il client e non per il server.&#xA;&#xA;Se client e server usassero chiavi rsa, sarebbe meglio per il server usare chiavi non superiori a 3072 bit (caso limite), consigliati 2048 bit. In questo modo un&#39;eventuale chiave client di 4096 bit sarebbe tollerata. Altrimenti si rischierebbe un fault: fwknop: fkospadatafinal: Error 59 - Args contain invalid data: FKOERRORINVALIDDATAENCRYPTGPGRESULTMSGLENVALIDFAIL&#xA;&#xA;Nell&#39;esempio che segue, prenderemo in esame lo scenario 4, ma con autenticazione GPG, con una chiave ECC per il client e una chiave rsa 3072 bit per il server (ma sarebbe tollerata anche una chiave a 4096 bit). &#xA;&#xA;Creazioni delle chiavi su server e client&#xA;spa client&#xA;Creazione chiave di sola firma&#xA;gpg --batch --passphrase &#39;&#39; --quick-gen-key &#34;fwknop client (chiave del client fwknop) fwknop@spaclient&#34; ed25519 cert,sign never`&#xA;&#xA;esporta chiave pubblica e invio a spaserver&#xA;gpg -o fwknop@spaclient.gpg --export fwknop@spaclient&#xA;scp fwknop@spaclient.gpg 107.23.186.49:&#xA;spa server &#xA;Creazione chiave di firma e cifratura. Quella di cifratura è una rsa 3072 bit&#xA;gpg --batch --passphrase &#39;&#39; --quick-gen-key &#34;fwknopd server (chiave del server fwknopd) fwknopd@spaserver&#34; ed25519 cert,sign never&#xA;gpg --batch --passphrase &#39;&#39; --quick-add-key &#39;2BCD6BEF564A54362F8242017C17EC045408C7DB&#39; rsa3072 encr never&#xA;&#xA;esporta chiave pubblica e invio al client&#xA;gpg -o fwknopd@spaserver.gpg --export fwknopd@spaserver&#xA;scp fwknopd@spaserver.gpg 107.23.186.160:&#xA;Importazioni e firma delle chiavi&#xA;importazione e firma della chiave&#xA;gpg --import fwknopd@spaserver.gpg&#xA;gpg --sign-key fwknopd@spaserver&#xA;&#xA;importazione e firma della chiave&#xA;gpg --import fwknop@spaclient.gpg&#xA;gpg --sign-key fwknop@spaclient&#xA;Configurazione access.conf.d/test.conf e .fwknoprc&#xA;Analogamente a quanto fatto con la cifratura simmetrica:&#xA;&#xA;access.conf.d/testgpg.conf&#xA;SOURCE                      ANY&#xA;REQUIRESOURCE              Y&#xA;HMACKEYBASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==&#xA;GPGALLOWNOPW             Y  &#xA;GPGREMOTEID               1B0D9549&#xA;GPGDECRYPTID              5408C7DB &#xA;&#xA;.fwknoprc&#xA;[testgpg]&#xA;USEGPG                     Y&#xA;GPGRECIPIENT               5408C7DB&#xA;GPGSIGNER                  1B0D9549&#xA;HMACKEYBASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==&#xA;USEHMAC                    Y&#xA;&#xA;Test client&#xA;fwknop --verbose -n testgpg -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306&#xA;mysql -h 107.23.186.49:80 -u user -p&#xA;----&#xA;N.B.: Gli scenari 2, 3 e 4 sono le riproposizioni di ciò che viene presentato da Michael Rash durante lo ShmooCon del 2013 in https://www.youtube.com/watch?v=GCGiI6DJuIc (scenario 2)  e nel suo blog (https://www.cipherdyne.org/blog/categories/port-knocking-and-spa.html) in  https://www.youtube.com/watch?v=tz-xK1BarKk  (scenario 3 e 4)&#xA;&#xA;Ghost Service e SPA across gateway NAT non sono chiarissimi negli esempi forniti, mancano alcuni dettagli per me, che non sono un esperto di reti, fondamentali come la giusta evidenza e l&#39;importanza sull&#39;uso corretto del local nat nel primo caso e di SNAT negli altri due.&#xA;&#xA;Tutti gli esempi, in particolare 3 e 4, sono stati testati con un&#39;infrastruttura speculare a quella usata nel 2° video, ottenuta non già attraverso AWS ma con il più modesto VirtualBox che ha comunque svolto egregiamente il suo compito.&#xA;&#xA;Per chi volesse effettuare delle prove sul campo, spero, in futuro, di mettere a disposizione questo piccolo laboratorio attraverso Vagrant e di dare indicazioni sulle configurazioni degli apparati che si occupano di routing e nat.&#xA;----&#xA;Osservazioni su access.conf&#xA;access.conf permette di stabilire chi accede e su quali risorse.&#xA;&#xA;Le porte specificate nella clausola ACCESS permetteranno al clent di accedere con la stessa chiave:&#xA;&#xA;a tutti i servizi relativi, se lo spaserver è installato sulla stessa macchina che li eroga;&#xA;a tutti i server relativi (eroganti i servizi indicati in ACCESS) nattati dallo spaserver; &#xA;ad uno solo dei servizi, e solo fra quelli &#34;nattabili&#34;, se nell&#39;access.conf uso le clausole FORCENAT/SNAT, per quanto siano larghe le maglie della clausola ACCESS. Inoltre posso usare ACCESS per concedere o meno la possibilità di ghostare un servizio &#xA;&#xA;Vediamo con un po&#39; di esempi cosa possiamo fare&#xA;&#xA;fwknop bastion host&#xA;&#xA;Questo scenario riprende ed estende quello visto finora, dove si evidenzia il natting sia dei client che dei server, entrambi nelle loro lan private.&#xA;&#xA;A differenza degli scenari precedenti, lo spaserver non è direttamente esposto ma è anch&#39;esso nel backend. Gli altri server espongono un server web sulla porta 8080, un remote-desktop sulla 3389 e un db mysql sulla 3306.&#xA;&#xA;Per mostrare quanto fwknop possa essere flessibile, supponiamo di avere 3 utenti, Alice, Bob e Carol, ognuno con privilegi differenti.&#xA;fwknop sarà configurato come bastion host.&#xA;&#xA;Supponiamo sempre che lo spaserver esponga pubblicamente un sito web sulla porta 80 (utile per un eventuale ghosting dei servizi) .&#xA;&#xA;Configurazione stanze con spa server come bastion host&#xA;La configurazione delle stanze richiederà al client anche di specificare l&#39;utente.&#xA;&#xA;access.conf.d/alice.conf&#xA;alice&#xA;SOURCE                      ANY&#xA;REQUIRESOURCE              Y&#xA;SPOOFUSER                  usernamealice&#xA;HMACKEYBASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==&#xA;GPGALLOWNOPW             Y  &#xA;GPGREMOTEID               1B0D9549&#xA;GPGDECRYPTID              5408C7DB &#xA;access.conf.d/bob.conf&#xA;bob&#xA;SOURCE                      ANY&#xA;OPENPORTS                  tcp/3306, tcp/3389&#xA;SPOOFUSER                  usernamebob&#xA;REQUIRESOURCE              Y&#xA;KEYBASE64                  /bUdrMWFbc754iitBPAm2iwpzJ9CeetVxKXJOY0b9yI=&#xA;HMACKEYBASE64             K22gfP5eq8Hveg58NeCWbXJEL/S/R74wGhxG3S6Gv+hl/bbqOZhExsRuLRrIvyZmW7iseEN8E48wHRQsUMozgA==&#xA;access.conf.d/carol.conf&#xA;carol&#xA;SOURCE                      154.23.162.32/27, 154.23.162.96/27&#xA;OPENPORTS                  tcp/3306&#xA;SPOOFUSER                  usernamecarol&#xA;REQUIRESOURCE              Y&#xA;KEYBASE64                  GK1CE1BE+ItAfZCMH9NPUkAd+rQv2mTm5df1wjN1w6w=&#xA;HMACKEYBASE64             ewbyRRz2B7mqQnXRa7Mm67Qa4xIzr1/oyKAhHSQ7+rwtNcEZrZbXeHb97drG8ebZ06F7OOLjp1i9Fy+DtN3F7Q==&#xA;&#xA;Alice&#xA;Con le stanze configurate in questo modo, alice, che ha una chiave gpg, può usare la stessa chiave da qualunque ip, per raggiungere uno qualunque fra i 3 server in backend.&#xA;Es.&#xA;webserver&#xA;fwknop -n alice -A tcp/8080 -R -w /usr/bin/wget -D 5.112.84.211 -U usernamealice -N 192.168.100.112&#xA;o&#xA;remote-desktop&#xA;fwknop -n alice -A tcp/3389 -R -w /usr/bin/wget -D 5.112.84.211 -U usernamealice -N 192.168.100.25&#xA;o&#xA;mysql&#xA;fwknop -n alice -A tcp/3306 -R -w /usr/bin/wget -D 5.112.84.211 -U usernamealice -N 192.168.100.109&#xA;Alice può anche &#34;ghostare&#34; il servizio, ad es. mysql&#xA;mysql&#xA;fwknop -n alice -A tcp/80 -R -w /usr/bin/wget -D 5.112.84.211 -U usernamealice -N 192.168.100.109:3306&#xA;Bob&#xA;Bob può raggiungere il db o il server windows in remote desktop, non il webserver.&#xA;Ad es.&#xA;mysql&#xA;fwknop -n bob -A tcp/3306 -R -w /usr/bin/wget -D 5.112.84.211 -U usernamebob -N 192.168.100.109&#xA;Carol&#xA;A Carol invece è consentito solo l&#39;accesso al db mysql  e solo da due subnet specifiche.&#xA;&#xA;Ad es.&#xA;mysql&#xA;fwknop -n carol -A tcp/3306 -a 154.23.162.99 -D 5.112.84.211 -U username_carol -N 192.168.100.109&#xA;Né Bob, né Carol possono ghostare servizi.&#xA;&#xA;small Riferimenti:&#xA;&#xA;https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html&#xA;/small&#xA;&#xA;#fwknop #spa #crittografia&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/634f2a4e4-291f24/QzgT0OY2gSKr/DlbL3aMNOGKs34WZtaTsigWdoF2EZ2OVjXRZv0Wo.jpg" alt="fwknop"></p>

<h2 id="cos-è-fwknop">Cos&#39;è fwknop</h2>

<p><strong>fwknop</strong> è un software di port knocking che usa uno schema di autenticazione chiamato “Single Packet Authorization” ipotizzato e formalizzato dallo stesso autore per risolvere le debolezze più comuni del classico port-knocking.
</p>
<ol><li><a href="#cos-e-fwknop" rel="nofollow">Cos&#39;è fwknop</a></li>
<li><a href="#installazione-client-e-server" rel="nofollow">Installazione client e server</a></li>
<li><a href="#configurazione-client" rel="nofollow">Configurazione client</a>
<ol><li><a href="#generazione-della-sola-chiave" rel="nofollow">Generazione della sola chiave</a></li>
<li><a href="#generazione-chiave-configurazione-complessa" rel="nofollow">Generazione chiave + configurazione complessa</a></li></ol></li>
<li><a href="#configurazione-server" rel="nofollow">Configurazione server</a></li>
<li><a href="#scenari" rel="nofollow">Scenari</a>
<ol><li><a href="#1-protezione-di-un-servizio-con-spa" rel="nofollow">Protezione di un servizio con SPA</a>
<ol><li><a href="#configurazione-lato-server" rel="nofollow">Configurazione lato server</a></li>
<li><a href="#configurazione-lato-client" rel="nofollow">Configurazione lato client</a></li></ol></li>
<li><a href="#2-ghost-locale-sullo-spaserver" rel="nofollow">Ghost locale sullo spaserver</a>
<ol><li><a href="#configurazione-lato-server-1" rel="nofollow">Configurazione lato server</a></li>
<li><a href="#invocazione-client" rel="nofollow">Invocazione client</a></li></ol></li>
<li><a href="#3-spa-attraverso-gateway-nat" rel="nofollow">SPA attraverso gateway NAT</a>
<ol><li><a href="#configurazione-lato-server-2" rel="nofollow">Configurazione lato server</a></li>
<li><a href="#invocazione-client-1" rel="nofollow">Invocazione client</a></li></ol></li>
<li><a href="#4-spa-ghost-service" rel="nofollow">SPA Ghost Service</a>
<ol><li><a href="#invocazione-client-2" rel="nofollow">Invocazione client</a></li></ol></li></ol></li>
<li><a href="#e-se-volessi-usare-la-crittografia-asimmetrica" rel="nofollow">E se volessi usare la crittografia asimmetrica?</a></li>
<li><a href="#osservazioni-su-access-conf" rel="nofollow">Osservazioni su access.conf</a>
<ol><li><a href="#configurazione-stanze-con-spa-server-come-bastion-host" rel="nofollow">Configurazione stanze con spa server come bastion host</a></li>
<li><a href="#alice" rel="nofollow">Alice</a></li>
<li><a href="#bob" rel="nofollow">Bob</a></li>
<li><a href="#carol" rel="nofollow">Carol</a></li></ol></li></ol>

<p><strong>fwknop</strong>, come il port knocking, unisce la comunicazione passiva di informazioni di autenticazione al filtraggio di tutti i pacchetti che non rispettano le sequenze di knock.</p>

<p>Il classico approccio di port-knocking sfrutta le intestazioni dei pacchetti (2 byte) e non il loro payload, per cui è necessario mandare un certo numero di pacchetti per mappare una porta senza generare falsi positivi. Questo però comporta inevitabilmente almeno due problemi:</p>
<ul><li>suscettibilità ad attacchi di spoofing</li>
<li>se le sequenze di knocking sono eccessivamente articolate (magari per inviare più informazioni), data l&#39;imprevedibilità della rete e l&#39;assenza di costrutti che garantiscano lo stesso ordine d&#39;arrivo dei pacchetti, c&#39;è la possibilità che il server non riesca a ricostruire la sequenza corretta.</li></ul>

<p>Il client <code>fwknop</code> (<strong>SPA Client</strong>) invia al server (<strong>SPA Server</strong>) un singolo pacchetto di dimensioni relativamente maggiori (possibile sfruttando il payload) per comunicare informazioni di accesso e interi comandi destinati al filtraggio dei pacchetti.</p>

<p>Il tutto viene protetto da una cifratura simmetrica con autenticazione (aes256-cbc + hmac-sha256, che sarà quella usata nel prosieguo perché più semplice da gestire) o asimmetrica che, al costo di una maggiore complessità di gestione, aggiunge la caratteristica di non ripudio alle caratteristiche di confidenzialità, integrità e autenticazione possedute anche dal primo schema di cifratura.</p>

<h2 id="installazione-client-e-server">Installazione client e server</h2>

<p><code>fwknop</code> client e server sono pacchettizzati per ogni distro linux (su Mac OS è possibile ricorrere a brew).
<strong>Sistemi rpm-based</strong></p>

<pre><code class="language-bash"># Installa il client (fwknop) e il server (fwknopd)
dfn install fwknop
</code></pre>

<p><strong>Sistemi debian-based</strong></p>

<pre><code class="language-bash"># Installa il client (fwknop)
apt install fwknop-client

# Installa il server (fwknopd)
apt install fwknop-server
</code></pre>

<h2 id="configurazione-client">Configurazione client</h2>

<p>La configurazione lato client viene conservata nel file <strong>.fwknoprc</strong> che può essere editato a a mano oppure attraverso il client <code>fwknop</code> salvando nel file <strong>.fwknoprc</strong> quelle che vengono definite “<strong>stanze</strong>”.</p>

<p>Nella configurazione è molto importante la generazione della chiave. Se la chiave è simmetrica, la si può generare con <code>fwknop</code>.</p>

<p>Di seguito, due esempi di creazione di stanze con <code>fwknop</code>, una minimale (che useremo nel resto del documento) e una più complessa.</p>

<h3 id="generazione-della-sola-chiave">Generazione della sola chiave</h3>

<p>Genero la chiave usando il default: aes256-cbc + hmac-sha256.</p>

<pre><code class="language-bash">fwknop -n test -k --use-hmac --save-rc-stanza
</code></pre>

<p>E in <strong>.fwknoprc</strong> troverò una nuova sezione <code>[test]</code></p>

<pre><code>[test]
KEY_BASE64                  dRYAH2O9FCUpNz1aMmlke9/AkGVdcLrnWxDy7jZC1wg=
HMAC_KEY_BASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==
USE_HMAC                    Y
</code></pre>

<h3 id="generazione-chiave-configurazione-complessa">Generazione chiave + configurazione complessa</h3>

<pre><code class="language-bash">fwknop -n test -k -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306 --save-rc-stanza
</code></pre>

<p>che ha  il corrispondente <strong>.fwknoprc</strong>:</p>

<pre><code>[test]
ACCESS                      tcp/80
SPA_SERVER                  107.23.186.49
KEY_BASE64                  0d/VcRXnf2si7hvfDsPN3YIG4Q7aPLU9Ndd5Pe+eMIQ=
HMAC_KEY_BASE64             EEXu0VCPQKPGp8FC8tYS6I/p56nWlot93BV3CPVf3De9FkM04z1SBWTUEJejHpq45+at7VQirgTYvSxeLoZkKQ==
NAT_ACCESS                  10.0.0.132:3306
RESOLVE_IP_HTTPS            Y
WGET_CMD                    /usr/bin/wget
</code></pre>

<p>La spiegazione di questa configurazione specifica la troveremo più avanti nel par. <a href="#4-spa-ghost-service" rel="nofollow">4. SPA Ghost Service</a>. È solo per far vedere che il file di configurazione <code>.fwknoprc</code> può essere rimpiazzato in toto dall&#39;invocazione via cli del client. Chiave compresa, se è il caso.</p>

<p>Affinché la “stanza” venga creata, deve necessariamente essere presente <strong>almeno uno</strong> fra valori dei flag <code>-D</code> e <code>-n</code>. Quest&#39;ultimo costituirà anche il nome alla sezione corrispondente, altrimenti sarà il valore di <code>-D</code> .</p>

<p>Per usare il cient con le preimpostazioni di <strong>.fwinoprc</strong>, basterà indicare il nome della sezione:</p>

<pre><code class="language-bash">fwknop -n test
</code></pre>

<p>Ne consegue che i nomi di sezione <strong>devono essere univoci.</strong></p>

<p>Da ricordare che quando si usa il client  quello che è importante specificare nel file <strong>.fwknoprc</strong> o nei parametri è:</p>
<ul><li><strong>ALLOW_IP (<code>-a</code>)</strong>: che indica l&#39;ip da cui sto facendo la richiesta e che deve rientrare nel <strong>SOURCE</strong> specificato nel server. Se l&#39;ip non è noto magari perché lo spaclient viene nattato, si può ricorrere alla risoluzione dell&#39;ip che viene instradato esternamente (chiamando un servizio esterno):
<ul><li><strong>RESOLVE_IP_HTTPS (<code>-R</code>)</strong>: booleano [Y|N] per abilitare lo spaclient a richiedere la risoluzione del proprio ip;</li>
<li><strong>WGET_CMD (<code>-w</code>)</strong>: path del comando <code>wget</code> che chiamerà lo script di risoluzione</li></ul></li>
<li><strong>ACCESS (<code>-A</code>)</strong>: benché non sia obbligatorio per il server, il client deve necessariamente specificare a quali porte/protocolli intende accedere. Se specificati anche nel server, devono appartenere alla sua lista</li>
<li><strong>SPA_SERVER (<code>-D</code>)</strong>: indica l&#39;ip o l&#39;url dello spaserver</li>
<li><strong>KEY</strong>: la chiave simmetrica per AES-CBC (default: <strong>aes256</strong>);</li>
<li><strong>HMAC_KEY</strong>: la chiave per HMAC (default: <strong>sha256</strong>)</li></ul>

<h2 id="configurazione-server">Configurazione server</h2>

<p>Il server si compone di due file:</p>
<ul><li><strong>fwknopd.conf</strong>: configura il servizio.
È il punto in cui si imposta la porta su cui il servizio sarò in ascolto per ricevere il pacchetto, l&#39;interfaccia, le configurazioni, anche complesse, dei firewall da manipolare in seguito al port-knocking (iptables, firewalld, ipf);</li>
<li><strong>access.conf</strong>: regola gli accessi degli utenti.
È il punto in cui si indicano quegli elementi  necessari ad autenticare ed autorizzare gli utenti, elementi che dovranno coincidere con ciò che contiene il pacchetto.
È possibile creare una cartella, da indicare in <strong>fwknopd.conf</strong>, contenente singole configurazioni di accesso, per utente o per policy, piuttosto che creare un unico, lungo elenco in access.conf.</li></ul>

<p>Anche <strong>access.conf</strong> è un elenco di “<strong>stanze</strong>”, i punti d&#39;accesso per i client contenenti come minimo la rete abilitata all&#39;accesso e la chiave con cui si presenta l&#39;utente, come visto in <a href="#generazione-della-sola-chiave" rel="nofollow">Configurazione client</a>:</p>
<ul><li><strong>SOURCE</strong>: gli ip o le subnet del client da abilitare all&#39;accesso</li>
<li><strong>KEY</strong>: la chiave simmetrica per AES-CBC (default: <strong>aes256</strong>)</li>
<li><strong>HMAC_KEY</strong>: la chiave per HMAC (default: <strong>sha256</strong>)</li></ul>

<p>Altri parametri utili a rafforzare ulteriormente il legame con le richieste client, ma non obbligatori per l&#39;avvio del servizio, sono:</p>
<ul><li><strong>OPEN_PORTS</strong>: specifica quali porte e quali protocolli abilitare</li>
<li><strong>REQUIRE_USERNAME</strong>: specifica un nome utente col quale il client si deve presentare</li>
<li><strong>REQUIRE_SOURCE_ADDRESS</strong>: impone che il client specifichi l&#39;ip da cui sta facendo la richiesta in modo da mitigare la possibilità di attacchi MITM</li></ul>

<p>Quando queste opzioni sono presenti sul server, dovranno essere obbligatoriamente specificate anche nel client.
Dopo aver visto le configurazioni di client e server, vedremo <code>fwknop</code> in azione in alcuni casi “reali”.</p>

<h2 id="scenari">Scenari</h2>

<p>Grazie alla sua capacità sia di manipolare, anche in maniera piuttosto articolata, i firewall che concedono l&#39;accesso alle risorse che ad eseguire interi comandi che fwknop mostra tutta la sua versatilità.</p>

<p>In particolare è col <strong>NAT</strong> che riesce ad andare oltre la sua natura di port knocking dove, grazie ad una combinazione di <strong>DNAT</strong> e <strong>SNAT</strong>, riesce a:</p>
<ul><li>girare richieste su server, che normalmente non sarebbero raggiungibili, posti nel backend insieme allo stesso spaserver o dietro di esso</li>
<li>presentare un servizio su una porta diversa rispetto a quella su cui è in ascolto</li></ul>

<p>diventando a tutti gli effetti un bastion host per l&#39;esposizione autenticata e sicura di servizi critici.</p>

<p>Riassumendo, fwknop può:</p>
<ul><li>essere messo direttamente sul server a protezione di uno o più servizi (caso classico);</li>
<li>può nattare un servizio sullo stesso spaverser con un inoltro delle porte locali e, contestualmente, ghostare un servizio con un altro</li>
<li>può nattare un servizio posto nel backend;</li>
<li>come prima, traslare porte e/o “ghostare” servizi</li></ul>

<p>Gli scenari che andrò a mostrare, copriranno i casi più comuni:</p>
<ol><li>Protezione di un servizio con SPA</li>
<li>Ghost locale sullo spaserver</li>
<li>SPA attraverso Gateway NAT</li>
<li>SPA Ghost Service</li></ol>

<p>Lato client, <code>fwknop</code> <u>si baserà <strong>sempre</strong> sulla configurazione minimale vista prima nel paragrafo “<a href="#generazione-della-sola-chiave" rel="nofollow">Configurazione client</a>“</u>. Il resto delle configurazioni verrà passato via cli.</p>

<h3 id="1-protezione-di-un-servizio-con-spa">1. Protezione di un servizio con SPA</h3>

<p>La cosa più semplice da fare è mettere lo spaserver a protezione diretta del servizio insieme ad un firewall che implementa una policy default-drop.
Ipotizziamo ad es. di proteggere l&#39;accesso in ssh sul nodo centrale (<strong>192.168.100.10</strong>) di una rete a stella.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/634f2a4e4-291f24/xZom9yeeZQtn/kPX18uH9bkazg34i95YNL56tXwAVmm2Lu64Nh4Jg.png" alt="fwknop spa server"></p>

<h4 id="configurazione-lato-server">Configurazione lato server</h4>
<ul><li><p>fwknopd.conf:</p>

<pre><code>PCAP_INTF                   eth1;
PCAP_FILTER                 udp port 62201;
</code></pre></li>

<li><p>access.conf:</p>

<pre><code>%include_folder /etc/fwknop/access.conf.d
</code></pre></li>

<li><p>test.conf:</p>

<pre><code>SOURCE                      192.168.100.0/24
REQUIRE_SOURCE              Y
KEY_BASE64                  dRYAH2O9FCUpNz1aMmlke9/AkGVdcLrnWxDy7jZC1wg=
HMAC_KEY_BASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==
</code></pre></li></ul>

<h4 id="configurazione-lato-client">Configurazione lato client</h4>
<ul><li><p>.fwknoprc:</p>

<pre><code>[test]
KEY_BASE64                  dRYAH2O9FCUpNz1aMmlke9/AkGVdcLrnWxDy7jZC1wg=
HMAC_KEY_BASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==
USE_HMAC                    Y
</code></pre></li>

<li><p>fwknop:</p>

<pre><code class="language-bash">fwknop -n test -a 192.168.100.15 -A tcp/22 -D 192.168.100.10
ssh 192.168.100.10
</code></pre></li></ul>

<p>Supponiamo adesso di voler proteggere l&#39;accesso ssh di una macchina dove però il client , caso molto frequente, sia in una rete privata e nattato con un ip pubblico (rete domestica o rete mobile per es.).</p>

<p>Non possiamo sapere con certezza quale sarà l&#39;ip del client per cui, lato server, dovrò essere disposto ad accettare qualunque sorgente e lato client lascerò che l&#39;ip venga risolto dinamicamente.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/634f2a4e4-291f24/J9X4nmlAhwCf/lAgMoITv4HDj5JsIWq2K3LgJrMz7vzz95RZjG6Vd.png" alt="fwknop con client nat"></p>

<pre><code class="language-bash">fwknop -n test -R -w /usr/bin/wget -A tcp/22 -D 107.23.186.49
ssh 107.23.186.49
</code></pre>

<p>L&#39;opzione:</p>
<ul><li><strong>-R</strong> permette di risolvere il proprio ip pubblico usando wget ( di cui va dato il path) che richiamerà uno script posto di default in <a href="https://www.cipherdyne.org/cgi-bin/myip" rel="nofollow">https://www.cipherdyne.org/cgi-bin/myip</a>, altrimenti se ne può specificare un altro analogo con <code>--resolve-url &lt;url&gt;</code>. Questo perché l&#39;ip reale del client viene nattato con l&#39;ip pubblico <strong>154.23.162.98</strong>, quindi il pacchetto inviato allo spaserver deve contenere questo IP come richiedente, non quello privato (che altrimenti non riceverebbe mai risposta)</li>
<li><strong>-D</strong> serve sempre per specificare l&#39;ip, stavolta pubblico, dello spaserver  (<strong>107.23.186.49</strong>)</li></ul>

<p><strong>N.B.</strong>  Non sapendo quale sarà l&#39;ip richiedente, la clausola  <strong>SOURCE</strong> nel file <strong>test.conf</strong> non potrà contenere un ip o una subnet, quanto piuttosto:</p>

<pre><code>...
SOURCE                      ANY
...
</code></pre>

<h3 id="2-ghost-locale-sullo-spaserver">2.  Ghost locale sullo spaserver</h3>

<p>Assumiamo che la topologia di rete sia semplice come quella del caso precedente ma ipotizziamo che il client che si autentichi con SPA, <strong>acceda ad un servizio protetto la cui porta sia associata contemporaneamente ad un altro servizio esposto pubblicamente</strong>.</p>

<p>In questo modo qualunque un altro client (anche attori malevoli) che volesse connettersi a quella porta, continuerebbe a vedere solo il servizio pubblico e non quello protetto.</p>

<p>Questa magia viene resa possibile grazie ad un <strong>DNAT</strong> locale che mappa temporaneamente, e solo per quell&#39;ip, la porta pubblica con quella del servizio da proteggere.</p>

<p>Nel nostro esempio vogliamo accedere in ssh alla macchina ma sulla porta <strong>80</strong>, corrispondente ad un servizio web esposto pubblicamente.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/634f2a4e4-291f24/x92Omv0hNdeE/H58KNFZBTEIIFk7NfKTXoJFgXXVlWn5yU4pooHYp.png" alt="fwknop con server local nat"></p>

<h4 id="configurazione-lato-server-1">Configurazione lato server</h4>
<ul><li><p>fwknopd.conf:</p>

<pre><code>PCAP_INTF                   enp0s8;
ENABLE_IPT_FORWARDING       Y;
ENABLE_IPT_LOCAL_NAT        Y;
</code></pre></li>

<li><p>access.conf:
Rimane invariato.</p></li></ul>

<h4 id="invocazione-client">Invocazione client</h4>
<ul><li>fwknop:</li></ul>

<pre><code class="language-bash">fwknop -n test -R -w /usr/bin/wget -A tcp/22 -D 107.23.186.49 --nat-local --nat-port 80
ssh 107.23.186.49 -p80
</code></pre>

<h3 id="3-spa-attraverso-gateway-nat">3. SPA attraverso gateway NAT</h3>

<p>In questo caso lo spa server verrà usato come gateway per accedere a servizi posti sulla rete interna. ad es. un db mybsql su una macchina (<strong>10.0.0.132</strong>) posta dietro lo spa server.</p>

<p>Per ottenere tutto questo, bisogna abilitare il port forwarding e il <strong>SNAT</strong> nel file <strong>fwknopd.conf</strong> in modo che vengano create le regole <strong>DNAT</strong> e <strong>MASQUERADE</strong> su iptables affinché le richieste vengano inoltrate rispettivamente verso la macchina  che eroga il servizio (mysql) e che i pacchetti di ritorno viaggino correttamente verso lo spa server e quindi verso il client. Il file <strong>access.conf</strong> rimane invariato</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/634f2a4e4-291f24/16QCyHYx5EWo/XR42wuBNPydnyGL25upmyGE7P1qIk4TWqIznv87p.png" alt="fwknop con gateway nat"></p>

<h4 id="configurazione-lato-server-2">Configurazione lato server</h4>
<ul><li>fwknopd.conf:</li></ul>

<pre><code>PCAP_INTF                   enp0s8;
ENABLE_IPT_FORWARDING       Y;
ENABLE_IPT_SNAT             Y;
</code></pre>

<h4 id="invocazione-client-1">Invocazione client</h4>
<ul><li>fwknop:</li></ul>

<pre><code class="language-bash">fwknop -n test -R -w /usr/bin/wget -A tcp/3306 -D 107.23.186.49 -N 10.0.0.132
mysql -h 107.23.186.49 -u &lt;user&gt; -p
</code></pre>

<h3 id="4-spa-ghost-service">4. SPA Ghost Service</h3>

<p>Adesso vogliamo che l&#39;accesso a mysql venga “nascosto” da un servizio legittimo esposto pubblicamente (un servizio http sulla porta 80).</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/634f2a4e4-291f24/NaMnC9wxDK2z/ydU1mmfAGQcxHn0Y9wFVPjDqLxbTZIoUhWOHKFpx.png" alt="fwknop con ghost service"></p>

<p>La configurazione lato server (<strong>fwknopd.conf</strong>, <strong>access.conf</strong>) rimane invariata rispetto a prima.</p>

<h4 id="invocazione-client-2">Invocazione client</h4>
<ul><li>fwknop:</li></ul>

<pre><code class="language-bash">fwknop -n test -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306
mysql -h 107.23.186.49:80 -u &lt;user&gt; -p 
</code></pre>

<h2 id="e-se-volessi-usare-la-crittografia-asimmetrica">E se volessi usare la crittografia asimmetrica?</h2>

<p>La crittografia asimmetrica usata con hmac costituisce un ulteriore enhancement di sicurezza.</p>

<p>Mentre con la crittografia simmetrica+hmac si ha una sorta di implicito mutuo riconoscimento, con la crittografia asimmetrica è sufficiente che il client sia riconosciuto dal server.</p>

<p>Affinché ciò avvenga, il client inva il pacchetto spa firmato con la sua chiave privata e lo cifra con la chiave pubblica dello spaserver.
Lo spaserver riceve il pacchetto, verifica la firma con la chiave pubblica del client, lo decifra con la sua chiave privata, proseguendo poi col resto del processo di autorizzazione e accesso.</p>

<p>È consigliata la creazione di chiavi apposite per fwknop, non quelle personali. Per il client creeremo una chiave di sola firma e per il server una chiave completa. Le corrispondenti chiavi private possono anche essere lasciate prive di password. Se non lo fossero, dovranno essere inserite nel file di configurazione in mancanza delle quali, soprattutto lato server, finirebbero per richiedere a runtime una poco gestibile interazione con l&#39;utente.</p>

<p>The last but not the least, bisogna tenere presente che, come riportato dalla documentazione (<a href="https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html#fwknop-gpg" rel="nofollow">https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html#fwknop-gpg</a>) la scelta delle chiavi è un&#39;operazione critica.</p>

<p>La cifratura asimmetrica, a differenza di quella simmetrica, tende a produrre dei payload decisamente più cicciotti.
Quindi, per non correre il rischio di avere un payload che superi il default dell&#39;MTU ethernet (1500 byte), bisogna “vincolare” la scelta della chiave del server (di cifratura) a quella del client (di firma).</p>

<p>Le chiavi a curva ellittica sarebbero una buona soluzione. Purtroppo funzionano solo per la firma, non per la cifratura. Quindi vanno bene per il client e <a href="https://github.com/mrash/fwknop/issues/323#issuecomment-770269364" rel="nofollow">non per il server</a>.</p>

<p>Se client e server usassero chiavi rsa, sarebbe meglio per il server usare chiavi non superiori a 3072 bit (caso limite), consigliati 2048 bit. In questo modo un&#39;eventuale chiave client di 4096 bit sarebbe tollerata. Altrimenti si rischierebbe <a href="https://github.com/mrash/fwknop/issues/211" rel="nofollow">un fault</a>: <code>fwknop: fko_spa_data_final: Error 59 - Args contain invalid data: FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_RESULT_MSGLEN_VALIDFAIL</code></p>

<p>Nell&#39;esempio che segue, prenderemo in esame <a href="#4-spa-ghost-service" rel="nofollow">lo scenario 4</a>, ma con autenticazione GPG, con una chiave ECC per il client e una chiave rsa 3072 bit per il server (ma sarebbe tollerata anche una chiave a 4096 bit).</p>

<h3 id="creazioni-delle-chiavi-su-server-e-client">Creazioni delle chiavi su server e client</h3>

<p><strong>spa client</strong></p>

<pre><code class="language-bash"># Creazione chiave di sola firma
gpg --batch --passphrase &#39;&#39; --quick-gen-key &#34;fwknop client (chiave del client fwknop) &lt;fwknop@spaclient&gt;&#34; ed25519 cert,sign never`

# esporta chiave pubblica e invio a spaserver
gpg -o fwknop@spaclient.gpg --export fwknop@spaclient
scp fwknop@spaclient.gpg 107.23.186.49:
</code></pre>

<p><strong>spa server</strong></p>

<pre><code class="language-bash"># Creazione chiave di firma e cifratura. Quella di cifratura è una rsa 3072 bit
gpg --batch --passphrase &#39;&#39; --quick-gen-key &#34;fwknopd server (chiave del server fwknopd) &lt;fwknopd@spaserver&gt;&#34; ed25519 cert,sign never
gpg --batch --passphrase &#39;&#39; --quick-add-key &#39;2BCD6BEF564A54362F8242017C17EC045408C7DB&#39; rsa3072 encr never

# esporta chiave pubblica e invio al client
gpg -o fwknopd@spaserver.gpg --export fwknopd@spaserver
scp fwknopd@spaserver.gpg 107.23.186.160:
</code></pre>

<h3 id="importazioni-e-firma-delle-chiavi">Importazioni e firma delle chiavi</h3>

<pre><code class="language-bash"># importazione e firma della chiave
gpg --import fwknopd@spaserver.gpg
gpg --sign-key fwknopd@spaserver
</code></pre>

<pre><code class="language-bash"># importazione e firma della chiave
gpg --import fwknop@spaclient.gpg
gpg --sign-key fwknop@spaclient
</code></pre>

<h3 id="configurazione-access-conf-d-test-conf-e-fwknoprc">Configurazione <code>access.conf.d/test.conf e .fwknoprc</code></h3>

<p>Analogamente a quanto fatto con la cifratura simmetrica:</p>
<ul><li><p>access.conf.d/test_gpg.conf</p>

<pre><code>SOURCE                      ANY
REQUIRE_SOURCE              Y
HMAC_KEY_BASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==
GPG_ALLOW_NO_PW             Y  
GPG_REMOTE_ID               1B0D9549
GPG_DECRYPT_ID              5408C7DB 
</code></pre></li>

<li><p>.fwknoprc</p>

<pre><code>[test_gpg]
USE_GPG                     Y
GPG_RECIPIENT               5408C7DB
GPG_SIGNER                  1B0D9549
HMAC_KEY_BASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==
USE_HMAC                    Y
</code></pre></li></ul>

<h3 id="test-client">Test client</h3>

<pre><code class="language-bash">fwknop --verbose -n test_gpg -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306
mysql -h 107.23.186.49:80 -u &lt;user&gt; -p
</code></pre>

<hr>

<p><strong>N.B.</strong>: Gli scenari 2, 3 e 4 sono le riproposizioni di ciò che viene presentato da Michael Rash durante lo <strong>ShmooCon del 2013</strong> in <a href="https://www.youtube.com/watch?v=GCGiI6DJuIc" rel="nofollow">https://www.youtube.com/watch?v=GCGiI6DJuIc</a> (scenario 2)  e nel suo blog (<a href="https://www.cipherdyne.org/blog/categories/port-knocking-and-spa.html" rel="nofollow">https://www.cipherdyne.org/blog/categories/port-knocking-and-spa.html</a>) in  <a href="https://www.youtube.com/watch?v=tz-xK1BarKk" rel="nofollow">https://www.youtube.com/watch?v=tz-xK1BarKk</a>  (scenario 3 e 4)</p>

<p><strong>Ghost Service</strong> e <strong>SPA across gateway NAT</strong> non sono chiarissimi negli esempi forniti, mancano alcuni dettagli per me, che non sono un esperto di reti, fondamentali come la giusta evidenza e l&#39;importanza sull&#39;uso corretto del local nat nel primo caso e di SNAT negli altri due.</p>

<p>Tutti gli esempi, in particolare 3 e 4, sono stati testati con un&#39;infrastruttura speculare a quella usata nel 2° video, ottenuta non già attraverso AWS ma con il più modesto VirtualBox che ha comunque svolto egregiamente il suo compito.</p>

<p>Per chi volesse effettuare delle prove sul campo, spero, in futuro, di mettere a disposizione questo piccolo laboratorio attraverso Vagrant e di dare indicazioni sulle configurazioni degli apparati che si occupano di routing e nat.</p>

<hr>

<h2 id="osservazioni-su-access-conf">Osservazioni su <strong>access.conf</strong></h2>

<p><strong>access.conf</strong> permette di stabilire chi accede e su quali risorse.</p>

<p>Le porte specificate nella clausola <strong>ACCESS</strong> permetteranno al clent di accedere con la stessa chiave:</p>
<ol><li>a <strong>tutti i servizi</strong> relativi, se lo spaserver è installato sulla stessa macchina che li eroga;</li>
<li>a <strong>tutti i server</strong> relativi (eroganti i servizi indicati in <strong>ACCESS</strong>) nattati dallo spaserver;</li>
<li>ad <strong>uno solo</strong> dei servizi, e solo fra quelli “nattabili”, se nell&#39;access.conf uso le clausole <strong>FORCE_NAT/SNAT</strong>, per quanto siano larghe le maglie della clausola <strong>ACCESS</strong>. Inoltre posso usare <strong>ACCESS</strong> per concedere o meno la possibilità di ghostare un servizio</li></ol>

<p>Vediamo con un po&#39; di esempi cosa possiamo fare</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/634f2a4e4-291f24/aE1N98kHGiRq/0YWH7vt1MGJmSHVTYMD7nNr8L7yVgH6Ed10atavg.png" alt="fwknop bastion host"></p>

<p>Questo scenario riprende ed estende quello visto finora, dove si evidenzia il natting sia dei client che dei server, entrambi nelle loro lan private.</p>

<p>A differenza degli scenari precedenti, lo spaserver non è direttamente esposto ma è anch&#39;esso nel backend. Gli altri server espongono un server web sulla porta <strong>8080</strong>, un remote-desktop sulla <strong>3389</strong> e un db mysql sulla <strong>3306</strong>.</p>

<p>Per mostrare quanto fwknop possa essere flessibile, supponiamo di avere 3 utenti, <strong>Alice</strong>, <strong>Bob</strong> e <strong>Carol</strong>, ognuno con privilegi differenti.
fwknop sarà configurato come bastion host.</p>

<p>Supponiamo sempre che lo spaserver esponga pubblicamente un sito web sulla porta 80 (utile per un eventuale ghosting dei servizi) .</p>

<h4 id="configurazione-stanze-con-spa-server-come-bastion-host">Configurazione stanze con spa server come bastion host</h4>

<p>La configurazione delle stanze richiederà al client anche di specificare l&#39;utente.</p>
<ul><li><p>access.conf.d/alice.conf</p>

<pre><code># alice
SOURCE                      ANY
REQUIRE_SOURCE              Y
SPOOF_USER                  &lt;username_alice&gt;
HMAC_KEY_BASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==
GPG_ALLOW_NO_PW             Y  
GPG_REMOTE_ID               1B0D9549
GPG_DECRYPT_ID              5408C7DB 
</code></pre></li>

<li><p>access.conf.d/bob.conf</p>

<pre><code># bob
SOURCE                      ANY
OPEN_PORTS                  tcp/3306, tcp/3389
SPOOF_USER                  &lt;username_bob&gt;
REQUIRE_SOURCE              Y
KEY_BASE64                  /bUdrMWFbc754iitBPAm2iwpzJ9CeetVxKXJOY0b9yI=
HMAC_KEY_BASE64             K22gfP5eq8Hveg58NeCWbXJEL/S/R74wGhxG3S6Gv+hl/bbqOZhExsRuLRrIvyZmW7iseEN8E48wHRQsUMozgA==
</code></pre></li>

<li><p>access.conf.d/carol.conf</p>

<pre><code># carol
SOURCE                      154.23.162.32/27, 154.23.162.96/27
OPEN_PORTS                  tcp/3306
SPOOF_USER                  &lt;username_carol&gt;
REQUIRE_SOURCE              Y
KEY_BASE64                  GK1CE1BE+ItAfZCMH9NPUkAd+rQv2mTm5df1wjN1w6w=
HMAC_KEY_BASE64             ewbyRRz2B7mqQnXRa7Mm67Qa4xIzr1/oyKAhHSQ7+rwtNcEZrZbXeHb97drG8ebZ06F7OOLjp1i9Fy+DtN3F7Q==
</code></pre></li></ul>

<h4 id="alice">Alice</h4>

<p>Con le stanze configurate in questo modo, alice, che ha una chiave gpg, può usare la stessa chiave da qualunque ip, per raggiungere uno qualunque fra i 3 server in backend.
Es.</p>

<pre><code class="language-bash">#webserver
fwknop -n alice -A tcp/8080 -R -w /usr/bin/wget -D 5.112.84.211 -U &lt;username_alice&gt; -N 192.168.100.112
</code></pre>

<p>o</p>

<pre><code class="language-bash"># remote-desktop
fwknop -n alice -A tcp/3389 -R -w /usr/bin/wget -D 5.112.84.211 -U &lt;username_alice&gt; -N 192.168.100.25
</code></pre>

<p>o</p>

<pre><code class="language-bash"># mysql
fwknop -n alice -A tcp/3306 -R -w /usr/bin/wget -D 5.112.84.211 -U &lt;username_alice&gt; -N 192.168.100.109
</code></pre>

<p>Alice può anche “ghostare” il servizio, ad es. mysql</p>

<pre><code class="language-bash"># mysql
fwknop -n alice -A tcp/80 -R -w /usr/bin/wget -D 5.112.84.211 -U &lt;username_alice&gt; -N 192.168.100.109:3306
</code></pre>

<h4 id="bob">Bob</h4>

<p>Bob può raggiungere il db o il server windows in remote desktop, non il webserver.
Ad es.</p>

<pre><code class="language-bash"># mysql
fwknop -n bob -A tcp/3306 -R -w /usr/bin/wget -D 5.112.84.211 -U &lt;username_bob&gt; -N 192.168.100.109
</code></pre>

<h4 id="carol">Carol</h4>

<p>A Carol invece è consentito solo l&#39;accesso al db mysql  e solo da due subnet specifiche.</p>

<p>Ad es.</p>

<pre><code class="language-bash"># mysql
fwknop -n carol -A tcp/3306 -a 154.23.162.99 -D 5.112.84.211 -U &lt;username_carol&gt; -N 192.168.100.109
</code></pre>

<p>Né Bob, né Carol possono ghostare servizi.</p>

<p><small> Riferimenti:</p>
<ul><li><a href="https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html" rel="nofollow">https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html</a>
</small></li></ul>

<p><a href="/aytin/tag:fwknop" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">fwknop</span></a> <a href="/aytin/tag:spa" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">spa</span></a> <a href="/aytin/tag:crittografia" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">crittografia</span></a></p>
]]></content:encoded>
      <guid>https://noblogo.org/aytin/fwknop-proteggere-servizi-con-single-packet-authorization-spa</guid>
      <pubDate>Sun, 15 Dec 2024 11:44:33 +0000</pubDate>
    </item>
    <item>
      <title>Gestire la tua chiave GPG</title>
      <link>https://noblogo.org/aytin/gestire-la-tua-chiave-gpg</link>
      <description>&lt;![CDATA[gpg tools&#xA;&#xA;Esistono numerose gui che semplificano la gestione di una chiave gpg.&#xA;&#xA;Questo articolo ha lo scopo di semplificare la creazione di una chiave gpg attraverso la cli di GnuPG, senza entrare nel suo mare magnum di opzioni.&#xA;!--more--&#xA;&#xA;Indice&#xA;&#xA;a href=&#34;#premessa&#34;Premessa/a&#xA;a href=&#34;#gestione-della-chiave&#34;Gestione della chiave/a&#xA;a href=&#34;#come-proteggere-il-nostro-keyring&#34;Come proteggere il nostro keyring/a&#xA;a href=&#34;#cos-e-un-keyserver&#34;Cos&#39;è un keyerver/a&#xA;&#xA;----&#xA;&#xA;a id=premessa&#34;Premessa/a&#xA;Cosa NON è una chiave gpg?&#xA;Una coppia di chiavi, una pubblica e una privata basate sulla crittografia asimmetrica.&#xA;&#xA;Cos&#39;è una chiave gpg?&#xA;Non è solo una coppia di chiavi asimmetriche ma è un certificato.&#xA;Dal punto di vista delle informazioni, una chiave gpg contiene:&#xA;&#xA;informazioni identificative (nome, commento, email, foto, ecc)&#xA;informazioni non identificative (dati tecnici che fanno parte delle chiavi: scadenza, keyserver, algoritmi di hash e cifratura, revoker ecc.)&#xA;&#xA;Una chiave gpg, in definitiva, è costituita da: &#xA;&#xA;una chiave primaria (detta anche secret key o master key)&#xA;da una o più sottochiavi&#xA;da una serie di informazioni personali.&#xA;&#xA;Ognuna di queste &#34;chiavi&#34; è in realtà una coppia di chiavi asimmetriche dotate delle seguenti autorizzazioni: &#xA;&#xA;Certificazione: capacità della chiave di firmare, e quindi validare, le chiavi gpg di altri utenti.&#xA;Firma: capacità di firmare documenti.&#xA;Cifratura: capacità di cifrare documenti.&#xA;Autenticazione: capacità di autenticare l&#39;utente su alcuni protocolli come TLS o SSH.&#xA;&#xA;La certificazione, ossia la capacità di validare altre chiavi oltre la propria, è esclusiva della master key.&#xA;Le altre autorizzazioni possono essere delegate alle sottochiavi.&#xA;&#xA;Certificazioni e firma, garantiscono autenticazione, integrità e non ripudio del mittente.&#xA;La cifratura garantisce confidenzialità.&#xA;Le prime due sono da considerarsi più critiche e normalmente assegnate alla master key.&#xA;&#xA;Una chiave può avere una o più proprietà. Di default, gpg crea una master key con autorizzazioni per firma e certificazione e una sottochiave con autorizzazioni per cifratura.&#xA;a id=&#34;gestione-della-chiave&#34;Gestione della chiave/a&#xA;Per la creazione e la gestione della chiave nei suoi elementi principali, vedremo:&#xA;&#xA;come creare la chiave primaria&#xA;come aggiungere sottochiavi, uid&#xA;come modificare password o scadenza&#xA;come si certifica un&#39;altra chiave con la nostra (firma di chiave)&#xA;come si cancellano localmente uid, sottochiavi e firme&#xA;come si revoca un certificato, una sottochiave, un uid o una certificazione&#xA;come si usa un keyserver per la pubblicazione e la ricerca delle chiavi&#xA;&#xA;Creazione della chiave primaria&#xA;gpg --quick-gen-key uid algo auth expire, dove&#xA;- uid: &#34;uidname (comment) e-mail&#34;&#xA;- algo: uno fra &#39;gpg --with-colons --list-config&#39;&#xA;- auth: cert|encr|sign&#xA;- expire: 0 =  illimitato, ny|nm|nd =  n anni|mesi|giorni&#xA;gpg --quick-gen-key gandalf ed25519 cert 0&#xA;Crea una chiave gpg la cui secret key può solo certificare, l&#39;uid è composto dal solo nome gandalf e ha scadenza illimitata.&#xA;gpg -K&#xA;/home/gandalf/.gnupg/pubring.kbx&#xA;--------------------------------&#xA;sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]&#xA;&#x9;  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B&#xA;uid                   [ultimate] gandalf&#xA;Ecco la chiave appena creata, nella prima riga distinguiamo: &#xA;&#xA;&#34;sec&#34;, sta per secret key&#xA;algoritmo/KeyID&#xA;data di creazione&#xA;capability ([C]=certify). &#xA;&#xA;Nella riga successiva è visibile il fingerprint e nella terza, l&#39;uid (gandalf). Questi elementi, come il KeyID, servono per indirizzare la chiave.&#xA;&#xA;Una sintassi più completa sarebbe:&#xA;gpg --quick-gen-key &#34;nome (commento) e-mail&#34; algo cert|sign|encr scadenza&#xA;Per avere una lista degli algo:&#xA;gpg --with-colons --list-config&#xA;Aggiungere una sottochiave&#xA;Aggiungiamo le chiavi di firma e di cifratura con scadenza 5 anni e 1 anno rispettivamente&#xA;gpg --quick-addgen-key fpr algo auth expire&#xA;gpg --quick-add-key 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B ed25519 sign 5y&#xA;gpg --quick-add-key 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B cv25519 encr 1y&#xA;Come prima, oltre alla secret key, ora sono visibili le sottochiavi (ssb, Secret SubKey) di firma e cifratura con le evidenze per:&#xA;algoritmo, KeyID, creazione, capability ([S] per sign e [E] per encrypt) e scadenza.&#xA;gpg -K&#xA;/home/gandalf/.gnupg/pubring.kbx&#xA;--------------------------------&#xA;sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]&#xA;&#x9;  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B&#xA;uid                   [ultimo] gandalf&#xA;ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [scadenza: 2029-11-04]&#xA;ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [scadenza: 2025-11-05]&#xA;Meccanismi di indirizzamento per una chiave&#xA;Una chiave può essere riferita attraverso l&#39;uid, il key ID o il fingerprint. Il riferimento è importante nelle operazioni di manipolazione della chiave.&#xA;gpg --with-subkey-fingerprint -K&#xA;/home/gandalf/.gnupg/pubring.kbx&#xA;--------------------------------&#xA;sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]&#xA;&#x9;  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B&#xA;uid                   [ultimate] gandalf&#xA;uid                   [ultimate] Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) gandalf@lotr.org&#xA;ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [expires: 2029-11-04]&#xA;&#x9;  87EF9CF3D5A4D78ADA80E364A391F0548FB542DB&#xA;ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [expires: 2025-11-04]&#xA;&#x9;  4DD33D36C54E2247486C9DC7AAEF649D51D832E8&#xA;&#xA;0xE01BDCB6A3C6778B è il key ID della master key&#xA;8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B è il fingerprint della master key&#xA;gandalf è uno degli uid&#xA;&#xA;Aggiungere un uid&#xA;Aggiunge un nuovo uid in termini di nome-commento-email e lo battezza come primario.&#xA;gpg --quick-add-uid primaryuid newuid&#xA;gpg --quick-add-uid gandalf &#34;Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) gandalf@lotr.org&#34;&#xA;&#xA;gpg --quick-set-primary-uid primaryuid newuid&#xA;gpg --quick-set-primary-uid &#34;gandalf&#34; &#34;Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) gandalf@lotr.org&#34;&#xA;Firmare una chiave&#xA;&#xA;Ossia riconoscere una chiave gpg come valida attraverso la certificazione.&#xA;Pubblicare questa chiave sul keyserver, comunica al mondo che riconosciamo quella chiave come valida.&#xA;&#xA;Convalida tutti gli uid della chiave identificata da fpr&#xA;gpg --quick-sign-key fpr&#xA;gpg --quick-sign-key AD59879E1CB5D63E98F05FB9204621DACB1296E0&#xA;Convalida un uid specifico della chiave identificata da fpr&#xA;gpg --quick-sign-key fpr uid&#xA;gpg --quick-sign-key AD59879E1CB5D63E98F05FB9204621DACB1296E0 frodo&#xA;Modificare la password&#xA;Inserisce la password con cui tutte le chiavi private (master key e subkey) relative all&#39;uid indicato, vengono cifrate. Se la password viene lasciata vuota, la chiave non viene cifrata.&#xA;gpg --passwd uid|KeyID|fpr&#xA;gpg --passwd gandalf&#xA;Modificare la scadenza&#xA;Modifico le scadenze delle chiavi come segue:&#xA;&#xA;la master key da illimitata a 10 anni&#xA;la sottochiave di firma da 5 anni a 4 anni&#xA;la sottochiave di cifratura da 1 anno a 2 anni&#xA;&#xA;gpg --quick-set-expire fpr expire&#xA;gpg --quick-set-expire 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B 10y&#xA;gpg --quick-set-expire 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B 4y 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB&#xA;gpg --quick-set-expire 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B 2y 4DD33D36C54E2247486C9DC7AAEF649D51D832E8&#xA;gpg --with-subkey-fingerprint -K&#xA;/home/gandalf/.gnupg/pubring.kbx&#xA;--------------------------------&#xA;sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C] [expires: 2034-11-04]&#xA;&#x9;  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B&#xA;uid                   [ultimate] gandalf&#xA;uid                   [ultimate] Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) gandalf@lotr.org&#xA;ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [expires: 2028-11-04]&#xA;&#x9;  87EF9CF3D5A4D78ADA80E364A391F0548FB542DB&#xA;ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [expires: 2026-11-04]&#xA;&#x9;  4DD33D36C54E2247486C9DC7AAEF649D51D832E8&#xA;Cancellazione di elementi dal keyring&#xA;La cancellazione di elementi come uid, firme o sottochiavi ha effetto solo sul keyring locale.&#xA;Se la chiave è stata pubblicata su un repository, le cancellazioni non avranno alcun effetto.&#xA;Se si vuole inibire uno di questi elementi, si deve ricorrere alla revoca che è esportabile sui keyserver.&#xA;Cancellare una sottochiave&#xA;Cancella la sottochiave di firma&#xA;gpg --delete-secret-and-public-keys KeyID|fpr&#xA;gpg --delete-secret-and-public-keys 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB!&#xA;o, equivalentemente&#xA;gpg --delete-secret-and-public-keys 0xA391F0548FB542DB!&#xA;Cancellare un uid&#xA;Cancella la seconda identità della chiave gandalf (0xA391F0548FB542DB)&#xA;gpg --edit-key [KeyID|fpr|uid]&#xA;gpg --edit-key gandalf&#xA;    uid 2&#xA;    deluid&#xA;    save&#xA;Cancellare una firma&#xA;Cancella tutte le firme del 2° uid che non siano self-signature.&#xA;gpg --edit-key [KeyID|fpr|uid]&#xA;gpg --edit-key gandalf&#xA;    uid 2&#xA;    delsig&#xA;    save&#xA;Operazioni di revoca&#xA;Per quel che riguarda le chiavi gpg (i certificati) di cui si possiede la chiave privata, l&#39;operazione di revoca può avvenire su uno degli elementi della chiave o sull&#39;intero certificato.&#xA;Revocare un uid&#xA;Revoco l&#39;uid (gandalf il grigio),&#xA;gpg --quick-revuid primaryuid uid &#xA;gpg --quick-revuid gandalf &#34;gandalf il grigio&#34;&#xA;Revocare una sottochiave&#xA;gpg --edit-key [KeyID|fpr|uid]&#xA;gpg --edit-key 0xA391F0548FB542DB&#xA;    key 1&#xA;    revkey&#xA;    save&#xA;Revocare una nostra certificazione&#xA;Così come validiamo le chiavi altrui con la nostra firma di certificazione, allo stesso modo possiamo revocarla.&#xA;&#xA;Revoco la mia firma su tutti gli uid di una chiave pubblica&#xA;gpg --quick-revoke-sig KeyID|fpr del firmato KeyID|fpr del firmante &#xA;gpg --quick-revoke-sig 0x204621DACB1296E0 0xE01BDCB6A3C6778B&#xA;Posso anche revocare la mia firma su un uid specifico&#xA;gpg --quick-revoke-sig KeyID|fpr del firmato KeyID|fpr del firmante uidi&#xA;gpg --quick-revoke-sig 0x204621DACB1296E0 0xE01BDCB6A3C6778B frodouid2&#xA;Revocare l&#39;intero certificato&#xA;Va a revocare non solo tutti gli uid e tutte le sottochiavi, ma anche la masterkey.&#xA;gpg --import 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB.rev&#xA;Il certificato di revoca viene generato all&#39;atto della creazione della chiave.&#xA;Se non ci fosse, conviene sempre crearlo così che, se la master key venisse compromessa, saremmo almeno in grado di revocare l&#39;intero certificato.&#xA;gpg -o file --gen-rev fpr&#xA;gpg -o 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB.rev --gen-rev 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB&#xA;Le operazioni di revoca, nel mondo gpg, corrispondono alle maledizioni senza perdono, nel mondo di Harry Potter.&#xA;Non si torna indietro a meno di un backup, e se le revoche vengono pubblicate su un keyserver, diventano irreversibili.&#xA;Operazioni sul keyserver&#xA;Il caricamento delle chiavi su un keyserver costituisce la finalizzazione delle operazioni svolte finora.&#xA;&#xA;Il keyserver pubblica al mondo le nostre chiavi, la configurazione avviene nel file dirmngr.conf aggiungendo una riga (ad es. per keys.openpgp.org):&#xA;vi dirmngr.conf&#xA;&#xA;...&#xA;keyserver hkps://keys.openpgp.org&#xA;...&#xA;e ricaricando la configurazione:&#xA;gpgconf --reload dirmngr&#xA;Cerca&#xA;Cerca nel keyserver le chiavi con uid specificato. In caso di successo, chiede se possono essere aggiunte al keyring.&#xA;gpg --search-keys uid&#xA;gpg --search-keys 0xE01BDCB6A3C6778B 0x204621DACB1296E0&#xA;Per gli utilizzatori di keys.openpgp.org:&#xA;gpg --auto-key-locate keyserver --locate-keys uid&#xA;Invia&#xA;Invia una lista di chiavi al keyserver&#xA;gpg --send-keys KeyIDs|fpr&#xA;gpg --send-keys 0xE01BDCB6A3C6778B 0x204621DACB1296E0&#xA;Per gli utilizzatori di keys.openpgp.org:&#xA;Il classico send non è sufficiente perché non sarebbe possibile validare la mail di conferma. Si consiglia, non volendo usare l&#39;interfaccia web, di usare il seguente comando:&#xA;gpg --export KeyID|fpr|uid | curl -T - https://keys.openpgp.org&#xA;gpg --export 0xE01BDCB6A3C6778B | curl -T - https://keys.openpgp.org&#xA;che restituisce un link diretto alla pagina di verifica.&#xA;Ricevi&#xA;Scarica dal keyserver le chiavi&#xA;gpg --keyserver-options honor-keyserver-url --receive-keys KeyIDs|fpr&#xA;gpg --keyserver-options honor-keyserver-url --receive-keys 0xE01BDCB6A3C6778B 0x204621DACB1296E0&#xA;Scarica dal keyserver la chiave indicata dall&#39;uri&#xA;gpg --fetch-keys uri&#xA;gpg --fetch-keys https://keyserver.ubuntu.com/pks/lookup?search=0xE01BDCB6A3C6778B&amp;fingerprint=on&amp;op=index&#xA;Aggiorna&#xA;Per rinnovare tutte le chiavi pubbliche del keyring.&#xA;gpg --keyserver-options honor-keyserver-url --refresh-keys&#xA;a id=&#34;come-proteggere-il-nostro-keyring&#34;Come proteggere il nostro keyring/a&#xA;Come visto in precedenza, suggerisco di creare la master key per la sola certificazione e le due sottochiavi per firma e cifratura (anche quando la chiave primaria dovesse contenere altre autorizzazioni).&#xA;&#xA;Questo permetterebbe, volendo ma non è necessario, di ruotare più agevolmente le chiavi di firma e cifratura svincolandole dalla certificazione.&#xA;&#xA;Inoltre, così è più semplice rendere le chiavi gpg &#34;partially stripped&#34;, chiavi la cui sola secret key sia mancante della chiave privata, cosicché, se queste venissero smarrite o trafugate, la secret key in nostro possesso ci permetterebbe immediatamente di generare un certificato di revoca per le sottochiavi compromesse, generare delle nuove sottochiavi di firma e cifratura e di distribuire il tutto ad un keyserver.&#xA;&#xA;Chiavi gpg siffatte permetterebbero di svolgere le consuete operazioni di firma e cifratura documentale (quello che potremmo definire &#34;utilizzo giornaliero&#34;) ma impedirebbero qualunque operazione critica sulla propria chiave gpg (impossibilità di aggiungere, revocare sottochiavi o uid, di alterare scadenza o password ecc.) e su quelle altrui (certificare e quindi validare altre chiavi) upoichè è la chiave privata della master key a sigillare self-signed le informazioni della chiave gpg/u.&#xA;&#xA;In generale, posso estrarre la chiave privata da qualunque coppia di chiavi, siano esse sottochiavi o master key, ma non è uno scenario molto comune. Per estensione, eliminandole tutte otterremo un insieme di chiavi pubbliche (quella che otterrei anche con gpg --export uid|KeyID|fpr).&#xA;&#xA;Quello che invece ci interessa è eliminare la chiave privata della sola master key.&#xA;L&#39;eliminazione della chiave privata dalla master key, di per sè, non è un&#39;operazione particolarmente onerosa.&#xA;&#xA;La vera &#34;difficoltà&#34; risiede nel cambio di paradigma per l&#39;utente che l&#39;utilizzo di master key stripped comporta, perché avremo a che fare con un keyring da proteggere accuratamente e dei keyring da &#34;trincea&#34; da usare liberamente sui nostri device.&#xA;Realizzare un keyring per l&#39;uso quotidiano&#xA;Per farlo dobbiamo eliminare le chiavi private di tutte le master key del nostro keyring e per farlo dobbiamo fare un po&#39; di assunzioni.&#xA;&#xA;Come primo passo, bisogna spostare, se non è stato già fatto, il keryring dal pc/laptop/device ad un luogo sicuro (ad es. pendrive cifrata)&#xA;quindi si devono estrarre le chiavi private dalle master key e distribuirle dove possano servire &#xA;in caso di emergenza o se vi è necessità di modificare le chiavi, importare le chiavi gpg dal dispositivo sicuro, effettuare le modifiche, rigenerare e ridistribuire le nuove chiavi stripped&#xA;&#xA;Eliminazione della chiave privata dalla master key&#xA;La cancellazione della chiave privata impedisce alla master key o alla sottochiave  di esercitare pienamente le funzioni indicate dalle proprie autorizzazioni ossia certificazione, firma o decifratura.&#xA;&#xA;Per intervenire sulla singola chiave privata, occorre individuare il suo fingerprint o il suo keyid e usarlo per cancellare postponendo il carattere &#34;!&#34;. &#xA;&#xA;Ad es. sulla master key di gandalf:&#xA;gpg --delete-secret-keys 0x055D271BD85313D0!&#xA;Il carattere &#34;#&#34; (accanto a sec) vuol dire che la chiave privata è stata eliminata&#xA;gpg -K&#xA;/home/gandalf/ramfsgpg/pubring.kbx&#xA;-----------------------------------&#xA;sec#  ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]&#xA;&#x9;  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B&#xA;uid                   [ultimo] gandalf&#xA;ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [scadenza: 2029-11-04]&#xA;ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [scadenza: 2025-11-05]&#xA;Generalizzando, per realizzare il nostro keyring di lavoro si può agire, una tantum, in questo modo:&#xA;&#xA;1\. spostiamo il keyring di lavoro sul dispositivo sicuro&#xA;KEYRINGRAMFS=pathramfs&#xA;KEYRINGVAULT=pathpendrivecifrata&#xA;KEYRINGWORK=pathgpgdaily&#xA;export GNUPGHOME=${KEYRINGWORK}; cd $GNUPGHOME&#xA;&#xA;rsync -avp ${KEYRINGWORK}/ ${KEYRINGVAULT}/&#xA;2\. rendiamo il keyring stripped cancellando le chiavi private di tutte le master key.&#xA;for FPR in $(gpg --with-colons -K|grep sec -A 1|grep fpr|cut -d &#34;:&#34; -f 10); do &#xA;    gpg --batch --yes --delete-secret-keys &#34;${FPR}!&#34;&#xA;done&#xA;In seguito, come detto in precedenza, per lavorare sul keyring occorrerà ripristinarlo dal dispositivo sicuro, ad es. una pendrive cifrata.&#xA;&#xA;Per non lasciare tracce su altri device che non sia la pendrive cifrata, si possono seguire due strade.&#xA;&#xA;usare una distribuzione live (più sicura)&#xA;montare una partizione in ram su ramfs (non usa lo swap) su cui caricare il keyring.&#xA;&#xA;La prima via è certamente preferibile. Non c&#39;è alcun uso dei dispositivi di storage fisici della macchine, solo quelli volatili, ma presuppone che si possa avviare un SO da pendrive.&#xA;La seconda è più accessibile per certi versi ma presuppone che si possiedano i privilegi per montare una partizione su ram.&#xA;&#xA;Mostrerò la seconda via che è più articolata.&#xA;Lavorare con un keyring effimero&#xA;La strategia è quella di avere un keyring effimero montato su ramfs che farà da tramite fra il keyring master (su pendrive cifrata) e il keyring di lavoro.&#xA;&#xA;L&#39;obiettivo finale è quello di rendere strutturale il fatto di riuscire a compiere operazioni sul keyring usando il meno possibile i dispositivi di storage.&#xA;&#xA;0\. Init&#xA;KEYRINGRAMFS=pathramfs&#xA;KEYRINGVAULT=pathpendrivecifrata&#xA;KEYRINGWORK=pathgpgdaily&#xA;1\. Monto la partizione effimera&#xA;mkdir -p ${KEYRINGRAMFS}&#xA;sudo mount -t ramfs -o size=10M ramfs ${KEYRINGRAMFS}&#xA;sudo chown $(logname):$(logname) ${KEYRINGRAMFS}&#xA;2\. Esporto chiavi pubbliche e trust dal keyring di lavoro&#xA;gpg -o ${KEYRINGRAMFS}/keyringpubkeys.gpg --export&#xA;gpg --export-ownertrust   ${KEYRINGRAMFS}/keyringownertrust.txt&#xA;3\. Copio il keyring master sulla partizione effimera, modifico GNUPGHOME in modo che gpg lavori direttamente sulla partizione effimera. Su questo keyring effimero, completo l&#39;allineamento importando le chiavi pubbliche e il trust provenienti dal keyring di lavoro.&#xA;rsync -avp ${KEYRINGVAULT}/ ${KEYRINGRAMFS}/&#xA;export GNUPGHOME=${KEYRINGRAMFS}; cd $GNUPGHOME&#xA;gpg --import keyringpubkeys.gpg&#xA;gpg --import-ownertrust keyringownertrust.txt&#xA;4\. Eseguo le mie manipolazioni sul keyring effimero: uid, key, passwd, firme, revoche ecc.&#xA;...&#xA;[operazioni gpg]&#xA;...&#xA;5\. Copio il keyring master dalla partizione effimera alla pendrive cifrata &#xA;rsync -avp ${KEYRINGRAMFS}/ ${KEYRINGVAULT}/&#xA;6\. Rendo il keyring effimero di nuovo stripped&#xA;for FPR in $(gpg --with-colons -K|grep sec -A 1|grep fpr|cut -d &#34;:&#34; -f 10); do &#xA;    gpg --batch --yes --delete-secret-keys &#34;${FPR}!&#34;&#xA;done&#xA;7\. Ripristino il keyring di lavoro escludendo i certificati di revoca e cancellando la partizione effimera&#xA;rsync -avp --exclude openpgp-revocs.d ${KEYRINGRAMFS}/ ${KEYRINGWORK}/&#xA;export GNUPGHOME=${KEYRINGWORK}/&#xA;sudo umount ${KEYRINGRAMFS}; rmdir ${KEYRINGRAMFS}&#xA;La complessità di questa gestione può essere ridotta rendendo scriptabili i due blocchi (1,2,3) e (5,6,7), ad es. immaginando di avere a disposizione delle funzioni come gpg-vault [open|close|status], avendo la consapevolezza che, se usate male, possono essere delle operazioni distruttive.&#xA;a id=&#34;cos-e-un-keyserver&#34;Cos&#39;è un keyerver/a&#xA;Il keyserver è il luogo in cui pubblichiamo le nostre chiavi per renderle disponibili agli altri utenti.&#xA;&#xA;Inizialmente i keyserver avevano una logica p2p, distribuita e decentralizzata ottenuta con un&#39;implementazione chiamata SKS (Synchronizing Key Server) basata sulla rapida diffusione delle chiavi fra keyserver.&#xA;&#xA;I keyserver inizialmente servivano anche a realizzare il WOT (Web Of Trust) per la convalida delle chiavi.&#xA;&#xA;Col tempo, la mancanza di aggiornamenti del protocollo sks e la suscettibilità ad attacchi di tipo &#34;key poisoning&#34;, che possono rendere indisponibili interi certificati (ad es. riempiendo la chiave con innumerevoli firme contenenti tonnellate di dati tali da far crashare i client) o gli stessi keyserver (pubblicando quantitivi enormi di certificati non validi), amplificata dalle caratteristiche di sincronizzazione dei server, ne hanno decretato la fine.&#xA;&#xA;La realizzazione del WOT, tra l&#39;altro, offriva pubblicamente una tale quantità di chiavi che permetteva, da un lato, di tracciare interi social network basati sulle firme che vi venivano apposte, dall&#39;altro, di essere un formidabile serbatoio di email e altri dati sensibili a disposizione di attori malevoli, spammer e altro.&#xA;&#xA;Inoltre leggi recenti sulla privacy come GDPR, cozzavano contro la natura immutabile dei keyserver che, by design, aggiungono chiavi e non permettono la cancellazione.&#xA;Modelli recenti&#xA;I modelli di keyserver successivi mitigano (ma non risolvono completamente) queste debolezze:&#xA;&#xA;rinunciando alla federazione e alla distribuzione&#xA;sposando un modello basato sul controllo dell&#39;email prima dell&#39;accettazione della chiave&#xA;ricorrendo a limitazioni, filtri e valutazioni sulla bontà delle chiavi prima che queste vengano accettate.&#xA;&#xA;I principali modelli di keyserver sono:&#xA;&#xA;Hagrid&#xA;Mailvelope&#xA;HockeyPuck&#xA;&#xA;Sono stati tutti creati per sopperire ai limiti dei server SKS.&#xA;Hagrid&#xA;Il primo, basato su SequoiaPGP, ha una natura centralizzata (non sarà mai federato), è GDPR compliant ed ha dato luogo a keys.openpgp.org.&#xA;&#xA;I keyserver di questo tipo non aderiscono al modello WOT per ragioni di privacy e di efficienza. Sono quindi rifiutate le chiavi di terze parti, essenziali nel modello WOT, l&#39;accettazione della chiave pubblica è vincolata dalla verifica dell&#39;email, è possibile rimuovere le chiavi. Sono più resistenti agli attacchi di key poisoning.&#xA;Mailvelope&#xA;Ha dato luogo al keyserver keys.mailvelope.com, molto simile al primo e ne condivide la politica: no federazione, niente firme di terze parti e verifica dell&#39;email vincolante per l&#39;accettazione della chiave.&#xA;&#xA;A differenza di altri keyserver, il focus di Mailvelope è la semplificazione dell&#39;utilizzo della crittografia sull&#39;e-mail, che sia webmail, con i provider e i browser che supportano Mailvelope, o client, quando si integrino con le sue api.&#xA;Hockeypuck&#xA;È un ritorno alle origini, ha una natura federata ed è considerato l&#39;alternativa robusta ai server SKS. Uno fra i più noti server hockeypuck è certamente:&#xA;&#xA;keyserver.ubuntu.com&#xA;&#xA;il keyserver gestito dalla comunità Ubuntu che contiene le chiavi per i suoi pacchetti ma è anche aperto al pubblico.&#xA;&#xA;Un altro keyserver hockeypuck più di nicchia perché legato ad una specifica realtà tecnologica olandese è:&#xA;&#xA;pgp.surf.nl&#xA;&#xA;Sebbene possa essere meno aggiornato del primo, può essere usato liberamente per pubblicare le proprie chiavi.&#xA;&#xA;I keyserver di questo tipo, come il pool di server sks, anche se con un filtraggio più stringente, abbracciano il modello WOT con tutto quello che ne consegue.&#xA;Altri keyserver&#xA;Infine, per dovere di cronaca, bisogna citare due decani dei keyserver apparsi all&#39;alba di pgp e ormai non più utilizzabili per motivi di obsolescenza e di abbandono.&#xA;&#xA;pgp.mit.edu: uno dei primi repository a permettere la pubblicazione e la distribuzione di chiavi pubbliche, facente anche parte della rete SKS.&#xA;&#xA;global.pgp.com: l&#39;alternativa proprietaria, appartenente a PGP Corporation prima e Symantec dopo, era il repository centralizzato per la distribuzione di chiavi usato dall&#39;applicazione pgp.&#xA;&#xA;In conclusione, se la necessità è di utilizzare il WOT, allora la scelta è senza dubbio Hockeypuck quindi keyserver.ubuntu.com.&#xA;Se invece la privacy è prioritaria, Hagrid quindi keys.openpgp.org diventa la scelta obbligatoria, tanto che è il default sia di GPG che di OpenKeyChain&#xA;&#xA;#gpg #gnupg #crittografia #keyserver #hagrid #hockeypuck #mailvelope]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/0bb057b62-db9a0d/RPB3ST0CtANw/6HDoBJ1kvx62x1IB9N7jfgzjG2JcWJ5eRPNRPOF6.png" alt="gpg tools"></p>

<p>Esistono numerose gui che semplificano la gestione di una chiave gpg.</p>

<p>Questo articolo ha lo scopo di semplificare la creazione di una chiave gpg attraverso la cli di GnuPG, senza entrare nel suo mare magnum di opzioni.
</p>

<h2 id="indice">Indice</h2>
<ol><li><a href="#premessa" rel="nofollow">Premessa</a></li>
<li><a href="#gestione-della-chiave" rel="nofollow">Gestione della chiave</a></li>
<li><a href="#come-proteggere-il-nostro-keyring" rel="nofollow">Come proteggere il nostro keyring</a></li>
<li><a href="#cos-e-un-keyserver" rel="nofollow">Cos&#39;è un keyerver</a></li></ol>

<hr>

<h2 id="a-id-premessa-premessa-a"><a id="premessa&#34;">Premessa</a></h2>

<p>Cosa <strong>NON</strong> è una chiave gpg?
Una coppia di chiavi, una pubblica e una privata basate sulla crittografia asimmetrica.</p>

<p>Cos&#39;è una chiave gpg?
Non è solo una coppia di chiavi asimmetriche ma è un <strong>certificato</strong>.
Dal punto di vista delle informazioni, una chiave gpg contiene:</p>
<ul><li>informazioni <strong>identificative</strong> (nome, commento, email, foto, ecc)</li>
<li>informazioni <strong>non identificative</strong> (dati tecnici che fanno parte delle chiavi: scadenza, keyserver, algoritmi di hash e cifratura, revoker ecc.)</li></ul>

<p>Una <strong>chiave gpg</strong>, in definitiva, è costituita da:</p>
<ul><li>una <strong>chiave primaria</strong> (detta anche <strong>secret key</strong> o <strong>master key</strong>)</li>
<li>da una o più sottochiavi</li>
<li>da una serie di informazioni personali.</li></ul>

<p>Ognuna di queste “chiavi” è in realtà una coppia di chiavi asimmetriche dotate delle seguenti autorizzazioni:</p>
<ul><li><strong>Certificazione</strong>: capacità della chiave di <strong>firmare</strong>, e quindi <strong>validare</strong>, le chiavi gpg di altri utenti.</li>
<li><strong>Firma</strong>: capacità di <strong>firmare documenti</strong>.</li>
<li><strong>Cifratura</strong>: capacità di <strong>cifrare documenti</strong>.</li>
<li><strong>Autenticazione</strong>: capacità di <strong>autenticare l&#39;utente</strong> su alcuni protocolli come <strong>TLS</strong> o <strong>SSH</strong>.</li></ul>

<p>La certificazione, ossia la capacità di validare altre chiavi oltre la propria, è esclusiva della master key.
Le altre autorizzazioni possono essere delegate alle sottochiavi.</p>

<p>Certificazioni e firma, garantiscono <strong>autenticazione</strong>, <strong>integrità</strong> e <strong>non ripudio</strong> del mittente.
La cifratura garantisce <strong>confidenzialità</strong>.
Le prime due sono da considerarsi più critiche e normalmente assegnate alla master key.</p>

<p>Una chiave può avere una o più proprietà. Di default, gpg crea una master key con autorizzazioni per firma e certificazione e una sottochiave con autorizzazioni per cifratura.</p>

<h2 id="a-id-gestione-della-chiave-gestione-della-chiave-a"><a id="gestione-della-chiave">Gestione della chiave</a></h2>

<p>Per la creazione e la gestione della chiave nei suoi elementi principali, vedremo:</p>
<ul><li>come creare la chiave primaria</li>
<li>come aggiungere sottochiavi, uid</li>
<li>come modificare password o scadenza</li>
<li>come si certifica un&#39;altra chiave con la nostra (firma di chiave)</li>
<li>come si cancellano localmente uid, sottochiavi e firme</li>
<li>come si revoca un certificato, una sottochiave, un uid o una certificazione</li>
<li>come si usa un keyserver per la pubblicazione e la ricerca delle chiavi</li></ul>

<h3 id="creazione-della-chiave-primaria">Creazione della chiave primaria</h3>

<pre><code class="language-bash"># gpg --quick-gen-key &lt;uid&gt; &lt;algo&gt; &lt;auth&gt; &lt;expire&gt;, dove
# - &lt;uid&gt;: &#34;uid_name (comment) &lt;e-mail&gt;&#34;
# - &lt;algo&gt;: uno fra &#39;gpg --with-colons --list-config&#39;
# - &lt;auth&gt;: cert|encr|sign
# - &lt;expire&gt;: 0 =&gt; illimitato, ny|nm|nd =&gt; n anni|mesi|giorni
gpg --quick-gen-key gandalf ed25519 cert 0
</code></pre>

<p>Crea una chiave gpg la cui secret key può solo certificare, l&#39;uid è composto dal solo nome <code>gandalf</code> e ha scadenza illimitata.</p>

<pre><code class="language-bash">gpg -K
/home/gandalf/.gnupg/pubring.kbx
--------------------------------
sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]
	  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B
uid                   [ultimate] gandalf
</code></pre>

<p>Ecco la chiave appena creata, nella prima riga distinguiamo:</p>
<ul><li>“sec”, sta per <strong>sec</strong>ret key</li>
<li>algoritmo/KeyID</li>
<li>data di creazione</li>
<li>capability (<strong>[C]</strong>=certify).</li></ul>

<p>Nella riga successiva è visibile il <strong>fingerprint</strong> e nella terza, l&#39;uid (gandalf). Questi elementi, come il KeyID, servono per indirizzare la chiave.</p>

<p>Una sintassi più completa sarebbe:</p>

<pre><code class="language-bash">gpg --quick-gen-key &#34;nome (commento) &lt;e-mail&gt;&#34; algo cert|sign|encr &lt;scadenza&gt;
</code></pre>

<p>Per avere una lista degli algo:</p>

<pre><code class="language-bash">gpg --with-colons --list-config
</code></pre>

<h3 id="aggiungere-una-sottochiave">Aggiungere una sottochiave</h3>

<p>Aggiungiamo le chiavi di firma e di cifratura con scadenza 5 anni e 1 anno rispettivamente</p>

<pre><code class="language-bash"># gpg --quick-addgen-key &lt;fpr&gt; &lt;algo&gt; &lt;auth&gt; &lt;expire&gt;
gpg --quick-add-key 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B ed25519 sign 5y
gpg --quick-add-key 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B cv25519 encr 1y
</code></pre>

<p>Come prima, oltre alla secret key, ora sono visibili le sottochiavi (ssb, <strong>S</strong>ecret <strong>S</strong>ub<strong>K</strong>ey) di firma e cifratura con le evidenze per:
algoritmo, KeyID, creazione, capability ([S] per sign e [E] per encrypt) e scadenza.</p>

<pre><code class="language-bash">gpg -K
/home/gandalf/.gnupg/pubring.kbx
--------------------------------
sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]
	  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B
uid                   [ultimo] gandalf
ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [scadenza: 2029-11-04]
ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [scadenza: 2025-11-05]
</code></pre>

<h3 id="meccanismi-di-indirizzamento-per-una-chiave">Meccanismi di indirizzamento per una chiave</h3>

<p>Una chiave può essere riferita attraverso l&#39;uid, il key ID o il fingerprint. Il riferimento è importante nelle operazioni di manipolazione della chiave.</p>

<pre><code class="language-bash">gpg --with-subkey-fingerprint -K
/home/gandalf/.gnupg/pubring.kbx
--------------------------------
sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]
	  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B
uid                   [ultimate] gandalf
uid                   [ultimate] Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) &lt;gandalf@lotr.org&gt;
ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [expires: 2029-11-04]
	  87EF9CF3D5A4D78ADA80E364A391F0548FB542DB
ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [expires: 2025-11-04]
	  4DD33D36C54E2247486C9DC7AAEF649D51D832E8
</code></pre>
<ul><li><code>0xE01BDCB6A3C6778B</code> è il key ID della master key</li>
<li><code>8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B</code> è il fingerprint della master key</li>
<li><code>gandalf</code> è uno degli uid</li></ul>

<h3 id="aggiungere-un-uid">Aggiungere un uid</h3>

<p>Aggiunge un nuovo uid in termini di nome-commento-email e lo battezza come primario.</p>

<pre><code class="language-bash"># gpg --quick-add-uid &lt;primary_uid&gt; &lt;new_uid&gt;
gpg --quick-add-uid gandalf &#34;Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) &lt;gandalf@lotr.org&gt;&#34;

# gpg --quick-set-primary-uid &lt;primary_uid&gt; &lt;new_uid&gt;
gpg --quick-set-primary-uid &#34;gandalf&#34; &#34;Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) &lt;gandalf@lotr.org&gt;&#34;
</code></pre>

<h3 id="firmare-una-chiave">Firmare una chiave</h3>

<p>Ossia riconoscere una chiave gpg come valida attraverso la certificazione.
Pubblicare questa chiave sul keyserver, comunica al mondo che riconosciamo quella chiave come valida.</p>

<p>Convalida tutti gli uid della chiave identificata da <code>&lt;fpr&gt;</code></p>

<pre><code class="language-bash"># gpg --quick-sign-key &lt;fpr&gt;
gpg --quick-sign-key AD59879E1CB5D63E98F05FB9204621DACB1296E0
</code></pre>

<p>Convalida un uid specifico della chiave identificata da <code>&lt;fpr&gt;</code></p>

<pre><code class="language-bash"># gpg --quick-sign-key &lt;fpr&gt; &lt;uid&gt;
gpg --quick-sign-key AD59879E1CB5D63E98F05FB9204621DACB1296E0 frodo
</code></pre>

<h3 id="modificare-la-password">Modificare la password</h3>

<p>Inserisce la password con cui tutte le chiavi private (master key e subkey) relative all&#39;uid indicato, vengono cifrate. Se la password viene lasciata vuota, la chiave non viene cifrata.</p>

<pre><code class="language-bash"># gpg --passwd &lt;uid|KeyID|fpr&gt;
gpg --passwd gandalf
</code></pre>

<h3 id="modificare-la-scadenza">Modificare la scadenza</h3>

<p>Modifico le scadenze delle chiavi come segue:</p>
<ul><li>la master key da illimitata a 10 anni</li>
<li>la sottochiave di firma da 5 anni a 4 anni</li>
<li>la sottochiave di cifratura da 1 anno a 2 anni</li></ul>

<pre><code class="language-bash"># gpg --quick-set-expire &lt;fpr&gt; &lt;expire&gt;
gpg --quick-set-expire 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B 10y
gpg --quick-set-expire 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B 4y 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB
gpg --quick-set-expire 8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B 2y 4DD33D36C54E2247486C9DC7AAEF649D51D832E8
</code></pre>

<pre><code class="language-bash">gpg --with-subkey-fingerprint -K
/home/gandalf/.gnupg/pubring.kbx
--------------------------------
sec   ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C] [expires: 2034-11-04]
	  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B
uid                   [ultimate] gandalf
uid                   [ultimate] Gandalf Il Bianco (Questa è la chiave di Gandalf Il Bianco) &lt;gandalf@lotr.org&gt;
ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [expires: 2028-11-04]
	  87EF9CF3D5A4D78ADA80E364A391F0548FB542DB
ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [expires: 2026-11-04]
	  4DD33D36C54E2247486C9DC7AAEF649D51D832E8
</code></pre>

<h3 id="cancellazione-di-elementi-dal-keyring">Cancellazione di elementi dal keyring</h3>

<p>La cancellazione di elementi come uid, firme o sottochiavi ha effetto solo sul keyring locale.
Se la chiave è stata pubblicata su un repository, le cancellazioni non avranno alcun effetto.
Se si vuole inibire uno di questi elementi, si deve ricorrere alla <strong>revoca</strong> che è esportabile sui keyserver.</p>

<h4 id="cancellare-una-sottochiave">Cancellare una sottochiave</h4>

<p>Cancella la sottochiave di firma</p>

<pre><code class="language-bash"># gpg --delete-secret-and-public-keys &lt;KeyID|fpr&gt;
gpg --delete-secret-and-public-keys 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB!
# o, equivalentemente
gpg --delete-secret-and-public-keys 0xA391F0548FB542DB!
</code></pre>

<h4 id="cancellare-un-uid">Cancellare un uid</h4>

<p>Cancella la seconda identità della chiave <code>gandalf</code> (<code>0xA391F0548FB542DB</code>)</p>

<pre><code class="language-bash"># gpg --edit-key [KeyID|fpr|uid]
gpg --edit-key gandalf
    uid 2
    deluid
    save
</code></pre>

<h4 id="cancellare-una-firma">Cancellare una firma</h4>

<p>Cancella tutte le firme del 2° uid che non siano self-signature.</p>

<pre><code class="language-bash"># gpg --edit-key [KeyID|fpr|uid]
gpg --edit-key gandalf
    uid 2
    delsig
    save
</code></pre>

<h3 id="operazioni-di-revoca">Operazioni di revoca</h3>

<p>Per quel che riguarda le chiavi gpg (i certificati) di cui si possiede la chiave privata, l&#39;operazione di revoca può avvenire su uno degli elementi della chiave o sull&#39;intero certificato.</p>

<h4 id="revocare-un-uid">Revocare un uid</h4>

<p>Revoco l&#39;uid (<code>gandalf il grigio</code>),</p>

<pre><code class="language-bash"># gpg --quick-revuid &lt;primary_uid&gt; &lt;uid&gt; 
gpg --quick-revuid gandalf &#34;gandalf il grigio&#34;
</code></pre>

<h4 id="revocare-una-sottochiave">Revocare una sottochiave</h4>

<pre><code class="language-bash"># gpg --edit-key [KeyID|fpr|uid]
gpg --edit-key 0xA391F0548FB542DB
    key 1
    revkey
    save
</code></pre>

<h4 id="revocare-una-nostra-certificazione">Revocare una nostra certificazione</h4>

<p>Così come validiamo le chiavi altrui con la nostra firma di certificazione, allo stesso modo possiamo revocarla.</p>

<p>Revoco la mia firma su tutti gli uid di una chiave pubblica</p>

<pre><code class="language-bash"># gpg --quick-revoke-sig &lt;KeyID|fpr del firmato&gt; &lt;KeyID|fpr del firmante&gt; 
gpg --quick-revoke-sig 0x204621DACB1296E0 0xE01BDCB6A3C6778B
</code></pre>

<p>Posso anche revocare la mia firma su un uid specifico</p>

<pre><code class="language-bash"># gpg --quick-revoke-sig &lt;KeyID|fpr del firmato&gt; &lt;KeyID|fpr del firmante&gt; &lt;uid_i&gt;
gpg --quick-revoke-sig 0x204621DACB1296E0 0xE01BDCB6A3C6778B frodo_uid2
</code></pre>

<h4 id="revocare-l-intero-certificato">Revocare l&#39;intero certificato</h4>

<p>Va a revocare non solo tutti gli uid e tutte le sottochiavi, ma anche la masterkey.</p>

<pre><code class="language-bash">gpg --import 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB.rev
</code></pre>

<p>Il certificato di revoca viene generato all&#39;atto della creazione della chiave.
Se non ci fosse, conviene sempre crearlo così che, se la master key venisse compromessa, saremmo almeno in grado di revocare l&#39;intero certificato.</p>

<pre><code class="language-bash"># gpg -o &lt;file&gt; --gen-rev &lt;fpr&gt;
gpg -o 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB.rev --gen-rev 87EF9CF3D5A4D78ADA80E364A391F0548FB542DB
</code></pre>

<p>Le operazioni di revoca, nel mondo gpg, corrispondono alle maledizioni senza perdono, nel mondo di Harry Potter.
Non si torna indietro a meno di un backup, e se le revoche vengono pubblicate su un keyserver, diventano irreversibili.</p>

<h3 id="operazioni-sul-keyserver">Operazioni sul keyserver</h3>

<p>Il caricamento delle chiavi su un keyserver costituisce la finalizzazione delle operazioni svolte finora.</p>

<p>Il keyserver pubblica al mondo le nostre chiavi, la configurazione avviene nel file <strong>dirmngr.conf</strong> aggiungendo una riga (ad es. per keys.openpgp.org):</p>

<pre><code class="language-bash">vi dirmngr.conf

...
keyserver hkps://keys.openpgp.org
...
</code></pre>

<p>e ricaricando la configurazione:</p>

<pre><code class="language-bash">gpgconf --reload dirmngr
</code></pre>

<h4 id="cerca">Cerca</h4>

<p>Cerca nel keyserver le chiavi con uid specificato. In caso di successo, chiede se possono essere aggiunte al keyring.</p>

<pre><code class="language-bash"># gpg --search-keys &lt;uid&gt;
gpg --search-keys 0xE01BDCB6A3C6778B 0x204621DACB1296E0
</code></pre>

<p><strong>Per gli utilizzatori di keys.openpgp.org:</strong></p>

<pre><code class="language-bash">gpg --auto-key-locate keyserver --locate-keys &lt;uid&gt;
</code></pre>

<h4 id="invia">Invia</h4>

<p>Invia una lista di chiavi al keyserver</p>

<pre><code class="language-bash"># gpg --send-keys &lt;KeyIDs|fpr&gt;
gpg --send-keys 0xE01BDCB6A3C6778B 0x204621DACB1296E0
</code></pre>

<p><strong>Per gli utilizzatori di keys.openpgp.org:</strong>
Il classico send non è sufficiente perché non sarebbe possibile validare la mail di conferma. Si consiglia, non volendo usare l&#39;interfaccia web, di usare il seguente comando:</p>

<pre><code class="language-bash"># gpg --export &lt;KeyID|fpr|uid&gt; | curl -T - https://keys.openpgp.org
gpg --export 0xE01BDCB6A3C6778B | curl -T - https://keys.openpgp.org
</code></pre>

<p>che restituisce un link diretto alla pagina di verifica.</p>

<h4 id="ricevi">Ricevi</h4>

<p>Scarica dal keyserver le chiavi</p>

<pre><code class="language-bash"># gpg --keyserver-options honor-keyserver-url --receive-keys &lt;KeyIDs|fpr&gt;
gpg --keyserver-options honor-keyserver-url --receive-keys 0xE01BDCB6A3C6778B 0x204621DACB1296E0
</code></pre>

<p>Scarica dal keyserver la chiave indicata dall&#39;uri</p>

<pre><code class="language-bash"># gpg --fetch-keys &lt;uri&gt;
gpg --fetch-keys https://keyserver.ubuntu.com/pks/lookup?search=0xE01BDCB6A3C6778B&amp;fingerprint=on&amp;op=index
</code></pre>

<h4 id="aggiorna">Aggiorna</h4>

<p>Per rinnovare tutte le chiavi pubbliche del keyring.</p>

<pre><code class="language-bash">gpg --keyserver-options honor-keyserver-url --refresh-keys
</code></pre>

<h2 id="a-id-come-proteggere-il-nostro-keyring-come-proteggere-il-nostro-keyring-a"><a id="come-proteggere-il-nostro-keyring">Come proteggere il nostro keyring</a></h2>

<p>Come visto in precedenza, suggerisco di creare la master key <strong>per la sola certificazione</strong> e le due sottochiavi per firma e cifratura (anche quando la chiave primaria dovesse contenere altre autorizzazioni).</p>

<p>Questo permetterebbe, volendo ma non è necessario, di ruotare più agevolmente le chiavi di firma e cifratura svincolandole dalla certificazione.</p>

<p>Inoltre, così è più semplice rendere le chiavi gpg “partially stripped”, chiavi la cui sola secret key sia mancante della chiave privata, cosicché, se queste venissero smarrite o trafugate, la secret key in nostro possesso ci permetterebbe immediatamente di generare un certificato di revoca per le sottochiavi compromesse, generare delle nuove sottochiavi di firma e cifratura e di distribuire il tutto ad un keyserver.</p>

<p>Chiavi gpg siffatte permetterebbero di svolgere le consuete operazioni di firma e cifratura documentale (quello che potremmo definire “utilizzo giornaliero”) ma impedirebbero qualunque operazione critica sulla propria chiave gpg (impossibilità di aggiungere, revocare sottochiavi o uid, di alterare scadenza o password ecc.) e su quelle altrui (certificare e quindi validare altre chiavi) <u><strong>poichè è la chiave privata della master key a sigillare self-signed le informazioni della chiave gpg</strong></u>.</p>

<p>In generale, posso estrarre la chiave privata da qualunque coppia di chiavi, siano esse sottochiavi o master key, ma non è uno scenario molto comune. Per estensione, eliminandole tutte otterremo un insieme di chiavi pubbliche (quella che otterrei anche con gpg —export ).</p>

<p>Quello che invece ci interessa è <strong>eliminare la chiave privata della sola master key</strong>.
L&#39;eliminazione della chiave privata dalla master key, di per sè, non è un&#39;operazione particolarmente onerosa.</p>

<p>La vera “difficoltà” risiede nel cambio di paradigma per l&#39;utente che l&#39;utilizzo di master key stripped comporta, perché avremo a che fare con un keyring da proteggere accuratamente e dei keyring da “trincea” da usare liberamente sui nostri device.</p>

<h3 id="realizzare-un-keyring-per-l-uso-quotidiano">Realizzare un keyring per l&#39;uso quotidiano</h3>

<p>Per farlo dobbiamo eliminare le chiavi private di tutte le master key del nostro keyring e per farlo dobbiamo fare un po&#39; di assunzioni.</p>
<ol><li>Come primo passo, bisogna spostare, se non è stato già fatto, il keryring dal pc/laptop/device ad un luogo sicuro (ad es. pendrive cifrata)</li>
<li>quindi si devono estrarre le chiavi private dalle master key e distribuirle dove possano servire</li>
<li>in caso di emergenza o se vi è necessità di modificare le chiavi, importare le chiavi gpg dal dispositivo sicuro, effettuare le modifiche, rigenerare e ridistribuire le nuove chiavi stripped</li></ol>

<h4 id="eliminazione-della-chiave-privata-dalla-master-key">Eliminazione della chiave privata dalla master key</h4>

<p>La cancellazione della chiave privata impedisce alla master key o alla sottochiave  di esercitare pienamente le funzioni indicate dalle proprie autorizzazioni ossia certificazione, firma o decifratura.</p>

<p>Per intervenire sulla singola chiave privata, occorre individuare il suo fingerprint o il suo keyid e usarlo per cancellare postponendo il carattere “!”.</p>

<p>Ad es. sulla master key di gandalf:</p>

<pre><code class="language-bash">gpg --delete-secret-keys 0x055D271BD85313D0!
</code></pre>

<p>Il carattere “#” (accanto a sec) vuol dire che la chiave privata è stata eliminata</p>

<pre><code class="language-bash">gpg -K
/home/gandalf/ramfs_gpg/pubring.kbx
-----------------------------------
sec#  ed25519/0xE01BDCB6A3C6778B 2024-11-05 [C]
	  8C8EC405954D4ABB32CFA431E01BDCB6A3C6778B
uid                   [ultimo] gandalf
ssb   ed25519/0xA391F0548FB542DB 2024-11-05 [S] [scadenza: 2029-11-04]
ssb   cv25519/0xAAEF649D51D832E8 2024-11-05 [E] [scadenza: 2025-11-05]
</code></pre>

<p>Generalizzando, per realizzare il nostro keyring di lavoro si può agire, una tantum, in questo modo:</p>

<p>1. spostiamo il keyring di lavoro sul dispositivo sicuro</p>

<pre><code class="language-bash">KEYRING_RAMFS=&lt;path_ramfs&gt;
KEYRING_VAULT=&lt;path_pendrive_cifrata&gt;
KEYRING_WORK=&lt;path_gpg_daily&gt;
export GNUPGHOME=${KEYRING_WORK}; cd $GNUPGHOME

rsync -avp ${KEYRING_WORK}/ ${KEYRING_VAULT}/
</code></pre>

<p>2. rendiamo il keyring stripped cancellando le chiavi private di tutte le master key.</p>

<pre><code class="language-bash">for FPR in $(gpg --with-colons -K|grep sec -A 1|grep fpr|cut -d &#34;:&#34; -f 10); do 
    gpg --batch --yes --delete-secret-keys &#34;${FPR}!&#34;
done
</code></pre>

<p>In seguito, come detto in precedenza, per lavorare sul keyring occorrerà ripristinarlo dal dispositivo sicuro, ad es. una pendrive cifrata.</p>

<p>Per non lasciare tracce su altri device che non sia la pendrive cifrata, si possono seguire due strade.</p>
<ol><li>usare una distribuzione live (più sicura)</li>
<li>montare una partizione in ram su ramfs (non usa lo swap) su cui caricare il keyring.</li></ol>

<p>La prima via è certamente preferibile. Non c&#39;è alcun uso dei dispositivi di storage fisici della macchine, solo quelli volatili, ma presuppone che si possa avviare un SO da pendrive.
La seconda è più accessibile per certi versi ma presuppone che si possiedano i privilegi per montare una partizione su ram.</p>

<p>Mostrerò la seconda via che è più articolata.</p>

<h4 id="lavorare-con-un-keyring-effimero">Lavorare con un keyring effimero</h4>

<p>La strategia è quella di avere un keyring effimero montato su ramfs che farà da tramite fra il keyring master (su pendrive cifrata) e il keyring di lavoro.</p>

<p>L&#39;obiettivo finale è quello di rendere strutturale il fatto di riuscire a compiere operazioni sul keyring usando il meno possibile i dispositivi di storage.</p>

<p>0. Init</p>

<pre><code class="language-bash">KEYRING_RAMFS=&lt;path_ramfs&gt;
KEYRING_VAULT=&lt;path_pendrive_cifrata&gt;
KEYRING_WORK=&lt;path_gpg_daily&gt;
</code></pre>

<p>1. Monto la partizione effimera</p>

<pre><code class="language-bash">mkdir -p ${KEYRING_RAMFS}
sudo mount -t ramfs -o size=10M ramfs ${KEYRING_RAMFS}
sudo chown $(logname):$(logname) ${KEYRING_RAMFS}
</code></pre>

<p>2. Esporto chiavi pubbliche e trust dal keyring di lavoro</p>

<pre><code class="language-bash">gpg -o ${KEYRING_RAMFS}/keyring_pubkeys.gpg --export
gpg --export-ownertrust &gt; ${KEYRING_RAMFS}/keyring_ownertrust.txt
</code></pre>

<p>3. Copio il keyring master sulla partizione effimera, modifico <code>GNUPGHOME</code> in modo che gpg lavori direttamente sulla partizione effimera. Su questo keyring effimero, completo l&#39;allineamento importando le chiavi pubbliche e il trust provenienti dal keyring di lavoro.</p>

<pre><code class="language-bash">rsync -avp ${KEYRING_VAULT}/ ${KEYRING_RAMFS}/
export GNUPGHOME=${KEYRING_RAMFS}; cd $GNUPGHOME
gpg --import keyring_pubkeys.gpg
gpg --import-ownertrust keyring_ownertrust.txt
</code></pre>

<p>4. Eseguo le mie manipolazioni sul keyring effimero: uid, key, passwd, firme, revoche ecc.</p>

<pre><code class="language-bash">...
[operazioni gpg]
...
</code></pre>

<p>5. Copio il keyring master dalla partizione effimera alla pendrive cifrata</p>

<pre><code class="language-bash">rsync -avp ${KEYRING_RAMFS}/ ${KEYRING_VAULT}/
</code></pre>

<p>6. Rendo il keyring effimero di nuovo stripped</p>

<pre><code class="language-bash">for FPR in $(gpg --with-colons -K|grep sec -A 1|grep fpr|cut -d &#34;:&#34; -f 10); do 
    gpg --batch --yes --delete-secret-keys &#34;${FPR}!&#34;
done
</code></pre>

<p>7. Ripristino il keyring di lavoro escludendo i certificati di revoca e cancellando la partizione effimera</p>

<pre><code class="language-bash">rsync -avp --exclude openpgp-revocs.d ${KEYRING_RAMFS}/ ${KEYRING_WORK}/
export GNUPGHOME=${KEYRING_WORK}/
sudo umount ${KEYRING_RAMFS}; rmdir ${KEYRING_RAMFS}
</code></pre>

<p>La complessità di questa gestione può essere ridotta rendendo scriptabili i due blocchi (1,2,3) e (5,6,7), ad es. immaginando di avere a disposizione delle funzioni come <strong>gpg-vault [open|close|status]</strong>, avendo la consapevolezza che, se usate male, possono essere delle operazioni distruttive.</p>

<h2 id="a-id-cos-e-un-keyserver-cos-è-un-keyerver-a"><a id="cos-e-un-keyserver">Cos&#39;è un keyerver</a></h2>

<p>Il keyserver è il luogo in cui pubblichiamo le nostre chiavi per renderle disponibili agli altri utenti.</p>

<p>Inizialmente i keyserver avevano una logica p2p, distribuita e decentralizzata ottenuta con un&#39;implementazione chiamata <strong>SKS</strong> (<strong>S</strong>ynchronizing <strong>K</strong>ey <strong>S</strong>erver) basata sulla rapida diffusione delle chiavi fra keyserver.</p>

<p>I keyserver inizialmente servivano anche a realizzare il <strong>WOT</strong> (<strong>W</strong>eb <strong>O</strong>f <strong>T</strong>rust) per la convalida delle chiavi.</p>

<p>Col tempo, la mancanza di aggiornamenti del protocollo sks e la suscettibilità ad attacchi di tipo “key poisoning”, che possono rendere indisponibili interi certificati (ad es. riempiendo la chiave con innumerevoli firme contenenti tonnellate di dati tali da far crashare i client) o gli stessi keyserver (pubblicando quantitivi enormi di certificati non validi), amplificata dalle caratteristiche di sincronizzazione dei server, ne hanno decretato la fine.</p>

<p>La realizzazione del WOT, tra l&#39;altro, offriva pubblicamente una tale quantità di chiavi che permetteva, da un lato, di tracciare interi social network basati sulle firme che vi venivano apposte, dall&#39;altro, di essere un formidabile serbatoio di email e altri dati sensibili a disposizione di attori malevoli, spammer e altro.</p>

<p>Inoltre leggi recenti sulla privacy come GDPR, cozzavano contro la natura immutabile dei keyserver che, by design, aggiungono chiavi e non permettono la cancellazione.</p>

<h3 id="modelli-recenti">Modelli recenti</h3>

<p>I modelli di keyserver successivi mitigano (ma non risolvono completamente) queste debolezze:</p>
<ul><li>rinunciando alla federazione e alla distribuzione</li>
<li>sposando un modello basato sul controllo dell&#39;email prima dell&#39;accettazione della chiave</li>
<li>ricorrendo a limitazioni, filtri e valutazioni sulla bontà delle chiavi prima che queste vengano accettate.</li></ul>

<p>I principali modelli di keyserver sono:</p>
<ul><li><strong>Hagrid</strong></li>
<li><strong>Mailvelope</strong></li>
<li><strong>HockeyPuck</strong></li></ul>

<p>Sono stati tutti creati per sopperire ai limiti dei server SKS.</p>

<h4 id="hagrid">Hagrid</h4>

<p>Il primo, basato su <strong>SequoiaPGP</strong>, ha una natura centralizzata (non sarà mai federato), è GDPR compliant ed ha dato luogo a <strong>keys.openpgp.org</strong>.</p>

<p>I keyserver di questo tipo non aderiscono al modello WOT per ragioni di privacy e di efficienza. Sono quindi rifiutate le chiavi di terze parti, essenziali nel modello WOT, l&#39;accettazione della chiave pubblica è vincolata dalla verifica dell&#39;email, è possibile rimuovere le chiavi. Sono più resistenti agli attacchi di key poisoning.</p>

<h4 id="mailvelope">Mailvelope</h4>

<p>Ha dato luogo al keyserver <strong>keys.mailvelope.com</strong>, molto simile al primo e ne condivide la politica: no federazione, niente firme di terze parti e verifica dell&#39;email vincolante per l&#39;accettazione della chiave.</p>

<p>A differenza di altri keyserver, il focus di Mailvelope è la semplificazione dell&#39;utilizzo della crittografia sull&#39;e-mail, che sia webmail, con i provider e i browser che supportano Mailvelope, o client, quando si integrino con le sue api.</p>

<h4 id="hockeypuck">Hockeypuck</h4>

<p>È un ritorno alle origini, ha una natura federata ed è considerato l&#39;alternativa robusta ai server SKS. Uno fra i più noti server hockeypuck è certamente:</p>
<ul><li><strong>keyserver.ubuntu.com</strong></li></ul>

<p>il keyserver gestito dalla comunità Ubuntu che contiene le chiavi per i suoi pacchetti ma è anche aperto al pubblico.</p>

<p>Un altro keyserver hockeypuck più di nicchia perché legato ad una specifica realtà tecnologica olandese è:</p>
<ul><li><strong>pgp.surf.nl</strong></li></ul>

<p>Sebbene possa essere meno aggiornato del primo, può essere usato liberamente per pubblicare le proprie chiavi.</p>

<p>I keyserver di questo tipo, come il pool di server sks, anche se con un filtraggio più stringente, abbracciano il modello WOT con tutto quello che ne consegue.</p>

<h4 id="altri-keyserver">Altri keyserver</h4>

<p>Infine, per dovere di cronaca, bisogna citare due decani dei keyserver apparsi all&#39;alba di pgp e ormai non più utilizzabili per motivi di obsolescenza e di abbandono.</p>

<p><strong>pgp.mit.edu</strong>: uno dei primi repository a permettere la pubblicazione e la distribuzione di chiavi pubbliche, facente anche parte della rete SKS.</p>

<p><strong>global.pgp.com</strong>: l&#39;alternativa proprietaria, appartenente a PGP Corporation prima e Symantec dopo, era il repository centralizzato per la distribuzione di chiavi usato dall&#39;applicazione pgp.</p>

<p>In conclusione, se la necessità è di utilizzare il WOT, allora la scelta è senza dubbio <strong>Hockeypuck</strong> quindi <strong>keyserver.ubuntu.com</strong>.
Se invece la privacy è prioritaria, <strong>Hagrid</strong> quindi <strong>keys.openpgp.org</strong> diventa la scelta obbligatoria, tanto che è il default sia di GPG che di OpenKeyChain</p>

<p><a href="/aytin/tag:gpg" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">gpg</span></a> <a href="/aytin/tag:gnupg" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">gnupg</span></a> <a href="/aytin/tag:crittografia" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">crittografia</span></a> <a href="/aytin/tag:keyserver" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">keyserver</span></a> <a href="/aytin/tag:hagrid" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">hagrid</span></a> <a href="/aytin/tag:hockeypuck" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">hockeypuck</span></a> <a href="/aytin/tag:mailvelope" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">mailvelope</span></a></p>
]]></content:encoded>
      <guid>https://noblogo.org/aytin/gestire-la-tua-chiave-gpg</guid>
      <pubDate>Mon, 25 Nov 2024 15:00:37 +0000</pubDate>
    </item>
    <item>
      <title>Script per la gestione della configurazione di una vpn wireguard</title>
      <link>https://noblogo.org/aytin/script-per-la-gestione-della-configurazione-di-una-vpn-wireguard</link>
      <description>&lt;![CDATA[vpn&#xA;&#xA;Cos&#39;è wireguard e come si configura, lo sappiamo ma mi serviva qualcosa che mi permettesse di fare provisioning e deprovisioning dei certificati in maniera più semplice di quanto già si faccia con i tool disponibili nella userland, wg e wg-quick.&#xA;&#xA;E questo è il motivo principale per cui è nato questo script.&#xA;!--more--&#xA;Prende come riferimento una configurazione road warrior, il primo scenario di una topologia point-to-site, quella più comune.&#xA;&#xA;Alcune considerazioni&#xA;Lo script definisce una workdir dove deposita tutte le configurazioni e i certificati.&#xA;Le precondizioni sono legate alla presenza dei tool userland wg-tools (ovviamente) e di ufw. Vengono comunque verificate nello script.&#xA;&#xA;Altra semplificazione è data dal fatto di allocare una /24 come rete wireguard. 254 host per una rete domestica sono più che sufficienti.&#xA;&#xA;L&#39;allocazione degli ip viene fatta con un progressivo memorizzato nel file &#39;ip\renew&#39;. Gli ip dei certificati revocati vengono mantenuti in un file, &#39;ip\release&#39;.&#xA;Quando si crea un nuovo certificato, si controlla prima che ci sia un ip da recuperare in ip\release. Se la lista è vuota si ricorre al progressivo.&#xA;&#xA;La creazione della configurazione lato server passa da due file di configurazione: una configurazione globale ottenuta tracciando l&#39;evoluzione iniziale in termini di aggiunta o rimozione dei client peer e destinata al rilascio in esecuzione. L&#39;altra contenente la sola configurazione del server e usata unicamente per la rigenerazione della configurazione globale a partire dai peer esistenti.&#xA;&#xA;L&#39;operazione di init è propedeutica per addclient, removeclient, rebuild, deploy, share.&#xA;&#xA;Le operazioni a disposizione sono:&#xA;&#xA;init: inizializza la configurazione di un server wireguard&#xA;addclient: crea il certificato lato client e aggiunge il relativo peer sulla configurazione del server&#xA;removeclient: cancella il certificato lato client e rimuove il relativo peer sulla configurazione del server&#xA;rebuild: rigenera la configurazione del server usando i certificati client esistenti&#xA;deploy: finalizza la configurazione riavviando il servizio con le nuove impostazioni&#xA;share: crea i qr-code per i certificati client da utilizzare nelle configurazioni&#xA;&#xA;Per tutto il resto, i commenti nel codice sono abbastanza esplicativi.&#xA;Lo script&#xA;!/bin/bash&#xA;&#xA;Questo è il file di configurazione globale, i dati sono fittizi.&#xA;Può essere mantenuto nello script o nella home dell&#39;utente &#xA;(es. $HOME/.config/wgman.conf) e importato &#xA;con &#39;source&#39; all&#39;inizio.&#xA;WGINTERFACE=wg0&#xA;PHYSICALINTERFACE=eth0&#xA;NETWORK=&#34;192.168.15.0&#34;&#xA;SUBNETMASK=&#34;24&#34;&#xA;SERVERIPADDRESS=&#34;192.168.15.1&#34;&#xA;DNS=&#34;1.1.1.1&#34;&#xA;LISTENPORT=&#34;51820&#34;&#xA;ENDPOINT=wireguard.nodns.net:51820&#34;&#xA;WORKDIR=&#34;$HOME/wireguard&#34;&#xA;&#xA;checkdependency() {&#xA;    if test -e /usr/sbin/ufw; then&#xA;        if test -e /usr/bin/wg; then&#xA;            return 0&#xA;        else&#xA;            return 2&#xA;        fi&#xA;    else&#xA;        return 1&#xA;    fi&#xA;}&#xA;&#xA;isinit() {&#xA;    test -e ${WORKDIR}/conf.d/serverwg.conf &amp;&amp; return 0 || return 1&#xA;}&#xA;&#xA;Genera la chiave privata&#xA;genprivkey() {&#xA;    wg genkey | tee ${WORKDIR}/keys/$1privkey&#xA;}&#xA;&#xA;Genera la pre-shared key&#xA;genclientpsk() {&#xA;    # Evita il warning sui permessi del file che devono essere 600&#xA;    umask 077&#xA;    wg genpsk | tee ${WORKDIR}/psk/$1psk&#xA;}&#xA;&#xA;Rilascio di un nuovo indirizzo ip. Questa funziona viene invocata da&#xA;addclient().&#xA;&#xA;I primi 3 ottetti li ottengo dalla variabile globale NETWORK.&#xA;L&#39;ultimo ottetto, relativo all&#39;host, lo ricavo dalla lista degli ip&#xA;riutilizzabili (&#34;iprelease&#34;).&#xA;&#xA;Se non è vuota, prelevo il primo e lo rimuovo dalla lista. Se è vuota,&#xA;prelevo l&#39;ultimo ottetto da &#34;iprenew&#34; e lo incremento per il successivo&#xA;assegnamento.&#xA;iprenew() {&#xA;    # Selezioni i primi 3 ottetti del network&#xA;    SUBIP=$(echo ${NETWORK}|awk -F &#34;.&#34; &#39;{print $1&#34;.&#34;$2&#34;.&#34;$3}&#39;)&#xA;&#xA;    if [[ ! -e ${WORKDIR}/conf.d/iprelease || ! -s ${WORKDIR}/conf.d/iprelease ]]; then&#xA;        # Genero il nuovo ip (Incremento di 1 l&#39;ultimo ottetto)&#xA;        IP=$(cat ${WORKDIR}/conf.d/iprenew)&#xA;        echo $((++IP))   ${WORKDIR}/conf.d/iprenew&#xA;&#xA;        # Restituisco i 3 ottetti + il quarto&#xA;        #echo -n ${SUBIP};cat ${WORKDIR}/conf.d/iprenew&#xA;    else&#xA;        IP=$(head -n 1 ${WORKDIR}/conf.d/iprelease)&#xA;        sed -i &#34;1d&#34; ${WORKDIR}/conf.d/iprelease&#xA;    fi&#xA;    echo -n ${SUBIP}&#34;.&#34;${IP}&#xA;}&#xA;&#xA;Riallocazione di un indirizzo ip. Questa funzione viene invocata da&#xA;removeclient().&#xA;Aggiungo l&#39;ultimo ottetto alla lista degli ip riallocabili.&#xA;@par 1: ultimo ottetto.&#xA;iprelease() {&#xA;    echo $1|cut -d&#34;.&#34; -f 4     ${WORKDIR}/conf.d/iprelease&#xA;}&#xA;&#xA;Aggiunge il nuovo peer al file di configurazione del server&#xA;@par 1: CLIENTPUBLICKEY&#xA;@par 2: CLIENTPSK&#xA;@par 3: CLIENTIPADDRESS&#xA;@par 4: CLIENTNAME&#xA;addpeertoserver() {&#xA;    cat     ${WORKDIR}/conf.d/serverwg.conf &lt;&lt; EOF&#xA;$4&#xA;[Peer]&#xA;PublicKey = $1&#xA;PresharedKey = $2&#xA;AllowedIPs = $3/32&#xA;PersistentKeepalive = 25&#xA;&#xA;EOF&#xA;}&#xA;&#xA;Inizializza la configurazione del server wireguard.&#xA;&#xA;Questa operazione può essere fatta una sola volta a meno che non si&#xA;cancelli tutta la workdir.&#xA;&#xA;Verranno creati due file  di configurazione: serverwg.conf e &#xA;serverwgraw.conf&#xA;&#xA;Il primo conterrà la configurazione completa del server e dei peer,&#xA;verrà aggiornato ad ogni modifica dei client (aggiunta o rimozione) e&#xA;verrà usato per il deploy della configurazione.&#xA;&#xA;Il secondo conterrà la configurazione del solo server e verrà usato&#xA;solo per rigenerare il primo file di configurazione.&#xA;init() {&#xA;    # Controllo che wireguard sia almeno abilitato&#xA;    echo -n &#34;Inserire la password di Amministratore: &#34;; read -s PASSWORD&#xA;    sudo -k&#xA;    if echo $PASSWORD|sudo -S echo &#34;got a root&#34;   /dev/null; then&#xA;        if ! sudo systemctl is-enabled --quiet wg-quick@${WGINTERFACE}; then&#xA;            echo -en &#34;\nAttivazione servizio wireguard... &#34;&#xA;            #sudo systemctl enable --quiet wg-quick@${WGINTERFACE}&#xA;            echo &#34;fatto.&#34;&#xA;        fi&#xA;        sudo -k &#xA;        &#xA;        #Verifico che queste cartelle esistano. Se lo sono, non faccio nulla, se no le creo.&#xA;        echo -n &#34;Creazione workdir... &#34;&#xA;        [[ ! -e ${WORKDIR}/conf.d || ! -e ${WORKDIR}/psk  || ! -e ${WORKDIR}/keys ]] \&#xA;            &amp;&amp; { mkdir -p ${WORKDIR}/{conf.d,keys,psk}; } \&#xA;            || { echo &#34;inizializzazione già effettuata.&#34;; exit; }&#xA;        echo &#34;fatto.&#34;&#xA;        &#xA;        # Genero la chiave privata per il server&#xA;        echo -n &#34;Creazione chiave private del server...&#34;&#xA;        SERVERPRIVKEY=$(genprivkey &#34;serverwg&#34;)&#xA;        echo &#34;fatto.&#34;&#xA;&#xA;        # Genero il file di configurazione&#xA;        echo -n &#34;Inizializzazione del server... &#34;&#xA;        cat   ${WORKDIR}/conf.d/serverwg.conf &lt;&lt; EOF&#xA;[Interface]&#xA;Address = ${SERVERIPADDRESS}/${SUBNETMASK}&#xA;SaveConfig = true&#xA;&#xA;PreUp = ufw route allow in on ${WGINTERFACE} out on ${PHYSICALINTERFACE} log from ${NETWORK}/${SUBNETMASK} to 0.0.0.0/0&#xA;PostDown = ufw route delete allow in on ${WGINTERFACE} out on ${PHYSICALINTERFACE} log from ${NETWORK}/${SUBNETMASK} to 0.0.0.0/0&#xA;&#xA;IP masquerading&#xA;PreUp = iptables -t nat -A POSTROUTING -o ${PHYSICALINTERFACE} -s ${NETWORK}/${SUBNETMASK} -j MASQUERADE&#xA;PostDown = iptables -t nat -D POSTROUTING -o ${PHYSICALINTERFACE} -s ${NETWORK}/${SUBNETMASK} -j MASQUERADE&#xA;&#xA;IP filtering&#xA;PreUp = ufw allow in on ${PHYSICALINTERFACE} log to 0.0.0.0/0 app Wireguard&#xA;PostDown = ufw delete allow in on ${PHYSICALINTERFACE} log to 0.0.0.0/0 app Wireguard&#xA;&#xA;ListenPort = ${LISTENPORT}&#xA;PrivateKey = ${SERVERPRIVKEY}&#xA;&#xA;EOF&#xA;        echo &#34;fatto.&#34;&#xA;        cp ${WORKDIR}/conf.d/serverwg.conf ${WORKDIR}/conf.d/serverwgraw.conf&#xA;        # Inizializza l&#39;erogatore di ip&#xA;        echo 1   ${WORKDIR}/conf.d/iprenew&#xA;    else&#xA;        echo &#34;Sono necessarie le credenziali di amministrazione per eseguire questo comando.&#34;&#xA;        exit 1&#xA;    fi&#xA;}&#xA;&#xA;Genera un certificato per il client composto da:&#xA;chiave privata del client&#xA;chiave pre-condivisa&#xA;client ip&#xA;chiave pubblica del server&#xA;nome simbolico del client&#xA;&#xA;Dopo la creazione e il salvataggio in WORKDIR/conf.d, verrà aggiunto&#xA;il relativo peer nella configurazione del server (serverwg.conf).&#xA;@par1 @par2 @par3...: lista di nomi relativi ai certificati da creare.&#xA;addclient() {&#xA;    if isinit; then&#xA;        # Se non c&#39;è alcun input, esco.&#xA;        if [[ $# -lt 1 ]]; then&#xA;            echo -e &#34;Devi inserire almeno un nome.&#34;&#xA;            exit 1&#xA;        else&#xA;            # Per ogni nome presente in input, creo una configurazione &#xA;            # client e l&#39;aggiungo alla configurazione del server.&#xA;            for CLIENTNAME in &#34;$@&#34;; do&#xA;                echo -n &#34;Creazione certificato per il client \&#34;${CLIENTNAME}\&#34;... &#34;&#xA;                &#xA;                # Controllo se la configurazione esista già discriminando&#xA;                # in base al nome del file.&#xA;                if [[ -e ${WORKDIR}/conf.d/client${CLIENTNAME}.conf ]]; then&#xA;                    echo &#34;già esistente.&#34;&#xA;                else&#xA;                    # Creo la configurazione del client&#xA;                    CLIENTPRIVKEY=$(genprivkey ${CLIENTNAME})&#xA;                    CLIENTPUBLICKEY=$(echo ${CLIENTPRIVKEY} | wg pubkey)&#xA;                    CLIENTPSK=$(genclientpsk ${CLIENTNAME})&#xA;                    CLIENTIPADDRESS=$(iprenew)&#xA;                    SERVERPUBLICKEY=$(grep PrivateKey ${WORKDIR}/conf.d/serverwg.conf | cut -d &#34; &#34; -f 3 | tr -d &#34; &#34; | wg pubkey)&#xA;                    CLIENTNAMEUPPER=$(echo ${CLIENTNAME} | tr &#39;[:lower:]&#39; &#39;[:upper:]&#39;)&#xA;                    cat   ${WORKDIR}/conf.d/client${CLIENTNAME}.conf &lt;&lt; EOF&#xA;    # ${CLIENTNAMEUPPER}&#xA;    [Interface]&#xA;    Address = ${CLIENTIPADDRESS}/${SUBNETMASK}&#xA;    DNS = ${DNS}&#xA;    PrivateKey = ${CLIENTPRIVKEY}&#xA;&#xA;    [Peer]&#xA;    PublicKey = ${SERVERPUBLICKEY}&#xA;    PresharedKey = ${CLIENTPSK}&#xA;    AllowedIPs = 0.0.0.0/0&#xA;    Endpoint = ${ENDPOINT}&#xA;    PersistentKeepalive = 25&#xA;EOF&#xA;                    echo &#34;fatto.&#34;&#xA;                    echo -n &#34;Aggiunta peer \&#34;${CLIENTNAME}\&#34; al file di configurazione del server... &#34;&#xA;                    &#xA;                    # Aggiungo il peer alla configurazione del server.&#xA;                    addpeertoserver ${CLIENTPUBLICKEY} ${CLIENTPSK} ${CLIENTIPADDRESS} ${CLIENTNAMEUPPER}&#xA;                    echo -e &#34;fatto.\n&#34;                &#xA;                fi&#xA;            done&#xA;        fi&#xA;    else&#xA;        echo &#34;È necessario inizializzare il server con &#39;wginit.sh init&#39;.&#34;&#xA;        echo &#34;L&#39;operazione richiesta non sarà completata&#34;&#xA;    fi&#xA;}&#xA;&#xA;Rimuove file di configurazioni, chiavi e pre-shared key realtive a file&#xA;dati in input.&#xA;Rimuove inoltre il peer dal file di configurazione serverwg.conf.&#xA;@par1 @par2 @par3...: lista di nomi relativi ai certificati da rimuovere.&#xA;removeclient() {&#xA;    if isinit; then&#xA;        if [[ $# -lt 1 ]]; then&#xA;            echo -e &#34;Devi inserire almeno un nome.&#34;&#xA;            exit 1&#xA;        else&#xA;            for CLIENTNAME in &#34;$@&#34;; do&#xA;                echo -n &#34;Rimozione client \&#34;${CLIENTNAME}\&#34;... &#34;&#xA;                if [[ ! -e ${WORKDIR}/conf.d/client${CLIENTNAME}.conf ]]; then&#xA;                    echo &#34;non esistente.&#34;&#xA;                else&#xA;                    # Estraggo l&#39;ultimo ottetto dell&#39;ip del client.&#xA;                    IP=$(grep &#34;Address&#34; ${WORKDIR}/conf.d/client${CLIENTNAME}.conf|cut -d &#34; &#34; -f 3|tr -d &#34; &#34;|cut -d &#34;/&#34; -f 1)&#xA;                    &#xA;                    # Lo inserisco nella lista degli ip riallocabili.&#xA;                    iprelease ${IP}&#xA;                    &#xA;                    # Cancello file di configurazione, chiave e psk del client.&#xA;                    rm ${WORKDIR}/conf.d/client${CLIENTNAME}.conf ${WORKDIR}/keys/${CLIENTNAME}privkey ${WORKDIR}/psk/${CLIENTNAME}psk&#xA;                    echo &#34;terminata con successo.&#34;&#xA;                    echo -n &#34;Rimozione peer \&#34;${CLIENTNAME}\&#34; dal file di configurazione del server... &#34;&#xA;                    &#xA;                    # Rimuovo il peer dalla configurazione del server.&#xA;                    CLIENTNAMEUPPER=$(echo ${CLIENTNAME} | tr &#39;[:lower:]&#39; &#39;[:upper:]&#39;)&#xA;                    sed -i &#34;/# ${CLIENTNAMEUPPER}/,+6d&#34; ${WORKDIR}/conf.d/serverwg.conf&#xA;                    echo -e &#34;terminata con successo.\n&#34;   &#xA;                fi&#xA;            done&#xA;        fi&#xA;    else&#xA;        echo &#34;È necessario inizializzare il server con &#39;wginit.sh init&#39;.&#34;&#xA;        echo &#34;L&#39;operazione richiesta non sarà completata&#34;&#xA;    fi&#xA;}&#xA;&#xA;rebuild() {&#xA;    if isinit; then&#xA;        # Rigenero il file di configurazione del server da serverwgraw.conf.&#xA;        echo -n &#34;Ripristino del file di configurazione del server... &#34;&#xA;        cat ${WORKDIR}/conf.d/serverwgraw.conf   ${WORKDIR}/conf.d/serverwg.conf&#xA;        echo &#34;fatto.&#34;&#xA;        &#xA;        # Per ogni file di configurazione client, aggiungo il relativo peer&#xA;        # nel file di configurazione serverwg.conf.&#xA;        for FILECONF in ${WORKDIR}/conf.d/client.conf; do&#xA;            CLIENTPUBLICKEY=$(grep &#34;PrivateKey&#34; ${FILECONF}|cut -d &#34; &#34; -f 3|tr -d &#34; &#34; | wg pubkey)&#xA;            CLIENTPSK=$(grep &#34;PresharedKey&#34; ${FILECONF}|cut -d &#34; &#34; -f 3|tr -d &#34; &#34;)&#xA;            CLIENTIPADDRESS=$(grep &#34;Address&#34; ${FILECONF}|cut -d &#34; &#34; -f 3|tr -d &#34; &#34;|cut -d &#34;/&#34; -f 1)&#xA;            CLIENTNAMEUPPER=$(grep &#34;#&#34; ${FILECONF} | cut -d &#34; &#34; -f 2)&#xA;            echo -n &#34;Aggiunta peer \&#34;$(echo ${CLIENTNAMEUPPER} | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;)\&#34;... &#34;&#xA;            addpeertoserver ${CLIENTPUBLICKEY} ${CLIENTPSK} ${CLIENTIPADDRESS} ${CLIENTNAMEUPPER}&#xA;            echo -e &#34;fatto.&#34;&#xA;        done&#xA;    else&#xA;        echo &#34;È necessario inizializzare il server con &#39;wginit.sh init&#39;.&#34;&#xA;        echo &#34;L&#39;operazione richiesta non sarà completata&#34;&#xA;    fi&#xA;}&#xA;&#xA;Avvia il server wireguard con la nuova configurazione&#xA;deploy() {&#xA;    if isinit; then&#xA;        echo -n &#34;Inserire la password di Amministratore: &#34;; read -s PASSWORD&#xA;        sudo -k&#xA;        if echo $PASSWORD|sudo -S echo &#34;got a root&#34;   /dev/null; then&#xA;   &#xA;            # Stoppo il servizio wireguard&#xA;            echo -ne &#34;\nStop wireguard... &#34;&#xA;            sudo systemctl stop wg-quick@${WGINTERFACE}&#xA;            echo &#34;fatto.&#34;&#xA;            &#xA;            # Aggiorno la configurazione&#xA;            echo -n &#34;Copia della nuova configurazione... &#34;&#xA;            sudo cp ${WORKDIR}/conf.d/serverwg.conf /etc/wireguard/${WGINTERFACE}&#xA;            echo &#34;fatto.&#34;&#xA;            &#xA;            # Riavvio il servizio wireguard&#xA;            echo -n &#34;Riavvio wireguard... &#34;&#xA;            sudo systemctl start wg-quick@${WGINTERFACE}&#xA;            echo &#34;fatto.&#34;&#xA;            &#xA;            # Revoco i privilegi di amministrazione&#xA;            sudo -k&#xA;        else&#xA;            echo &#34;Sono necessarie le credenziali di amministrazione per eseguire questo comando.&#34;&#xA;            exit 1&#xA;        fi&#xA;    else&#xA;        echo &#34;È necessario inizializzare il server con &#39;wginit.sh init&#39;.&#34;&#xA;        echo &#34;L&#39;operazione richiesta non sarà completata&#34;&#xA;    fi&#xA;}&#xA;&#xA;Crea il qr-code della configurazione del client nella cartella corrente.&#xA;share() {&#xA;    if isinit; then&#xA;        if [[ $# -lt 1 ]]; then&#xA;            echo -e &#34;Devi inserire almeno un nome.&#34;&#xA;            exit 1&#xA;        else&#xA;            for CLIENTNAME in &#34;$@&#34;; do&#xA;                echo -n &#34;Creazione qr-code per il client \&#34;${CLIENTNAME}\&#34;... &#34;&#xA;                qrencode -r ${WORKDIR}/conf.d/client${CLIENTNAME}.conf -o qrcodeclient${CLIENTNAME}.jpg&#xA;                echo &#34;fatto.&#34;&#xA;            done&#xA;        fi&#xA;    else&#xA;        echo &#34;È necessario inizializzare il server con &#39;wginit.sh init&#39;.&#34;&#xA;        echo &#34;L&#39;operazione richiesta non sarà completata&#34;&#xA;    fi&#xA;}&#xA;&#xA;help() {&#xA;&#xA;[[ $1 != &#34;&#34; &amp;&amp; $1 != &#34;help&#34; ]] &amp;&amp; echo -e &#34;Comando inesistente.&#34;&#xA;&#xA;    cat&lt;&lt;EOF&#xA;Usa come: ./wgman.sh [command] ARG&#xA;dove:&#xA;    [command]&#xA;        init                     : Inizializza la configurazione del server.&#xA;        addclient lista nomi   : Aggiunge i client indicati in lista nomi.&#xA;        removeclient lista nomi: Rimuove i client indicati in lista nomi.&#xA;        rebuild                  : Ricostruisce il file di configurazione&#xA;                                   del server partendo dalle configurazioni&#xA;                                   di tutti i client registrati.&#xA;        deploy                   : Riavvia il server wireguard con l&#39;ultima&#xA;                                   configurazione disponibile.&#xA;        share lista nomi       : Genera i qr-code relativi ai client indicati in lista nomi.&#xA;        help                     : Stampa questa pagina di help.&#xA;&#xA;ESEMPI:&#xA;    INiZIALIZZA IL SERVER WIREGUARD&#xA;    wgman.sh init&#xA;&#xA;    AGGIUNGE I CLIENT &#39;macbookpro&#39;, &#39;mobile&#39;&#xA;    wgman.sh addclient macbookpro mobile&#xA;&#xA;    RIMUOVE I CLIENT &#39;iphoneluca&#39;, &#39;workstation&#39;&#xA;    wgman.sh removeclient iphoneluca workstation&#xA;&#xA;    RICOSTRUISCE LA CONFIGURAZIONE DEL SERVER WIREGUARD&#xA;    wgman.sh rebuild&#xA;    &#xA;    ATTIVA LA NUOVA CONFIGURAZIONE&#xA;    wgman.sh deploy&#xA;&#xA;    GENERA I QRCODE PER &#39;pcufficio&#39;, &#39;laptop&#39;&#xA;    wgman.sh share pcufficio laptop&#xA;EOF&#xA;}&#xA;&#xA;main() {&#xA;    case $1 in&#xA;        init         ) init ;;&#xA;        addclient    ) shift; addclient &#34;$@&#34; ;;&#xA;        removeclient ) shift; removeclient &#34;$@&#34; ;;&#xA;        rebuild      ) rebuild ;;&#xA;        deploy       ) deploy ;;&#xA;        share        ) shift; share &#34;$@&#34; ;;&#xA;        ) help ;;&#xA;    esac&#xA;}&#xA;&#xA;check_dependency&#xA;case $? in&#xA;    &#34;0&#34; ) main $* ;;&#xA;    &#34;1&#34; ) echo -e &#34;UFW non presente. Installare UFW.&#34;; exit 1 ;;&#xA;    &#34;2&#34; ) echo -e &#34;wireguard-tools non presenti. È necessario installarli.&#34;; exit 1 ;;&#xA;esac&#xA;&#xA;#bash #wireguard #psk #chiavi #certificati #crittografia&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/586f75268-5004eb/XBn3L6jB84Ka/b6zYDZWzIcLbax1taLgBnIQu8hoy7ZeZVlXBkGf0.png" alt="vpn"></p>

<p><a href="https://noblogo.org/aytin/vpn-con-wireguard-semplice-e-veloce" rel="nofollow">Cos&#39;è wireguard e come si configura</a>, lo sappiamo ma mi serviva qualcosa che mi permettesse di fare provisioning e deprovisioning dei certificati in maniera più semplice di quanto già si faccia con i tool disponibili nella userland, wg e wg-quick.</p>

<p>E questo è il motivo principale per cui è nato questo script.

Prende come riferimento una configurazione road warrior, <a href="https://noblogo.org/aytin/vpn-con-wireguard-semplice-e-veloce#primo-scenario" rel="nofollow">il primo scenario di una topologia point-to-site</a>, quella più comune.</p>

<h2 id="alcune-considerazioni">Alcune considerazioni</h2>
<ol><li><p>Lo script definisce una workdir dove deposita tutte le configurazioni e i certificati.
Le precondizioni sono legate alla presenza dei tool userland <strong>wg-tools</strong> (ovviamente) e di <strong>ufw</strong>. Vengono comunque verificate nello script.</p></li>

<li><p>Altra semplificazione è data dal fatto di allocare una /24 come rete wireguard. 254 host per una rete domestica sono più che sufficienti.</p></li>

<li><p>L&#39;allocazione degli ip viene fatta con un progressivo memorizzato nel file &#39;ip_renew&#39;. Gli ip dei certificati revocati vengono mantenuti in un file, &#39;ip_release&#39;.
Quando si crea un nuovo certificato, si controlla prima che ci sia un ip da recuperare in ip_release. Se la lista è vuota si ricorre al progressivo.</p></li>

<li><p>La creazione della configurazione lato server passa da due file di configurazione: una configurazione <strong>globale</strong> ottenuta tracciando l&#39;evoluzione iniziale in termini di aggiunta o rimozione dei client peer e destinata al rilascio in esecuzione. L&#39;altra contenente <strong>la sola configurazione del server</strong> e usata unicamente per la rigenerazione della configurazione globale a partire dai peer esistenti.</p></li>

<li><p>L&#39;operazione di <strong>init</strong> è propedeutica per <strong>addclient</strong>, <strong>removeclient</strong>, <strong>rebuild</strong>, <strong>deploy</strong>, <strong>share</strong>.</p></li></ol>

<p>Le operazioni a disposizione sono:</p>
<ul><li><strong>init:</strong> inizializza la configurazione di un server wireguard</li>
<li><strong>addclient:</strong> crea il certificato lato client e aggiunge il relativo peer sulla configurazione del server</li>
<li><strong>removeclient:</strong> cancella il certificato lato client e rimuove il relativo peer sulla configurazione del server</li>
<li><strong>rebuild:</strong> rigenera la configurazione del server usando i certificati client esistenti</li>
<li><strong>deploy:</strong> finalizza la configurazione riavviando il servizio con le nuove impostazioni</li>
<li><strong>share:</strong> crea i qr-code per i certificati client da utilizzare nelle configurazioni</li></ul>

<p>Per tutto il resto, i commenti nel codice sono abbastanza esplicativi.</p>

<h2 id="lo-script">Lo script</h2>

<pre><code class="language-bash">#!/bin/bash

# Questo è il file di configurazione globale, i dati sono fittizi.
# Può essere mantenuto nello script o nella home dell&#39;utente 
# (es. $HOME/.config/wg_man.conf) e importato 
# con &#39;source&#39; all&#39;inizio.
WG_INTERFACE=wg0
PHYSICAL_INTERFACE=eth0
NETWORK=&#34;192.168.15.0&#34;
SUBNET_MASK=&#34;24&#34;
SERVER_IP_ADDRESS=&#34;192.168.15.1&#34;
DNS=&#34;1.1.1.1&#34;
LISTEN_PORT=&#34;51820&#34;
ENDPOINT=wireguard.nodns.net:51820&#34;
WORKDIR=&#34;$HOME/wireguard&#34;



check_dependency() {
    if test -e /usr/sbin/ufw; then
        if test -e /usr/bin/wg; then
            return 0
        else
            return 2
        fi
    else
        return 1
    fi
}



is_init() {
    test -e ${WORKDIR}/conf.d/server_wg.conf &amp;&amp; return 0 || return 1
}



# Genera la chiave privata
gen_priv_key() {
    wg genkey | tee ${WORKDIR}/keys/$1_privkey
}



# Genera la pre-shared key
gen_client_psk() {
    # Evita il warning sui permessi del file che devono essere 600
    umask 077
    wg genpsk | tee ${WORKDIR}/psk/$1_psk
}



# Rilascio di un nuovo indirizzo ip. Questa funziona viene invocata da
# addclient().
#
# I primi 3 ottetti li ottengo dalla variabile globale NETWORK.
# L&#39;ultimo ottetto, relativo all&#39;host, lo ricavo dalla lista degli ip
# riutilizzabili (&#34;ip_release&#34;).
#
# Se non è vuota, prelevo il primo e lo rimuovo dalla lista. Se è vuota,
# prelevo l&#39;ultimo ottetto da &#34;ip_renew&#34; e lo incremento per il successivo
# assegnamento.
ip_renew() {
    # Selezioni i primi 3 ottetti del network
    SUB_IP=$(echo ${NETWORK}|awk -F &#34;.&#34; &#39;{print $1&#34;.&#34;$2&#34;.&#34;$3}&#39;)

    if [[ ! -e ${WORKDIR}/conf.d/ip_release || ! -s ${WORKDIR}/conf.d/ip_release ]]; then
        # Genero il nuovo ip (Incremento di 1 l&#39;ultimo ottetto)
        IP=$(cat ${WORKDIR}/conf.d/ip_renew)
        echo $((++IP)) &gt; ${WORKDIR}/conf.d/ip_renew

        # Restituisco i 3 ottetti + il quarto
        #echo -n ${SUB_IP};cat ${WORKDIR}/conf.d/ip_renew
    else
        IP=$(head -n 1 ${WORKDIR}/conf.d/ip_release)
        sed -i &#34;1d&#34; ${WORKDIR}/conf.d/ip_release
    fi
    echo -n ${SUB_IP}&#34;.&#34;${IP}
}



# Riallocazione di un indirizzo ip. Questa funzione viene invocata da
# removeclient().
# Aggiungo l&#39;ultimo ottetto alla lista degli ip riallocabili.
# @par 1: ultimo ottetto.
ip_release() {
    echo $1|cut -d&#34;.&#34; -f 4 &gt;&gt; ${WORKDIR}/conf.d/ip_release
}



# Aggiunge il nuovo peer al file di configurazione del server
# @par 1: CLIENT_PUBLIC_KEY
# @par 2: CLIENT_PSK
# @par 3: CLIENT_IP_ADDRESS
# @par 4: CLIENT_NAME
add_peer_to_server() {
    cat &gt;&gt; ${WORKDIR}/conf.d/server_wg.conf &lt;&lt; EOF
# $4
[Peer]
PublicKey = $1
PresharedKey = $2
AllowedIPs = $3/32
PersistentKeepalive = 25

EOF
}



# Inizializza la configurazione del server wireguard.
#
# Questa operazione può essere fatta una sola volta a meno che non si
# cancelli tutta la workdir.
#
# Verranno creati due file  di configurazione: server_wg.conf e 
# server_wg_raw.conf
#
# Il primo conterrà la configurazione completa del server e dei peer,
# verrà aggiornato ad ogni modifica dei client (aggiunta o rimozione) e
# verrà usato per il deploy della configurazione.
#
# Il secondo conterrà la configurazione del solo server e verrà usato
# solo per rigenerare il primo file di configurazione.
init() {
    # Controllo che wireguard sia almeno abilitato
    echo -n &#34;Inserire la password di Amministratore: &#34;; read -s PASSWORD
    sudo -k
    if echo $PASSWORD|sudo -S echo &#34;got a root&#34; &gt; /dev/null; then
        if ! sudo systemctl is-enabled --quiet wg-quick@${WG_INTERFACE}; then
            echo -en &#34;\nAttivazione servizio wireguard... &#34;
            #sudo systemctl enable --quiet wg-quick@${WG_INTERFACE}
            echo &#34;fatto.&#34;
        fi
        sudo -k 
        
        #Verifico che queste cartelle esistano. Se lo sono, non faccio nulla, se no le creo.
        echo -n &#34;Creazione workdir... &#34;
        [[ ! -e ${WORKDIR}/conf.d || ! -e ${WORKDIR}/psk  || ! -e ${WORKDIR}/keys ]] \
            &amp;&amp; { mkdir -p ${WORKDIR}/{conf.d,keys,psk}; } \
            || { echo &#34;inizializzazione già effettuata.&#34;; exit; }
        echo &#34;fatto.&#34;
        
        # Genero la chiave privata per il server
        echo -n &#34;Creazione chiave private del server...&#34;
        SERVER_PRIV_KEY=$(gen_priv_key &#34;server_wg&#34;)
        echo &#34;fatto.&#34;

        # Genero il file di configurazione
        echo -n &#34;Inizializzazione del server... &#34;
        cat &gt; ${WORKDIR}/conf.d/server_wg.conf &lt;&lt; EOF
[Interface]
Address = ${SERVER_IP_ADDRESS}/${SUBNET_MASK}
# SaveConfig = true

PreUp = ufw route allow in on ${WG_INTERFACE} out on ${PHYSICAL_INTERFACE} log from ${NETWORK}/${SUBNET_MASK} to 0.0.0.0/0
PostDown = ufw route delete allow in on ${WG_INTERFACE} out on ${PHYSICAL_INTERFACE} log from ${NETWORK}/${SUBNET_MASK} to 0.0.0.0/0

# IP masquerading
PreUp = iptables -t nat -A POSTROUTING -o ${PHYSICAL_INTERFACE} -s ${NETWORK}/${SUBNET_MASK} -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o ${PHYSICAL_INTERFACE} -s ${NETWORK}/${SUBNET_MASK} -j MASQUERADE

# IP filtering
PreUp = ufw allow in on ${PHYSICAL_INTERFACE} log to 0.0.0.0/0 app Wireguard
PostDown = ufw delete allow in on ${PHYSICAL_INTERFACE} log to 0.0.0.0/0 app Wireguard

ListenPort = ${LISTEN_PORT}
PrivateKey = ${SERVER_PRIV_KEY}

EOF
        echo &#34;fatto.&#34;
        cp ${WORKDIR}/conf.d/server_wg.conf ${WORKDIR}/conf.d/server_wg_raw.conf
        # Inizializza l&#39;erogatore di ip
        echo 1 &gt; ${WORKDIR}/conf.d/ip_renew
    else
        echo &#34;Sono necessarie le credenziali di amministrazione per eseguire questo comando.&#34;
        exit 1
    fi
}



# Genera un certificato per il client composto da:
# * chiave privata del client
# * chiave pre-condivisa
# * client ip
# * chiave pubblica del server
# * nome simbolico del client
#
# Dopo la creazione e il salvataggio in &lt;WORKDIR&gt;/conf.d, verrà aggiunto
# il relativo peer nella configurazione del server (server_wg.conf).
# @par_1 @par_2 @par_3...: lista di nomi relativi ai certificati da creare.
add_client() {
    if is_init; then
        # Se non c&#39;è alcun input, esco.
        if [[ $# -lt 1 ]]; then
            echo -e &#34;Devi inserire almeno un nome.&#34;
            exit 1
        else
            # Per ogni nome presente in input, creo una configurazione 
            # client e l&#39;aggiungo alla configurazione del server.
            for CLIENT_NAME in &#34;$@&#34;; do
                echo -n &#34;Creazione certificato per il client \&#34;${CLIENT_NAME}\&#34;... &#34;
                
                # Controllo se la configurazione esista già discriminando
                # in base al nome del file.
                if [[ -e ${WORKDIR}/conf.d/client_${CLIENT_NAME}.conf ]]; then
                    echo &#34;già esistente.&#34;
                else
                    # Creo la configurazione del client
                    CLIENT_PRIV_KEY=$(gen_priv_key ${CLIENT_NAME})
                    CLIENT_PUBLIC_KEY=$(echo ${CLIENT_PRIV_KEY} | wg pubkey)
                    CLIENT_PSK=$(gen_client_psk ${CLIENT_NAME})
                    CLIENT_IP_ADDRESS=$(ip_renew)
                    SERVER_PUBLIC_KEY=$(grep PrivateKey ${WORKDIR}/conf.d/server_wg.conf | cut -d &#34; &#34; -f 3 | tr -d &#34; &#34; | wg pubkey)
                    CLIENT_NAME_UPPER=$(echo ${CLIENT_NAME} | tr &#39;[:lower:]&#39; &#39;[:upper:]&#39;)
                    cat &gt; ${WORKDIR}/conf.d/client_${CLIENT_NAME}.conf &lt;&lt; EOF
    # ${CLIENT_NAME_UPPER}
    [Interface]
    Address = ${CLIENT_IP_ADDRESS}/${SUBNET_MASK}
    DNS = ${DNS}
    PrivateKey = ${CLIENT_PRIV_KEY}

    [Peer]
    PublicKey = ${SERVER_PUBLIC_KEY}
    PresharedKey = ${CLIENT_PSK}
    AllowedIPs = 0.0.0.0/0
    Endpoint = ${ENDPOINT}
    PersistentKeepalive = 25
EOF
                    echo &#34;fatto.&#34;
                    echo -n &#34;Aggiunta peer \&#34;${CLIENT_NAME}\&#34; al file di configurazione del server... &#34;
                    
                    # Aggiungo il peer alla configurazione del server.
                    add_peer_to_server ${CLIENT_PUBLIC_KEY} ${CLIENT_PSK} ${CLIENT_IP_ADDRESS} ${CLIENT_NAME_UPPER}
                    echo -e &#34;fatto.\n&#34;                
                fi
            done
        fi
    else
        echo &#34;È necessario inizializzare il server con &#39;wg_init.sh init&#39;.&#34;
        echo &#34;L&#39;operazione richiesta non sarà completata&#34;
    fi
}



# Rimuove file di configurazioni, chiavi e pre-shared key realtive a file
# dati in input.
# Rimuove inoltre il peer dal file di configurazione server_wg.conf.
# @par_1 @par_2 @par_3...: lista di nomi relativi ai certificati da rimuovere.
remove_client() {
    if is_init; then
        if [[ $# -lt 1 ]]; then
            echo -e &#34;Devi inserire almeno un nome.&#34;
            exit 1
        else
            for CLIENT_NAME in &#34;$@&#34;; do
                echo -n &#34;Rimozione client \&#34;${CLIENT_NAME}\&#34;... &#34;
                if [[ ! -e ${WORKDIR}/conf.d/client_${CLIENT_NAME}.conf ]]; then
                    echo &#34;non esistente.&#34;
                else
                    # Estraggo l&#39;ultimo ottetto dell&#39;ip del client.
                    IP=$(grep &#34;Address&#34; ${WORKDIR}/conf.d/client_${CLIENT_NAME}.conf|cut -d &#34; &#34; -f 3|tr -d &#34; &#34;|cut -d &#34;/&#34; -f 1)
                    
                    # Lo inserisco nella lista degli ip riallocabili.
                    ip_release ${IP}
                    
                    # Cancello file di configurazione, chiave e psk del client.
                    rm ${WORKDIR}/conf.d/client_${CLIENT_NAME}.conf ${WORKDIR}/keys/${CLIENT_NAME}_privkey ${WORKDIR}/psk/${CLIENT_NAME}_psk
                    echo &#34;terminata con successo.&#34;
                    echo -n &#34;Rimozione peer \&#34;${CLIENT_NAME}\&#34; dal file di configurazione del server... &#34;
                    
                    # Rimuovo il peer dalla configurazione del server.
                    CLIENT_NAME_UPPER=$(echo ${CLIENT_NAME} | tr &#39;[:lower:]&#39; &#39;[:upper:]&#39;)
                    sed -i &#34;/# ${CLIENT_NAME_UPPER}/,+6d&#34; ${WORKDIR}/conf.d/server_wg.conf
                    echo -e &#34;terminata con successo.\n&#34;   
                fi
            done
        fi
    else
        echo &#34;È necessario inizializzare il server con &#39;wg_init.sh init&#39;.&#34;
        echo &#34;L&#39;operazione richiesta non sarà completata&#34;
    fi
}



rebuild() {
    if is_init; then
        # Rigenero il file di configurazione del server da server_wg_raw.conf.
        echo -n &#34;Ripristino del file di configurazione del server... &#34;
        cat ${WORKDIR}/conf.d/server_wg_raw.conf &gt; ${WORKDIR}/conf.d/server_wg.conf
        echo &#34;fatto.&#34;
        
        # Per ogni file di configurazione client, aggiungo il relativo peer
        # nel file di configurazione server_wg.conf.
        for FILE_CONF in ${WORKDIR}/conf.d/client_*.conf; do
            CLIENT_PUBLIC_KEY=$(grep &#34;PrivateKey&#34; ${FILE_CONF}|cut -d &#34; &#34; -f 3|tr -d &#34; &#34; | wg pubkey)
            CLIENT_PSK=$(grep &#34;PresharedKey&#34; ${FILE_CONF}|cut -d &#34; &#34; -f 3|tr -d &#34; &#34;)
            CLIENT_IP_ADDRESS=$(grep &#34;Address&#34; ${FILE_CONF}|cut -d &#34; &#34; -f 3|tr -d &#34; &#34;|cut -d &#34;/&#34; -f 1)
            CLIENT_NAME_UPPER=$(grep &#34;#&#34; ${FILE_CONF} | cut -d &#34; &#34; -f 2)
            echo -n &#34;Aggiunta peer \&#34;$(echo ${CLIENT_NAME_UPPER} | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;)\&#34;... &#34;
            add_peer_to_server ${CLIENT_PUBLIC_KEY} ${CLIENT_PSK} ${CLIENT_IP_ADDRESS} ${CLIENT_NAME_UPPER}
            echo -e &#34;fatto.&#34;
        done
    else
        echo &#34;È necessario inizializzare il server con &#39;wg_init.sh init&#39;.&#34;
        echo &#34;L&#39;operazione richiesta non sarà completata&#34;
    fi
}



# Avvia il server wireguard con la nuova configurazione
deploy() {
    if is_init; then
        echo -n &#34;Inserire la password di Amministratore: &#34;; read -s PASSWORD
        sudo -k
        if echo $PASSWORD|sudo -S echo &#34;got a root&#34; &gt; /dev/null; then
   
            # Stoppo il servizio wireguard
            echo -ne &#34;\nStop wireguard... &#34;
            sudo systemctl stop wg-quick@${WG_INTERFACE}
            echo &#34;fatto.&#34;
            
            # Aggiorno la configurazione
            echo -n &#34;Copia della nuova configurazione... &#34;
            sudo cp ${WORKDIR}/conf.d/server_wg.conf /etc/wireguard/${WG_INTERFACE}
            echo &#34;fatto.&#34;
            
            # Riavvio il servizio wireguard
            echo -n &#34;Riavvio wireguard... &#34;
            sudo systemctl start wg-quick@${WG_INTERFACE}
            echo &#34;fatto.&#34;
            
            # Revoco i privilegi di amministrazione
            sudo -k
        else
            echo &#34;Sono necessarie le credenziali di amministrazione per eseguire questo comando.&#34;
            exit 1
        fi
    else
        echo &#34;È necessario inizializzare il server con &#39;wg_init.sh init&#39;.&#34;
        echo &#34;L&#39;operazione richiesta non sarà completata&#34;
    fi
}



# Crea il qr-code della configurazione del client nella cartella corrente.
share() {
    if is_init; then
        if [[ $# -lt 1 ]]; then
            echo -e &#34;Devi inserire almeno un nome.&#34;
            exit 1
        else
            for CLIENT_NAME in &#34;$@&#34;; do
                echo -n &#34;Creazione qr-code per il client \&#34;${CLIENT_NAME}\&#34;... &#34;
                qrencode -r ${WORKDIR}/conf.d/client_${CLIENT_NAME}.conf -o qrcode_client_${CLIENT_NAME}.jpg
                echo &#34;fatto.&#34;
            done
        fi
    else
        echo &#34;È necessario inizializzare il server con &#39;wg_init.sh init&#39;.&#34;
        echo &#34;L&#39;operazione richiesta non sarà completata&#34;
    fi
}



help() {

[[ $1 != &#34;&#34; &amp;&amp; $1 != &#34;help&#34; ]] &amp;&amp; echo -e &#34;Comando inesistente.&#34;

    cat&lt;&lt;EOF
Usa come: ./wg_man.sh [command] ARG
dove:
    [command]
        init                     : Inizializza la configurazione del server.
        addclient &lt;lista nomi&gt;   : Aggiunge i client indicati in &lt;lista nomi&gt;.
        removeclient &lt;lista nomi&gt;: Rimuove i client indicati in &lt;lista nomi&gt;.
        rebuild                  : Ricostruisce il file di configurazione
                                   del server partendo dalle configurazioni
                                   di tutti i client registrati.
        deploy                   : Riavvia il server wireguard con l&#39;ultima
                                   configurazione disponibile.
        share &lt;lista nomi&gt;       : Genera i qr-code relativi ai client indicati in &lt;lista nomi&gt;.
        help                     : Stampa questa pagina di help.

ESEMPI:
    INiZIALIZZA IL SERVER WIREGUARD
    wg_man.sh init

    AGGIUNGE I CLIENT &#39;macbook_pro&#39;, &#39;mobile&#39;
    wg_man.sh addclient macbook_pro mobile

    RIMUOVE I CLIENT &#39;iphone_luca&#39;, &#39;workstation&#39;
    wg_man.sh removeclient iphone_luca workstation

    RICOSTRUISCE LA CONFIGURAZIONE DEL SERVER WIREGUARD
    wg_man.sh rebuild
    
    ATTIVA LA NUOVA CONFIGURAZIONE
    wg_man.sh deploy

    GENERA I QRCODE PER &#39;pc_ufficio&#39;, &#39;laptop&#39;
    wg_man.sh share pc_ufficio laptop
EOF
}



main() {
    case $1 in
        init         ) init ;;
        addclient    ) shift; add_client &#34;$@&#34; ;;
        removeclient ) shift; remove_client &#34;$@&#34; ;;
        rebuild      ) rebuild ;;
        deploy       ) deploy ;;
        share        ) shift; share &#34;$@&#34; ;;
        *            ) help ;;
    esac
}



check_dependency
case $? in
    &#34;0&#34; ) main $* ;;
    &#34;1&#34; ) echo -e &#34;UFW non presente. Installare UFW.&#34;; exit 1 ;;
    &#34;2&#34; ) echo -e &#34;wireguard-tools non presenti. È necessario installarli.&#34;; exit 1 ;;
esac
</code></pre>

<p><a href="/aytin/tag:bash" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">bash</span></a> <a href="/aytin/tag:wireguard" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">wireguard</span></a> <a href="/aytin/tag:psk" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">psk</span></a> <a href="/aytin/tag:chiavi" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">chiavi</span></a> <a href="/aytin/tag:certificati" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">certificati</span></a> <a href="/aytin/tag:crittografia" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">crittografia</span></a></p>
]]></content:encoded>
      <guid>https://noblogo.org/aytin/script-per-la-gestione-della-configurazione-di-una-vpn-wireguard</guid>
      <pubDate>Sun, 22 Sep 2024 13:27:09 +0000</pubDate>
    </item>
    <item>
      <title>VPN con Wireguard: semplice e veloce</title>
      <link>https://noblogo.org/aytin/vpn-con-wireguard-semplice-e-veloce</link>
      <description>&lt;![CDATA[vpn&#xA;smalliFonte:  Photo by Stefan Coders on a href=&#34;https://www.pexels.com/it-it/foto/uomo-persone-donna-apple-5243610/&#34;Pexels.com/a/i/small&#xA;&#xA;a id=&#34;perche-wireguard&#34;Perché wireguard?/a&#xA;&#xA;È più semplice di OpenVPN.&#xA;Fa parte del kernel dalla versione 5.6 in poi (ci sono anche versioni in userspaces). Vanno installati solo i software di gestione del tunnel&#xA;Si basa su uno strato di crittografia all&#39;avanguardia per quel che riguarda efficienza e robustezza&#xA;Il suo codice, estremamente compatto, viene revisionato con molta più facilità.&#xA;Non si basa su un modello client-server ma P2P&#xA;Il traffico è UDP piuttosto che TCP (ci sono modi per fare un wrapping TCP delle connessioni UDP)&#xA;&#xA;!--more--&#xA;&#xA;a href=&#34;#perche-wireguard&#34;Perché wireguard?/a&#xA;a href=&#34;#crittografia-di-wireguard&#34;Crittografia di Wireguard/a&#xA;a href=&#34;#un-po-di-teoria&#34;Un po&#39; di teoria/a&#xA;a href=&#34;#installazione&#34;Installazione/a&#xA;   a href=&#34;#generazione-chiavi&#34;Generazione chiavi/a&#xA;a href=&#34;#attivazione-nodo&#34;Attivazione del nodo/a&#xA;   a href=&#34;#pc-laptop&#34;PC/Laptop/a&#xA;   a href=&#34;#mobile&#34;Mobile/a&#xA;a href=&#34;#debug&#34;Debug/a&#xA;a href=&#34;#topologie&#34;Topologie/a&#xA;a href=&#34;#point-to-site&#34;Point-To-Site/a&#xA;   a href=&#34;#primo-scenario&#34;Primo scenario/a&#xA;      a href=&#34;#pts-configurazione-wireguard-endpoint-a&#34;Configurazione wireguard Endpoint A/a&#xA;      a href=&#34;#pts-configurazione-wireguard-host-b&#34;Configurazione wireguard Host B/a&#xA;      a href=&#34;#pts-configurazione-routing-filtering-host-b&#34;Configurazione routing/filtering Host B/a&#xA;      a href=&#34;#pts-test&#34;Test/a&#xA;      a href=&#34;#pts-tips&#34;Tips/a&#xA;   a href=&#34;#secondo-scenario&#34;Secondo scenario/a&#xA;      a href=&#34;#stp-configurazione-wireguard-endpoint-a&#34;Configurazione wireguard Endpoint A/a&#xA;      a href=&#34;#stp-configurazione-wireguard-host-b&#34;Configurazione wireguard Host B/a&#xA;      a href=&#34;#stp-configurazione-routing-filtering-host-b&#34;Configurazione routing/filtering Host B/a&#xA;      a href=&#34;#stp-test&#34;Test/a&#xA;      a href=&#34;#stp-tips&#34;Tips/a&#xA;   a href=&#34;#terzo-scenario&#34;Terzo scenario/a&#xA;      a href=&#34;#gtw-configurazione-routing-filtering-host-b&#34;Configurazione routing/filtering Host B/a&#xA;      a href=&#34;#gtw-configurazione-gateway-host-sito-b&#34;Configurazione gateway Sito B/a&#xA;      a href=&#34;#gtw-test&#34;Test/a&#xA;      a href=&#34;#gtw-tips&#34;Tips/a&#xA;   a href=&#34;#differenze-3-approcci&#34;Differenze fra i 3 approcci/a&#xA;&#xA;a id=&#34;crittografia-di-wireguard&#34;Crittografia di Wireguard/a&#xA;&#xA;Le primitive crittografiche di Wireguard si basano su:&#xA;&#xA;Curve25519, per autenticazione e key exchange (ECDH)&#xA;ChaCha20 e Poly1305, per la cifratura simmetrica con autenticazione (AEAD)&#xA;BLAKE2, come hash crittografico&#xA;SipHash-2-4, come funzione di hash crittografico con chiave (tipo HMAC)&#xA;HKDF, come funzione di derivazione della chiave basata su HMAC&#xA;Noise Framework, è un protocollo crittografico. Stabilisce il modo con cui tutte queste operazioni crittografiche vengono fatte lavorare.&#xA;&#xA;a id=&#34;un-po-di-teoria&#34;Un po&#39; di teoria/a&#xA;&#xA;Wireguard implementa una vpn L3 solo tunneling, incapsulando pacchetti IP all&#39;interno di pacchetti UDP per il trasporto. Ciò implica che funzioni come dhcp, essendo L2, non possono trovare spazio all&#39;interno di wireguard, ergo l&#39;indirizzamento (ip, subnet, dns) deve essere fatto staticamente.&#xA;&#xA;Avendo un&#39;anima P2P, ogni nodo (peer) wireguard è sia client che server. Ciò permette di realizzare topologie anche piuttosto complesse con uno sforzo relativamente ridotto.&#xA;&#xA;Un peer wireguard è composto da due tipi di sezioni:&#xA;&#xA;una sezione &#34;interface&#34;, relativa al peer stesso, contenente:&#xA;  il proprio IP, nello spazio di indirizzamento privato usato dalla vpn.&#xA;  una porta, su cui il peer può essere in ascolto per accettare richieste da altri nodi wireguard&#xA;  la parte privata della chiave asimmetrica con cui decifra e autentica&#xA;una o più sezioni &#34;peer&#34;, relative ai nodi a cui può connettersi, contenenti:&#xA;  la parte pubblica della chiave asimmetrica del peer, con cui cifra e verifica&#xA;  AllowedIPs, che descrive l&#39;ip o le reti da ruotare nel tunnel, a cui è consentito il traffico in entrata e a cui è diretto il traffico in uscita&#xA;  l&#39;endpoint del peer, necessario solo se altri peer devono avviare connessioni verso di lui&#xA;&#xA;I nodi si autenticano a vicenda scambiandosi e convalidando le chiavi pubbliche. Ogni chiave pubblica è associata all&#39;IP di un peer.&#xA;&#xA;Quando un peer deve inviare dei pacchetti, AllowedIPs si comporta come una tabella di instradamento. Il peer esamina l&#39;IP di destinazione di quel pacchetto e lo cerca negli AllowedIPs dei suoi peer per capire a chi inviarlo. Se lo trova, ruota il pacchetto nel tunnel, altrimenti no.&#xA;&#xA;Quando si ricevono pacchetti, AllowedIPs si comporta come una lista di controllo degli accessi. Il peer esamina l&#39;IP di origine e se rientra nell&#39;AllowedIPs di uno dei suoi peer, accetterà il pacchetto altrimenti lo scarterà.&#xA;&#xA;Per esperienza personale, il 99% degli errori di configurazione su wireguard viene fatto proprio sul campo AllowedIPs perché non se ne comprende bene il funzionamento.&#xA;&#xA;Uno degli errori più comuni è quello di definire dei peer in cui gli ip contenuti nei campi AllowedIPs si sovrappongono. In base al funzionamento di wireguard infatti, non posso avere chiavi pubbliche diverse per uno stesso ip perché il peer, pur essendo in grado di ricevere pacchetti, non riuscirebbe a inviarli, non sapendo come ruotarli dovendo scegliere fra più peer.&#xA;a id=&#34;installazione&#34;Installazione/a&#xA;&#xA;Come già detto, wireguard è presente di base nel kernel linux. Bisogna installare solo gli strumenti di interfacciamento per la configurazione su ogni host.&#xA;&#xA;Per sistemi debian-based:&#xA;apt install wireguard wireguard-tools&#xA;a id=&#34;generazione-chiavi&#34;Generazione chiavi/a&#xA;Per semplicità, suppongo di generare tutte le chiavi che mi occorrono, del server (host B) e del client (Endpoint A) in questo caso. Oltre alle chiavi, userò anche una pre-shared key per il client. Non è obbligatorio ma mi costa zero e aumenta la resistenza post-quantistica.&#xA;&#xA;server&#xA;wg genkey   serverwg.key&#xA;wg pubkey  serverwg.key  serverwg.pub&#xA;&#xA;client&#xA;wg genkey   endpoint-awg.key&#xA;wg pubkey  endpoint-awg.key  endpoint-awg.pub&#xA;&#xA;Creazione psk&#xA;wg genpsk   endpoint-a.psk&#xA;a id=&#34;attivazione-nodo&#34;Attivazione del nodo/a&#xA;&#xA;Una volta che la configurazione del nodo è pronta, va attivato il servizio se ci troviamo su un pc. Altrimenti bisognerà importare la configurazione sul device.&#xA;a id=&#34;pc-laptop&#34;PC/Laptop/a&#xA;&#xA;Sia esso un client o un server, una volta configurato il peer, salva il file file sotto /etc/wireguard/ col nome dell&#39;interfaccia virtuale che hai scelto, nel mio caso, wg0.conf&#xA;&#xA;Attivazione/Disattivazione vpn on-demand:&#xA;wg-quick up wg0 #attiva la vpn&#xA;wg-quick down wg0 #disattiva la vpn&#xA;Attivazione/Disattivazione vpn come servizio:&#xA;systemctl enable wg-quick@wg0&#xA;systemctl start/stop wg-quick@wg0.service&#xA;a id=&#34;mobile&#34;Mobile/a&#xA;&#xA;Se il provisioning delle configurazioni si fa attraverso un pc, per portare facilmente la configurazione su un device mobile, si può generare un qrcode del file (supponiamo sia mobile.conf) e importarlo.&#xA;Installazione qrencode (debian-based)&#xA;apt install qrencode&#xA;&#xA;Crea il qr-code e dallo in pasto a al client&#xA;qrencode -t ansiutf8 &lt; mobile.conf&#xA;a id=&#34;debug&#34;Debug/a&#xA;&#xA;Wireguard è un modulo del kernel e quindi la sua attività viene raccolta dai log del kernel (/var/log/kern.log o /var/log/messages).&#xA;&#xA;Bisogna verificare che sul kernel si possa abilitare il dynamicdebugcontrol, controllando se è presente:&#xA;ls /sys/kernel/debug/dynamicdebug&#xA;Se lo è, si carica il modulo, si setta il dynamic debug e si potrà esaminare log del kernel ad es. con journalctl -fk&#xA;modprobe wireguard&#xA;echo module wireguard +p | sudo tee /sys/kernel/debug/dynamicdebug/control&#xA;Potresti dover installare resolvconf sul server.&#xA;&#xA;Quando wireguard fa salire l&#39;interfaccia, la registra su systemd-resolve attraverso resolvconf e se non è installato potrebbe verificarsi un malfunzionamento.&#xA;a id=&#34;topologie&#34;Topologie/a&#xA;&#xA;Le principali topologie che possono essere realizzate con wireguard sono:&#xA;&#xA;point-to-point&#xA;point-to-site&#xA;site-to-site&#xA;hub-and-spoke (a stella)&#xA;&#xA;Il canale sicuro fra i nodi wireguard viene creato attraverso le primitive crittografiche di cui sopra, ogni peer viene identificato da una chiave asimmetrica.&#xA;&#xA;Non è necessario approfondire la parte di crittografia per capire come configurare wireguard. Ci fidiamo che faccia un buon lavoro.&#xA;&#xA;Ciò su cui invece vale la pena soffermarsi, è la parte di instradamento, essenziale per l&#39;implementazione delle topologie di cui sopra.&#xA;&#xA;Io mi soffermerò sulla topologia più comune, point-to-site, che permette di unire un endpoint che esegue wireguard, con un altro endpoint situato all&#39;interno di una LAN in cui c&#39;è un host wireguard.&#xA;&#xA;easy-point-to-site&#xA;&#xA;Tanto per fissare le idee indicherò:&#xA;&#xA;col termine peer, uno dei punti logici di una vpn wireguard&#xA;col termine endpoint, uno dei punti di arrivo della tratta interessata dal tunnel vpn&#xA;col termine host wireguard, l&#39;host che esegue wireguard.&#xA;&#xA;Osservazioni banali:&#xA;In una topologia point-to-point, host wireguard ed endpoint coincidono su entrambi gli estremi della tratta.&#xA;In una topologia point-to-site, host wireguard ed endpoint coincidono solo sul &#34;point&#34; (l&#39;altro endpoint è dietro ad un host wireguard).&#xA;In una topologia site-to-site, gli endpoint sono sempre dietro gli host wireguard.&#xA;a id=&#34;point-to-site&#34;Point-To-Site/a&#xA;&#xA;Avrò un Sito A che comprende il solo endpoint dove non ho la possibilità di gestire routing e filtering e un Sito B dove, al contrario, potrò impostare le mie policy di instradamento e filtraggio e dove sarà presente l&#39;host wireguard (indicato come Host B, di solito) che fungerà da server.&#xA;&#xA;La configurazione di un peer si divide in 3 tronconi:&#xA;&#xA;il listener&#xA;l&#39;instradamento dei pacchetti fra gli host wireguard e gli endpoint&#xA;gli altri peers della VPN Wireguard&#xA;&#xA;Gli scenari che andremo a considerare riguarderanno la direzione delle comunicazioni e le strategie adottate per realizzarle:&#xA;&#xA;da Endpoint A a Endpoint B (punto-sito)&#xA;da Endpoint B a Endpoint A (sito-punto)&#xA;bidirezionale (punto-sito-punto)&#xA;&#xA;Prendendo uno scenario reale come riferimento, suppongo che la parte &#34;point&#34; sia dietro un NAT che nasconde l&#39;ip privato dell&#39;endpoint e permette solo connessioni già stabilite.&#xA;Nella parte &#34;site&#34;, la lan è protetta da un firewall-router-nat che espone il solo ip pubblico.&#xA;&#xA;Nella configurazione di filtering/routing sul firewall (ufw nel mio caso) di Host B, ci sarà da tenere conto delle politiche di inoltro. Per semplificarci la vita si potrebbe abilitare qualunque inoltro di default ma sarebbe un po&#39; pericoloso quindi, a meno di casi particolari, anche gli inoltri saranno filtrati.&#xA;a id=&#34;primo-scenario&#34;Primo scenario/a&#xA;&#xA;Nel primo scenario, considererò il caso punto-sito, in cui un endpoint (con wireguard) si collega, nella LAN attraverso un host wireguard, all&#39;endpoint che eroga un servizio.&#xA;&#xA;point-to-site&#xA;smallPoint-To-Site/small&#xA;&#xA;Obiettivo:&#xA;L&#39;endpoint del sito B (192.168.1.3) ha un servizio web https sulla porta 443, che non è raggiungibile dall&#39;esterno.&#xA;Possiamo usare wireguard per permettere all&#39;Endpoint A di raggiungere il servizio sugli endpoint del sito B, per mezzo dell&#39;host wireguard B.&#xA;Affinché l&#39;host B possa inoltrare i pacchetti dall&#39;Endpoint A all&#39;Endpoint B si ricorre al SNAT (MASQUERADING).&#xA;&#xA;point-to-site-masquerading&#xA;smallPoint-To-Site: Masquerading/small&#xA;&#xA;a id=&#34;pts-configurazione-wireguard-endpoint-a&#34;Configurazione wireguard Endpoint A/a&#xA;&#xA;[Interface]&#xA;Address = 10.0.0.2/32&#xA;SaveConfig = true&#xA;PrivateKey = Contenuto di endpoint-awg.key&#xA;&#xA;[Peer]&#xA;PublicKey = Contenuto di serverwg.pub&#xA;PresharedKey = Contenuto di endpoint-a.psk&#xA;Endpoint = 200.76.182.23:51820&#xA;AllowedIPs = 192.168.1.0/24&#xA;Dettagli:&#xA;&#xA;Interface.Address: IP dell&#39;Endpoint A nella rete virtuale definita da wireguard&#xA;Interface.SaveConfig: se è true, qualunque modifica fatta al file di configurazione prima dello spegnimento dell&#39;interfaccia verrà ignorato.&#xA;Interface.PrivateKey: la chiave privata dell&#39;Endpoint A&#xA;Peer.PublicKey: La chiave pubblica dell&#39;host B wireguard&#xA;Peer.PresharedKey: La preshared key dell&#39;Endpoint A&#xA;Peer.Endpoint: L&#39;ip esposto dell&#39;host B wireguard. Potrebbe trovarsi dietro un firewall/nat ma tanto sappiamo che sul sito B ho libertà d&#39;azione&#xA;Peer.AllowedIPs: Sono le reti che voglio ruotare nel tunnel. Possono essere singoli ip o subnet separati da &#34; , &#34;.&#xA;0.0.0.0/0 equivale a ruotare tutto il traffico del peer nella VPN wireguard. Nel caso in esame, ruoto nel tunnel solo la lan del sito B. Il resto del traffico è al di fuori della VPN wireguard (split tunnel)&#xA;&#xA;a id=&#34;pts-configurazione-wireguard-host-b&#34;Configurazione wireguard Host B/a&#xA;&#xA;[Interface]&#xA;Address = 10.0.0.1/24&#xA;SaveConfig = true&#xA;ListenPort = 51820&#xA;PrivateKey = Contenuto di serverwg.key&#xA;&#xA;endpoint A&#xA;[Peer]&#xA;PublicKey = Contenuto di endpoint-awg.pub&#xA;PresharedKey = Contenuto di endpoint-a.psk&#xA;AllowedIPs = 10.0.0.2/32&#xA;Dettagli:&#xA;&#xA;Interface.Address: ip dell&#39;host B nella rete virtuale definita da wireguard&#xA;Interface.SaveConfig: se è true, qualunque modifica fatta al file di configurazione prima dello spegnimento dell&#39;interfaccia verrà ignorato.&#xA;Interface.PrivateKey: la chiave privata dell&#39;host B&#xA;Peer.PublicKey: La chiave pubblica dell&#39;Endpoint A&#xA;Peer.PresharedKey: La preshared key dell&#39;Endpoint A&#xA;Peer.AllowedIPs: Dovendo contattare il singolo endpoint, AllowedIPs definito nel peer è l&#39;ip del peer stesso all&#39;interno della rete virtuale definita da wireguard.&#xA;&#xA;Non poteva essere altrimenti. In una topologia point-to-site,&#xA;&#xA;da point verso site, AllowedIPs della sezione [Peer] del point indirizza una o più subnet.&#xA;da site verso point, AllowedIPs della sezione [Peer] nell&#39;host wireguard indirizza puntualmente l&#39;Endpoint A.&#xA;&#xA;Inoltre, sempre in una topologia point-to-site, è sempre il point ad iniziare la connessione per cui:&#xA;&#xA;nel point:&#xA;  si deve specificare l&#39;Endpoint (\fqdn\or\ip:port\) nella sezione [Peer] relativa al server wireguard.&#xA;  non importa specificare la ListenPort nella sezione Interface che può essere scelta casualmente, perché l&#39;Endpoint A non verrà mai contattato direttamente&#xA;nel site:&#xA;  non importa specificare l&#39;Endpoint (\fqdn\orip:port\) nella sezione [Peer] relativa all&#39;Endpoint A, perché non sarà mai in attesa di una connessione&#xA;  si deve specificare la ListenPort nella sezione [Interface] perché le connessioni sono sempre iniziate dagli endpoint verso di lui&#xA;&#xA;a id=&#34;pts-configurazione-routing-filtering-host-b&#34;Configurazione routing/filtering Host B/a&#xA;&#xA;Il resto della configurazione non riguarda più wireguard direttamente ma riguarda l&#39;insieme di  policy di routing e filtering da fare sull&#39;host B per permettere ai pacchetti dell&#39;Endpoint A di essere inoltrati all&#39;Endpoint B attraverso l&#39;host B.&#xA;&#xA;Affinchè i pacchetti possano viaggiare dall&#39;Endpoint A all&#39;Endpoint B:&#xA;&#xA;i pacchetti arriveranno all&#39;host B sull&#39;interfaccia virtuale della VPN (wg0)&#xA;poi verranno inoltrati dall&#39;interfaccia virtuale della vpn (wg0) all&#39;interfaccia reale di host B (eth0),&#xA;prima di essere inviati a Endpoint B, una regola di post-routing riscriverà i pacchetti cambiandone l&#39;ip sorgente in modo che risultino inviati da host B piuttosto che da Endpoint A, così da permettere ad Endpoint B di rispondere.&#xA;&#xA;Quindi:&#xA;&#xA;va configurato un inoltro (eventualmente filtrato) dall&#39;interfaccia virtuale wireguard (wg0) a quella reale dell&#39;host B (eth0)&#xA;deve essere configurato il SNAT affinché l&#39;Endpoint B possa rispondere all&#39;Endpoint A&#xA;&#xA;abilita il forward&#xA;sysctl -w net.ipv4.ipforward=1&#xA;inoltra tutto il traffico in arrivo da wg0 verso il solo Endpoint B&#xA;ufw route allow in on wg0 out on eth0 proto tcp to 192.168.1.3 port 443;&#xA;masquerading&#xA;iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE&#xA;N.B. potrei ancora raffinare queste regole ricorrendo alla tabella Mangle per marcare i pacchetti ai quali applicare il masquerading.&#xA;&#xA;Questi comandi possono far parte della configurazione. Nella sezione [Interface] si possono usare i costrutti PreUp, PreDown, PostUp e PostDown per rendere dinamici alcuni passi di configurazione prima/dopo l&#39;apertura/chiusura del tunnel.&#xA;E così, la configurazione del server diventa:&#xA;&#xA;[Interface]&#xA;Address = 10.0.0.1/24&#xA;SaveConfig = true&#xA;ListenPort = 51820&#xA;PrivateKey = Contenuto di serverwg.key&#xA;&#xA;IP forwarding&#xA;PreUp = sysctl -w net.ipv4.ipforward=1&#xA;PreUp = ufw route allow in on wg0 out on eth0 proto tcp to 192.168.1.3 port 443&#xA;PostDown = ufw route delete allow in on wg0 out on eth0 proto tcp to 192.168.1.3 port 443&#xA;&#xA;IP masquerading&#xA;PreUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE&#xA;PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE&#xA;&#xA;IP filtering&#xA;PreUp = ufw allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;&#xA;PostDown = ufw delete allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;&#xA;&#xA;endpoint A&#xA;[Peer]&#xA;PublicKey = Contenuto di endpoint.awg.pub&#xA;PresharedKey = Contenuto di endpoint-a.psk&#xA;AllowedIPs = 10.0.0.2/32&#xA;a id=&#34;pts-test&#34;Test/a&#xA;&#xA;Da Endpoint A (192.168.10.10) possiamo raggiungere il servizio come se fossimo nella lan del sito B, quindi:&#xA;curl https://192.168.1.3&#xA;risponderà al browsing.&#xA;a id=&#34;pts-tips&#34;Tips/a&#xA;&#xA;La combinazione AllowedIPs / routing è la chiave per gestire qualunque instradamento.&#xA;Nell&#39;esempio visto finora abbiamo fatto in modo che:&#xA;&#xA;l&#39;Endpoint A ruotasse nella VPN wireguard solo la subnet relativa al sito B, 192.168.1.0/24, facendo split tunnel per il resto.&#xA;l&#39;host B avesse delle regole di inoltro per l&#39;Endpoint B per i soli pacchetti destinati al servizio che eroga, https. Qualuque altro host del sito B non può essere raggiunto.&#xA;&#xA;In questo modello, qualunque altro endpoint abilitato alla VPN wireguard potrebbe accedere al servizio dell&#39;Endpoint B.&#xA;Vale la pena dare un&#39;occhiata ad un altro paio di combinazioni che si trovano agli opposti del nostro esempio.&#xA;In un caso, ruoteremo tutto il traffico verso la vpn, in un altro consentiremo solo a determinati peer, non a tutti, di fruire di determinati servizi.&#xA;&#xA;1. Inoltro di tutto il traffico nella vpn&#xA;In questo modo, l&#39;Endpoint A lavora come se facesse parte della lan del sito B. È una modalità totalmente anonimizzante. Da usare solo con  dispositivi trusted perché un eventuale traffico malevolo verrebbe ruotato nel tunnel e risulterebbe proveniente dal sito B&#xA;&#xA;Su Endpoint A:&#xA;...&#xA;AllowedIPs = 0.0.0.0/0&#xA;...&#xA;Su host B:&#xA;...&#xA;ufw route allow in on wg0 out on eth0;`&#xA;...&#xA;2. Indirizzamento puntuale su servizi specifici&#xA;È il caso in cui alcuni peer debbano raggiungere solo determinati servizi e non altri. Supponiamo di avere altri due endpoint, Endpoint Asub1/sub e Endpoint Asub2/sub.&#xA;&#xA;Su Endpoint Asub1/sub e Asub2/sub (in realtà AllowedIPs potrebbe essere puntuale):&#xA;...&#xA;AllowedIPs = 192.168.1.0/24&#xA;...&#xA;...&#xA;PreUp = ufw route allow in on wg0 out on eth0 proto tcp from 10.0.0.3 to 192.168.1.4 port 3306&#xA;PreUp = ufw route allow in on wg0 out on eth0 proto tcp from 10.0.0.4 to 192.168.1.5 port 22&#xA;PostDown = ufw route delete allow in on wg0 out on eth0 proto tcp from 10.0.0.3 to 192.168.1.4 port 3306&#xA;PostDown = ufw route delete allow in on wg0 out on eth0 proto tcp from 10.0.0.4 to 192.168.1.5 port 22&#xA;...&#xA;a id=&#34;secondo-scenario&#34;Secondo scenario/a&#xA;&#xA;Nel secondo scenario, ribalterò il punto di vista e prenderò in esame il caso in cui sia un host del sito B a contattare un endpoint esterno con wireguard (sito-punto).&#xA;Non il classico scenario road-warrior in cui un endpoint deve raggiungere la rete aziendale o domestica, ma il suo opposto.&#xA;&#xA;site-to-point&#xA;smallSite-To-Point/small&#xA;&#xA;Obiettivo:&#xA;L&#39;host del sito A (192.168.10.10) ha un servizio web https sulla porta 1443, che non è raggiungibile dall&#39;esterno ma vogliamo che lo sia dal sito B.&#xA;Con wireguard, possiamo usare l&#39;interfaccia virtuale per esporre il servizio su 10.0.0.2, verso gli endpoint del sito B, per mezzo dell&#39;host wireguard B.&#xA;Affinché l&#39;host B possa inoltrare i pacchetti dall&#39;Endpoint B all&#39;Endpoint A si ricorre al DNAT (PORT FORWARDING).&#xA;&#xA;point-to-site-port-forwarding&#xA;smallSite-To-Point: Port-Forwarding/small&#xA;&#xA;La configurazione di wireguard su host B rimane sostanzialmente identica rispetto a prima.&#xA;A cambiare sarà soprattutto la parte di filtering e routing.&#xA;a id=&#34;stp-configurazione-wireguard-endpoint-a&#34;Configurazione wireguard Endpoint A/a&#xA;&#xA;[Interface]&#xA;Address = 10.0.0.2/32&#xA;SaveConfig = true&#xA;PrivateKey = Contenuto di endpoint-awg.key&#xA;&#xA;[Peer]&#xA;PublicKey = Contenuto di serverwg.pub&#xA;PresharedKey = Contenuto di endpoint-a.psk&#xA;Endpoint = 200.76.182.23:51820&#xA;AllowedIPs = 192.168.1.0/24&#xA;PersistentKeepalive = 25&#xA;Su Endpoint A c&#39;è una piccola modifica.&#xA;&#xA;Dettagli:&#xA;&#xA;PersistentKeepalive: Il NAT davanti all&#39;Endpoint A potrebbe troncare la connessione dopo un po&#39; visto che non è lui ad avviarla. Dal momento che è Endpoint A a dare servizio, si ricorre al keepalive per mantenere la connessione persistente.&#xA;&#xA;a id=&#34;stp-configurazione-wireguard-host-b&#34;Configurazione wireguard Host B/a&#xA;&#xA;[Interface]&#xA;Address = 10.0.0.1/24&#xA;SaveConfig = true&#xA;ListenPort = 51820&#xA;PrivateKey = Contenuto di serverwg.key&#xA;&#xA;endpoint A&#xA;[Peer]&#xA;PublicKey = Contenuto di endpoint-awg.pub&#xA;PresharedKey = Contenuto di endpoint-a.psk&#xA;AllowedIPs = 10.0.0.2/32&#xA;La configurazione di Host B rimane sostanzialmente invariata.&#xA;a id=&#34;stp-configurazione-routing-filtering-host-b&#34;Configurazione routing/filtering Host B/a&#xA;&#xA;Affinchè i pacchetti possano viaggiare dall&#39;Endpoint B all&#39;Endpoint A:&#xA;&#xA;i pacchetti arriveranno sull&#39;interfaccia reale di host B (eth0),&#xA;una regola di pre-routing riscriverà i pacchetti cambiandone l&#39;ip di destinazione con quello virtuale dell&#39;Endpoint A&#xA;poi verranno inoltrati dall&#39;interfaccia reale di host B (eth0) all&#39;interfaccia virtuale della VPN (wg0) che li recapiterà ad Endpoint A&#xA;&#xA;Quindi&#xA;&#xA;va configurato un inoltro (eventualmente filtrato) dall&#39;interfaccia reale dell&#39;host B (eth0) a quella virtuale wireguard (wg0)&#xA;deve essere configurato il DNAT affinché l&#39;Endpoint B possa contattare l&#39;Endpoint A.&#xA;&#xA;...&#xA;IP forwarding&#xA;abilita il forward&#xA;PreUp = sysctl -w net.ipv4.ipforward=1&#xA;inoltra tutto il traffico in arrivo da eth0 verso l&#39;Endpoint A&#xA;PreUp = ufw route allow in on eth0 out on wg0 proto tcp to 10.0.0.2 port 443&#xA;PostDown = ufw route delete allow in on eth0 out on wg0 proto tcp to 10.0.0.2 port 443&#xA;&#xA;IP port forwarding&#xA;inoltro della porta 1443 dall&#39;interfaccia lan verso la porta 443 dell&#39;Endpoint A&#xA;PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.0.0.2:1443&#xA;PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.0.0.2:1443&#xA;&#xA;IP filtering&#xA;PreUp = ufw allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;&#xA;PostDown = ufw delete allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;&#xA;...&#xA;a id=&#34;stp-test&#34;Test/a&#xA;&#xA;Da Endpoint B (192.168.1.3) possiamo raggiungere il servizio sull&#39;interfaccia virtuale dell&#39;Endpoint A passando dalla porta dell&#39;host B, quindi:&#xA;curl https://192.168.1.2&#xA;risponderà al browsing.&#xA;a id=&#34;stp-tips&#34;Tips/a&#xA;&#xA;In questa rappresentazione, ogni host del sito B viene indirizzato solo verso la vpn wireguard.&#xA;L&#39;host B inoltra:&#xA;&#xA;la porta 443 di ogni host del sito B verso l&#39;Endpoint A&#xA;tutto il traffico della lan verso la vpn wireguard.&#xA;&#xA;Se volessimo che solo determinati endpoint del sito B potessero inoltrare il loro traffico, si dovrebbero rendere le regole di inoltro più puntuali.&#xA;Supponiamo che Endpoint A (10.0.0.2) esponga un servzio ihttpd/i sulla porta 10080 e vogliamo che solo gli host 192.168.1.9-192.168.1.14 del sito B lo possano raggiungere sulla canonica porta 80.&#xA;&#xA;Port Forwarding di un solo endpoint&#xA;ufw route allow from 192.168.1.4 to 10.0.0.2 port 10080 proto tcp&#xA;iptables -t nat -A PREROUTING -s 192.168.1.4 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:10080&#xA;Port Forwarding di una subnet&#xA;ufw route allow from 192.168.1.8/29 to 10.0.0.2 port 10080 proto tcp&#xA;iptables -t nat -A PREROUTING -s 192.168.1.9-192.168.1.14 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:10080&#xA;a id=&#34;terzo-scenario&#34;Terzo scenario/a&#xA;&#xA;Il terzo scenario può essere considerato un&#39;unione dei primi due.&#xA;&#xA;point-to-site-to-point&#xA;smallPoint-To-Site-To-Point/small&#xA;&#xA;Obiettivo:&#xA;L&#39;host del sito A (192.168.10.10) espone un servizio di remote desktop (porta 3389), l&#39;endpoint del sito B (192.168.1.3) espone un servizio web https sulla porta 443. Vogliamo che l&#39;Endpoint A raggiunga il servizio web e che l&#39;Endpoint B acceda al desktop remoto dell&#39;Endpoint A.&#xA;&#xA;point-to-site-gateway&#xA;smallPoint-To-Site: Gateway/small&#xA;&#xA;Se viene configurato il routing sul gateway per indirizzare wireguard, il traffico potrà essere bidirezionale. Non ci sarà bisogno di manipolare i pacchetti perché:&#xA;&#xA;Da Endpoint A a Endpoint B, i pacchetti inoltrati da host B avranno come sorgente l&#39;ip della rete wireguard di Endpoint A.&#xA;Attraverso il gateway, Endpoint B potrà rispondere/contattare direttamente l&#39;indirizzo sorgente wireguard di Endpoint A.&#xA;&#xA;La configurazione di wireguard su Endpoint A e Endpoint B è assimilabile allo scenario 2 con l&#39;impostazione del PersistentKeepAlive_ su Endpoint A&#xA;&#xA;a id=&#34;gtw-configurazione-routing-filtering-host-b&#34;Configurazione routing/filtering Host B/a&#xA;&#xA;Al solito va configurato l&#39;inoltro su Host B da Endpoint A a B e viceversa&#xA;...&#xA;PreUp = ufw route allow in on wg0 out on eth0 to 192.168.1.3 port 443 proto tcp&#xA;PostDown = ufw route delete allow in on wg0 out on eth0 to 192.168.1.3 port 443 proto tcp&#xA;PreUp = ufw route allow in on eth0 out on wg0 from 192.168.1.3 port 3389 proto tcp&#xA;PostDown = ufw route delete allow in on eth0 out on wg0 from 192.168.1.3 port 3389 proto tcp&#xA;...&#xA;a id=&#34;gtw-configurazione-gateway-host-sito-b&#34;Configurazione gateway host del Sito B/a&#xA;&#xA;A parte attivare il solito inoltro su host B, bisognerà avere la possibilità di configurare il routing anche sul nostro router (192.168.1.1), in maniera che Endpoint B, che presumbilmente ha proprio 192.168.1.1 come gateway di default, indirizzando Endpoint A, venga rediretto verso Host B. Ad es.&#xA;ip route add 10.0.0.2/32 via 192.168.1.2 dev eth0&#xA;In alternativa, se non si ha la possibilità/voglia di configurare il router, bisognerà configurare Endpoint B con la rotta statica indicata prima.&#xA;a id=&#34;gtw-test&#34;Test/a&#xA;&#xA;Da Endpoint A (192.168.10.10) possiamo raggiungere il servizio come se fossimo nella lan del sito B, quindi:&#xA;curl https://192.168.1.3&#xA;&#xA;Da Endpoint B (192.168.1.3) raggiungiamo il desktop remoto dell&#39;Endpoint A attraverso la sua interfaccia virtuale (10.0.0.2)&#xA;rdesktop 10.0.0.2&#xA;a id=&#34;gtw-tips&#34;Tips/a&#xA;&#xA;Si potrebbe pensare di aggregare le potenziali rotte statiche considerando l&#39;intera subnet  wireguard per avere un&#39;unica rotta statica su tutti gli host del sito B configurando sul nostro router (oppure su tutti gli host del sito B):&#xA;ip route add 10.0.0.0/24 via 192.168.1.2 dev eth0&#xA;In questo modo, ogni host del sito B può indirizzare vicendevolmente il suo traffico verso endpoint esterni purché le regole wireguard lo consentano (iAllowedIPs/i)&#xA;a id=&#34;differenze-3-approcci&#34;Differenze fra i 3 approcci/a&#xA;&#xA;Primo scenario: l&#39;Endpoint A contatta l&#39;Endpoint B sul suo indirizzo reale ma l&#39;Endpoint B non ha idea di chi siano gli endpoint, lato &#34;punto&#34;, che lo contattano (per effetto del masquerading, le connessioni agli Endpoint B partono da host B).&#xA;&#xA;Secondo scenario: l&#39;Endpoint B non può contattare direttamente gli endpoint lato &#34;punto&#34; ma contatterà l&#39;host B e sarà il DNAT a veicolare i pacchetti agli endpoint lato &#34;punto&#34;.&#xA;&#xA;Terzo scenario: potendo configurare il router (o gli host del sito B), è l&#39;approccio più semplice e garantisce bidirezionalità senza manipolazione dei pacchetti.&#xA;&#xA;small Riferimenti:&#xA;&#xA;https://www.wireguard.com/&#xA;/small&#xA;&#xA;#vpn #openvpn #wireguard #CryptokeyRouting&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/42a8ecf32-5a8865/ppStGSe7U66H/y0DHDOsjleOm5BwuCTL4fqaibuW7yYDX643arMfx.jpg" alt="vpn">
<small><i>Fonte:  Photo by Stefan Coders on <a href="https://www.pexels.com/it-it/foto/uomo-persone-donna-apple-5243610/" rel="nofollow">Pexels.com</a></i></small></p>

<h2 id="a-id-perche-wireguard-perché-wireguard-a"><a id="perche-wireguard">Perché wireguard?</a></h2>
<ul><li>È più semplice di OpenVPN.</li>
<li>Fa parte del kernel dalla versione 5.6 in poi (ci sono anche versioni in userspaces). Vanno installati solo i software di gestione del tunnel</li>
<li>Si basa su uno strato di crittografia all&#39;avanguardia per quel che riguarda efficienza e robustezza</li>
<li>Il suo codice, estremamente compatto, viene revisionato con molta più facilità.</li>
<li>Non si basa su un modello client-server ma P2P</li>
<li>Il traffico è UDP piuttosto che TCP (ci sono modi per fare un wrapping TCP delle connessioni UDP)</li></ul>


<ol><li><a href="#perche-wireguard" rel="nofollow">Perché wireguard?</a></li>
<li><a href="#crittografia-di-wireguard" rel="nofollow">Crittografia di Wireguard</a></li>
<li><a href="#un-po-di-teoria" rel="nofollow">Un po&#39; di teoria</a></li>
<li><a href="#installazione" rel="nofollow">Installazione</a>
<ol><li><a href="#generazione-chiavi" rel="nofollow">Generazione chiavi</a></li></ol></li>
<li><a href="#attivazione-nodo" rel="nofollow">Attivazione del nodo</a>
<ol><li><a href="#pc-laptop" rel="nofollow">PC/Laptop</a></li>
<li><a href="#mobile" rel="nofollow">Mobile</a></li></ol></li>
<li><a href="#debug" rel="nofollow">Debug</a></li>
<li><a href="#topologie" rel="nofollow">Topologie</a></li>
<li><a href="#point-to-site" rel="nofollow">Point-To-Site</a>
<ol><li><a href="#primo-scenario" rel="nofollow">Primo scenario</a>
<ol><li><a href="#pts-configurazione-wireguard-endpoint-a" rel="nofollow">Configurazione wireguard Endpoint A</a></li>
<li><a href="#pts-configurazione-wireguard-host-b" rel="nofollow">Configurazione wireguard Host B</a></li>
<li><a href="#pts-configurazione-routing-filtering-host-b" rel="nofollow">Configurazione routing/filtering Host B</a></li>
<li><a href="#pts-test" rel="nofollow">Test</a></li>
<li><a href="#pts-tips" rel="nofollow">Tips</a></li></ol></li>
<li><a href="#secondo-scenario" rel="nofollow">Secondo scenario</a>
<ol><li><a href="#stp-configurazione-wireguard-endpoint-a" rel="nofollow">Configurazione wireguard Endpoint A</a></li>
<li><a href="#stp-configurazione-wireguard-host-b" rel="nofollow">Configurazione wireguard Host B</a></li>
<li><a href="#stp-configurazione-routing-filtering-host-b" rel="nofollow">Configurazione routing/filtering Host B</a></li>
<li><a href="#stp-test" rel="nofollow">Test</a></li>
<li><a href="#stp-tips" rel="nofollow">Tips</a></li></ol></li>
<li><a href="#terzo-scenario" rel="nofollow">Terzo scenario</a>
<ol><li><a href="#gtw-configurazione-routing-filtering-host-b" rel="nofollow">Configurazione routing/filtering Host B</a></li>
<li><a href="#gtw-configurazione-gateway-host-sito-b" rel="nofollow">Configurazione gateway Sito B</a></li>
<li><a href="#gtw-test" rel="nofollow">Test</a></li>
<li><a href="#gtw-tips" rel="nofollow">Tips</a></li></ol></li>
<li><a href="#differenze-3-approcci" rel="nofollow">Differenze fra i 3 approcci</a></li></ol></li></ol>

<h2 id="a-id-crittografia-di-wireguard-crittografia-di-wireguard-a"><a id="crittografia-di-wireguard">Crittografia di Wireguard</a></h2>

<p>Le primitive crittografiche di Wireguard si basano su:</p>
<ul><li><strong>Curve25519</strong>, per autenticazione e key exchange (ECDH)</li>
<li><strong>ChaCha20</strong> e <strong>Poly1305</strong>, per la cifratura simmetrica con autenticazione (AEAD)</li>
<li><strong>BLAKE2</strong>, come hash crittografico</li>
<li><strong>SipHash-2-4</strong>, come funzione di hash crittografico con chiave (tipo HMAC)</li>
<li><strong>HKDF</strong>, come funzione di derivazione della chiave basata su HMAC</li>
<li><strong>Noise Framework</strong>, è un protocollo crittografico. Stabilisce il modo con cui tutte queste operazioni crittografiche vengono fatte lavorare.</li></ul>

<h2 id="a-id-un-po-di-teoria-un-po-di-teoria-a"><a id="un-po-di-teoria">Un po&#39; di teoria</a></h2>

<p>Wireguard implementa una vpn L3 solo tunneling, incapsulando pacchetti IP all&#39;interno di pacchetti UDP per il trasporto. Ciò implica che funzioni come dhcp, essendo L2, non possono trovare spazio all&#39;interno di wireguard, ergo l&#39;indirizzamento (ip, subnet, dns) deve essere fatto staticamente.</p>

<p>Avendo un&#39;anima P2P, ogni nodo (peer) wireguard è sia client che server. Ciò permette di realizzare topologie anche piuttosto complesse con uno sforzo relativamente ridotto.</p>

<p>Un peer wireguard è composto da due tipi di sezioni:</p>
<ul><li>una sezione “interface”, relativa al peer stesso, contenente:
<ul><li>il proprio IP, nello spazio di indirizzamento privato usato dalla vpn.</li>
<li>una porta, su cui il peer può essere in ascolto per accettare richieste da altri nodi wireguard</li>
<li>la parte privata della chiave asimmetrica con cui decifra e autentica</li></ul></li>
<li>una o più sezioni “peer”, relative ai nodi a cui può connettersi, contenenti:
<ul><li>la parte pubblica della chiave asimmetrica del peer, con cui cifra e verifica</li>
<li>AllowedIPs, che descrive l&#39;ip o le reti da ruotare nel tunnel, a cui è consentito il traffico in entrata e a cui è diretto il traffico in uscita</li>
<li>l&#39;endpoint del peer, necessario solo se altri peer devono avviare connessioni verso di lui</li></ul></li></ul>

<p>I nodi si autenticano a vicenda scambiandosi e convalidando le chiavi pubbliche. Ogni chiave pubblica è associata all&#39;IP di un peer.</p>

<p>Quando un peer deve inviare dei pacchetti, <strong>AllowedIPs</strong> si comporta come una <strong>tabella di instradamento</strong>. Il peer esamina l&#39;<strong>IP di destinazione</strong> di quel pacchetto e lo cerca negli <strong>AllowedIPs</strong> dei suoi peer per capire a chi inviarlo. Se lo trova, ruota il pacchetto nel tunnel, altrimenti no.</p>

<p>Quando si ricevono pacchetti, <strong>AllowedIPs</strong> si comporta come una <strong>lista di controllo degli accessi</strong>. Il peer esamina l&#39;<strong>IP di origine</strong> e se rientra nell&#39;<strong>AllowedIPs</strong> di uno dei suoi peer, accetterà il pacchetto altrimenti lo scarterà.</p>

<p>Per esperienza personale, il 99% degli errori di configurazione su wireguard viene fatto proprio sul campo <strong>AllowedIPs</strong> perché non se ne comprende bene il funzionamento.</p>

<p>Uno degli errori più comuni è quello di definire dei peer in cui gli ip contenuti nei campi AllowedIPs si sovrappongono. In base al funzionamento di wireguard infatti, non posso avere chiavi pubbliche diverse per uno stesso ip perché il peer, pur essendo in grado di ricevere pacchetti, non riuscirebbe a inviarli, non sapendo come ruotarli dovendo scegliere fra più peer.</p>

<h2 id="a-id-installazione-installazione-a"><a id="installazione">Installazione</a></h2>

<p>Come già detto, wireguard è presente di base nel kernel linux. Bisogna installare solo gli strumenti di interfacciamento per la configurazione su ogni host.</p>

<p>Per sistemi debian-based:</p>

<pre><code class="language-bash">apt install wireguard wireguard-tools
</code></pre>

<h2 id="a-id-generazione-chiavi-generazione-chiavi-a"><a id="generazione-chiavi">Generazione chiavi</a></h2>

<p>Per semplicità, suppongo di generare tutte le chiavi che mi occorrono, del server (host B) e del client (Endpoint A) in questo caso. Oltre alle chiavi, userò anche una pre-shared key per il client. Non è obbligatorio ma mi costa zero e aumenta la resistenza post-quantistica.</p>

<pre><code class="language-bash">#server
wg genkey &gt; server_wg.key
wg pubkey &lt; server_wg.key &gt; server_wg.pub

#client
wg genkey &gt; endpoint-a_wg.key
wg pubkey &lt; endpoint-a_wg.key &gt; endpoint-a_wg.pub

# Creazione psk
wg genpsk &gt; endpoint-a.psk
</code></pre>

<h2 id="a-id-attivazione-nodo-attivazione-del-nodo-a"><a id="attivazione-nodo">Attivazione del nodo</a></h2>

<p>Una volta che la configurazione del nodo è pronta, va attivato il servizio se ci troviamo su un pc. Altrimenti bisognerà importare la configurazione sul device.</p>

<h3 id="a-id-pc-laptop-pc-laptop-a"><a id="pc-laptop">PC/Laptop</a></h3>

<p>Sia esso un client o un server, una volta configurato il peer, salva il file file sotto <strong>/etc/wireguard/</strong> col nome dell&#39;interfaccia virtuale che hai scelto, nel mio caso, <strong>wg0.conf</strong></p>

<p><strong>Attivazione/Disattivazione vpn on-demand</strong>:</p>

<pre><code class="language-bash">wg-quick up wg0 #attiva la vpn
wg-quick down wg0 #disattiva la vpn
</code></pre>

<p><strong>Attivazione/Disattivazione vpn come servizio</strong>:</p>

<pre><code class="language-bash">systemctl enable wg-quick@wg0
systemctl start/stop wg-quick@wg0.service
</code></pre>

<h3 id="a-id-mobile-mobile-a"><a id="mobile">Mobile</a></h3>

<p>Se il provisioning delle configurazioni si fa attraverso un pc, per portare facilmente la configurazione su un device mobile, si può generare un qrcode del file (supponiamo sia <em>mobile.conf</em>) e importarlo.</p>

<pre><code class="language-bash"># Installazione qrencode (debian-based)
apt install qrencode

#Crea il qr-code e dallo in pasto a al client
qrencode -t ansiutf8 &lt; mobile.conf
</code></pre>

<h2 id="a-id-debug-debug-a"><a id="debug">Debug</a></h2>

<p>Wireguard è un modulo del kernel e quindi la sua attività viene raccolta dai log del kernel (<strong>/var/log/kern.log</strong> o <strong>/var/log/messages</strong>).</p>

<p>Bisogna verificare che sul kernel si possa abilitare il <code>dynamic_debug_control</code>, controllando se è presente:</p>

<pre><code class="language-bash">ls /sys/kernel/debug/dynamic_debug
</code></pre>

<p>Se lo è, si carica il modulo, si setta il dynamic debug e si potrà esaminare log del kernel ad es. con <code>journalctl -fk</code></p>

<pre><code class="language-bash">modprobe wireguard
echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control
</code></pre>

<p>Potresti dover installare <strong>resolvconf</strong> sul server.</p>

<p>Quando wireguard fa salire l&#39;interfaccia, la registra su <strong>systemd-resolve</strong> attraverso <strong>resolvconf</strong> e se non è installato potrebbe verificarsi un malfunzionamento.</p>

<h2 id="a-id-topologie-topologie-a"><a id="topologie">Topologie</a></h2>

<p>Le principali topologie che possono essere realizzate con wireguard sono:</p>
<ul><li>point-to-point</li>
<li>point-to-site</li>
<li>site-to-site</li>
<li>hub-and-spoke (a stella)</li></ul>

<p>Il canale sicuro fra i nodi wireguard viene creato attraverso le primitive crittografiche di cui sopra, ogni peer viene identificato da una chiave asimmetrica.</p>

<p>Non è necessario approfondire la parte di crittografia per capire come configurare wireguard. Ci fidiamo che faccia un buon lavoro.</p>

<p>Ciò su cui invece vale la pena soffermarsi, è la parte di instradamento, essenziale per l&#39;implementazione delle topologie di cui sopra.</p>

<p>Io mi soffermerò sulla topologia più comune, point-to-site, che permette di unire un endpoint che esegue wireguard, con un altro endpoint situato all&#39;interno di una LAN in cui c&#39;è un host wireguard.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/9e2db7367-e375b7/4wYB1RIZRwIY/ZlVqqUt6vE98pxToDuixqc0cKJdZeeorUu2pqGL7.png" alt="easy-point-to-site"></p>

<p>Tanto per fissare le idee indicherò:</p>
<ul><li>col termine <strong>peer</strong>, uno dei punti logici di una vpn wireguard</li>
<li>col termine <strong>endpoint</strong>, uno dei punti di arrivo della tratta interessata dal tunnel vpn</li>
<li>col termine <strong>host wireguard</strong>, l&#39;host che esegue wireguard.</li></ul>

<p><strong>Osservazioni banali:</strong>
– In una topologia point-to-point, <strong>host wireguard</strong> ed <strong>endpoint</strong> coincidono su entrambi gli estremi della tratta.
– In una topologia point-to-site, <strong>host wireguard</strong> ed <strong>endpoint</strong> coincidono solo sul “point” (l&#39;altro endpoint è dietro ad un host wireguard).
– In una topologia site-to-site, gli endpoint sono sempre dietro gli host wireguard.</p>

<h2 id="a-id-point-to-site-point-to-site-a"><a id="point-to-site">Point-To-Site</a></h2>

<p>Avrò un <strong>Sito A</strong> che comprende il solo endpoint dove non ho la possibilità di gestire routing e filtering e un <strong>Sito B</strong> dove, al contrario, potrò impostare le mie policy di instradamento e filtraggio e dove sarà presente l&#39;host wireguard (indicato come Host B, di solito) che fungerà da server.</p>

<p>La configurazione di un peer si divide in 3 tronconi:</p>
<ul><li>il listener</li>
<li>l&#39;instradamento dei pacchetti fra gli host wireguard e gli endpoint</li>
<li>gli altri peers della VPN Wireguard</li></ul>

<p>Gli scenari che andremo a considerare riguarderanno la direzione delle comunicazioni e le strategie adottate per realizzarle:</p>
<ul><li>da Endpoint A a Endpoint B (punto-sito)</li>
<li>da Endpoint B a Endpoint A (sito-punto)</li>
<li>bidirezionale (punto-sito-punto)</li></ul>

<p>Prendendo uno scenario reale come riferimento, suppongo che la parte “point” sia dietro un NAT che nasconde l&#39;ip privato dell&#39;endpoint e permette solo connessioni già stabilite.
Nella parte “site”, la lan è protetta da un firewall-router-nat che espone il solo ip pubblico.</p>

<p>Nella configurazione di filtering/routing sul firewall (ufw nel mio caso) di Host B, ci sarà da tenere conto delle politiche di inoltro. Per semplificarci la vita si potrebbe abilitare qualunque inoltro di default ma sarebbe un po&#39; pericoloso quindi, a meno di casi particolari, anche gli inoltri saranno filtrati.</p>

<h3 id="a-id-primo-scenario-primo-scenario-a"><a id="primo-scenario">Primo scenario</a></h3>

<p>Nel primo scenario, considererò il caso <strong>punto-sito</strong>, in cui un endpoint (con wireguard) si collega, nella LAN attraverso un <strong>host wireguard</strong>, all&#39;endpoint che eroga un servizio.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/9e2db7367-e375b7/S1wOox3eybrz/wSkUqX0YwaqHqt4DEoCakacEVmzqOuITr1x0NS88.png" alt="point-to-site">
<em><small>Point-To-Site</small></em></p>

<p><strong>Obiettivo</strong>:
L&#39;endpoint del sito B (<strong>192.168.1.3</strong>) ha un servizio web https sulla porta 443, che non è raggiungibile dall&#39;esterno.
Possiamo usare wireguard per permettere all&#39;Endpoint A di raggiungere il servizio sugli endpoint del sito B, per mezzo dell&#39;host wireguard B.
Affinché l&#39;host B possa inoltrare i pacchetti dall&#39;Endpoint A all&#39;Endpoint B si ricorre al <strong>SNAT (MASQUERADING)</strong>.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/c537ce87c-f5971d/6qCphDfGjYeW/7XkgfWnP54UKaFMio7kaHRvThXhmfkzW9Lbnkm4M.png" alt="point-to-site-masquerading">
<em><small>Point-To-Site: Masquerading</small></em></p>

<h4 id="a-id-pts-configurazione-wireguard-endpoint-a-configurazione-wireguard-endpoint-a-a"><a id="pts-configurazione-wireguard-endpoint-a">Configurazione wireguard Endpoint A</a></h4>

<pre><code class="language-bash">[Interface]
Address = 10.0.0.2/32
SaveConfig = true
PrivateKey = &lt;Contenuto di endpoint-a_wg.key&gt;

[Peer]
PublicKey = &lt;Contenuto di server_wg.pub&gt;
PresharedKey = &lt;Contenuto di endpoint-a.psk&gt;
Endpoint = 200.76.182.23:51820
AllowedIPs = 192.168.1.0/24
</code></pre>

<p><strong>Dettagli:</strong></p>
<ul><li><strong>Interface.Address</strong>: IP dell&#39;Endpoint A nella rete virtuale definita da wireguard</li>
<li><strong>Interface.SaveConfig</strong>: se è true, qualunque modifica fatta al file di configurazione prima dello spegnimento dell&#39;interfaccia verrà ignorato.</li>
<li><strong>Interface.PrivateKey</strong>: la chiave privata dell&#39;Endpoint A</li>
<li><strong>Peer.PublicKey</strong>: La chiave pubblica dell&#39;host B wireguard</li>
<li><strong>Peer.PresharedKey</strong>: La preshared key dell&#39;Endpoint A</li>
<li><strong>Peer.Endpoint</strong>: L&#39;ip esposto dell&#39;host B wireguard. Potrebbe trovarsi dietro un firewall/nat ma tanto sappiamo che sul sito B ho libertà d&#39;azione</li>
<li><strong>Peer.AllowedIPs</strong>: Sono le reti che voglio ruotare nel tunnel. Possono essere singoli ip o subnet separati da “ , “.
0.0.0.0/0 equivale a ruotare tutto il traffico del peer nella VPN wireguard. Nel caso in esame, ruoto nel tunnel solo la lan del sito B. Il resto del traffico è al di fuori della VPN wireguard (<strong>split tunnel</strong>)</li></ul>

<h4 id="a-id-pts-configurazione-wireguard-host-b-configurazione-wireguard-host-b-a"><a id="pts-configurazione-wireguard-host-b">Configurazione wireguard Host B</a></h4>

<pre><code class="language-bash">[Interface]
Address = 10.0.0.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = &lt;Contenuto di server_wg.key&gt;

# endpoint A
[Peer]
PublicKey = &lt;Contenuto di endpoint-a_wg.pub&gt;
PresharedKey = &lt;Contenuto di endpoint-a.psk&gt;
AllowedIPs = 10.0.0.2/32
</code></pre>

<p><strong>Dettagli:</strong></p>
<ul><li><strong>Interface.Address</strong>: ip dell&#39;host B nella rete virtuale definita da wireguard</li>
<li><strong>Interface.SaveConfig</strong>: se è true, qualunque modifica fatta al file di configurazione prima dello spegnimento dell&#39;interfaccia verrà ignorato.</li>
<li><strong>Interface.PrivateKey</strong>: la chiave privata dell&#39;host B</li>
<li><strong>Peer.PublicKey</strong>: La chiave pubblica dell&#39;Endpoint A</li>
<li><strong>Peer.PresharedKey</strong>: La preshared key dell&#39;Endpoint A</li>
<li><strong>Peer.AllowedIPs</strong>: Dovendo contattare il singolo endpoint, AllowedIPs definito nel peer è l&#39;ip del peer stesso all&#39;interno della rete virtuale definita da wireguard.</li></ul>

<p>Non poteva essere altrimenti. In una topologia point-to-site,</p>
<ul><li>da point verso site, <em>AllowedIPs</em> della sezione [Peer] del point <strong>indirizza una o più subnet</strong>.</li>
<li>da site verso point, <em>AllowedIPs</em> della sezione [Peer] nell&#39;host wireguard <strong>indirizza puntualmente l&#39;Endpoint A</strong>.</li></ul>

<p>Inoltre, sempre in una topologia point-to-site, è sempre il point ad iniziare la connessione per cui:</p>
<ul><li>nel point:
<ul><li><strong>si deve specificare l&#39;Endpoint</strong> (&lt;fqdn_or_ip:port&gt;) nella sezione [Peer] relativa al server wireguard.</li>
<li><strong>non importa specificare la ListenPort</strong> nella sezione Interface che può essere scelta casualmente, perché l&#39;Endpoint A non verrà mai contattato direttamente</li></ul></li>
<li>nel site:
<ul><li><strong>non importa specificare l&#39;Endpoint</strong> (&lt;fqdn_or_ip:port&gt;) nella sezione [Peer] relativa all&#39;Endpoint A, perché non sarà mai in attesa di una connessione</li>
<li><strong>si deve specificare la ListenPort</strong> nella sezione [Interface] perché le connessioni sono sempre iniziate dagli endpoint verso di lui</li></ul></li></ul>

<h4 id="a-id-pts-configurazione-routing-filtering-host-b-configurazione-routing-filtering-host-b-a"><a id="pts-configurazione-routing-filtering-host-b">Configurazione routing/filtering Host B</a></h4>

<p>Il resto della configurazione non riguarda più wireguard direttamente ma riguarda l&#39;insieme di  policy di routing e filtering da fare sull&#39;host B per permettere ai pacchetti dell&#39;Endpoint A di essere inoltrati all&#39;Endpoint B attraverso l&#39;host B.</p>

<p>Affinchè i pacchetti possano viaggiare dall&#39;Endpoint A all&#39;Endpoint B:</p>
<ul><li>i pacchetti arriveranno all&#39;host B sull&#39;interfaccia virtuale della VPN (wg0)</li>
<li>poi verranno inoltrati dall&#39;interfaccia virtuale della vpn (wg0) all&#39;interfaccia reale di host B (eth0),</li>
<li>prima di essere inviati a Endpoint B, una regola di post-routing riscriverà i pacchetti cambiandone l&#39;ip sorgente in modo che risultino inviati da host B piuttosto che da Endpoint A, così da permettere ad Endpoint B di rispondere.</li></ul>

<p>Quindi:</p>
<ul><li>va configurato un inoltro (eventualmente filtrato) dall&#39;interfaccia virtuale wireguard (wg0) a quella reale dell&#39;host B (eth0)</li>
<li>deve essere configurato il SNAT affinché l&#39;Endpoint B possa <strong>rispondere</strong> all&#39;Endpoint A</li></ul>

<pre><code class="language-bash"># abilita il forward
sysctl -w net.ipv4.ip_forward=1
# inoltra tutto il traffico in arrivo da wg0 verso il solo Endpoint B
ufw route allow in on wg0 out on eth0 proto tcp to 192.168.1.3 port 443;
# masquerading
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
</code></pre>

<p><strong>N.B.</strong> potrei ancora raffinare queste regole ricorrendo alla tabella <strong>Mangle</strong> per marcare i pacchetti ai quali applicare il masquerading.</p>

<p>Questi comandi possono far parte della configurazione. Nella sezione [Interface] si possono usare i costrutti <strong>PreUp</strong>, <strong>PreDown</strong>, <strong>PostUp</strong> e <strong>PostDown</strong> per rendere dinamici alcuni passi di configurazione prima/dopo l&#39;apertura/chiusura del tunnel.
E così, la configurazione del server diventa:</p>

<pre><code class="language-bash">[Interface]
Address = 10.0.0.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = &lt;Contenuto di server_wg.key&gt;

# IP forwarding
PreUp = sysctl -w net.ipv4.ip_forward=1
PreUp = ufw route allow in on wg0 out on eth0 proto tcp to 192.168.1.3 port 443
PostDown = ufw route delete allow in on wg0 out on eth0 proto tcp to 192.168.1.3 port 443

# IP masquerading
PreUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# IP filtering
PreUp = ufw allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;
PostDown = ufw delete allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;

# endpoint A
[Peer]
PublicKey = &lt;Contenuto di endpoint.a_wg.pub&gt;
PresharedKey = &lt;Contenuto di endpoint-a.psk&gt;
AllowedIPs = 10.0.0.2/32
</code></pre>

<h4 id="a-id-pts-test-test-a"><a id="pts-test">Test</a></h4>

<p>Da Endpoint A (192.168.10.10) possiamo raggiungere il servizio come se fossimo nella lan del sito B, quindi:</p>

<pre><code class="language-bash">curl https://192.168.1.3
</code></pre>

<p>risponderà al browsing.</p>

<h4 id="a-id-pts-tips-tips-a"><a id="pts-tips">Tips</a></h4>

<p>La combinazione <em>AllowedIPs / routing</em> è la chiave per gestire qualunque instradamento.
Nell&#39;esempio visto finora abbiamo fatto in modo che:</p>
<ul><li>l&#39;Endpoint A ruotasse nella VPN wireguard solo la subnet relativa al sito B, 192.168.1.0/24, facendo split tunnel per il resto.</li>
<li>l&#39;host B avesse delle regole di inoltro per l&#39;Endpoint B per i soli pacchetti destinati al servizio che eroga, https. Qualuque altro host del sito B non può essere raggiunto.</li></ul>

<p>In questo modello, qualunque altro endpoint abilitato alla VPN wireguard potrebbe accedere al servizio dell&#39;Endpoint B.
Vale la pena dare un&#39;occhiata ad un altro paio di combinazioni che si trovano agli opposti del nostro esempio.
In un caso, ruoteremo tutto il traffico verso la vpn, in un altro consentiremo solo a determinati peer, non a tutti, di fruire di determinati servizi.</p>

<p><strong>1. Inoltro di tutto il traffico nella vpn</strong>
In questo modo, l&#39;Endpoint A lavora come se facesse parte della lan del sito B. È una modalità totalmente anonimizzante. Da usare solo con  dispositivi trusted perché un eventuale traffico malevolo verrebbe ruotato nel tunnel e risulterebbe proveniente dal sito B</p>

<p>Su Endpoint A:</p>

<pre><code class="language-bash">...
AllowedIPs = 0.0.0.0/0
...
</code></pre>

<p>Su host B:</p>

<pre><code class="language-bash">...
ufw route allow in on wg0 out on eth0;`
...
</code></pre>

<p><strong>2. Indirizzamento puntuale su servizi specifici</strong>
È il caso in cui alcuni peer debbano raggiungere <strong>solo</strong> determinati servizi e non altri. Supponiamo di avere altri due endpoint, Endpoint A<sub>1</sub> e Endpoint A<sub>2</sub>.</p>

<p>Su Endpoint A<sub>1</sub> e A<sub>2</sub> (in realtà AllowedIPs potrebbe essere puntuale):</p>

<pre><code class="language-bash">...
AllowedIPs = 192.168.1.0/24
...
</code></pre>

<pre><code class="language-bash">...
PreUp = ufw route allow in on wg0 out on eth0 proto tcp from 10.0.0.3 to 192.168.1.4 port 3306
PreUp = ufw route allow in on wg0 out on eth0 proto tcp from 10.0.0.4 to 192.168.1.5 port 22
PostDown = ufw route delete allow in on wg0 out on eth0 proto tcp from 10.0.0.3 to 192.168.1.4 port 3306
PostDown = ufw route delete allow in on wg0 out on eth0 proto tcp from 10.0.0.4 to 192.168.1.5 port 22
...
</code></pre>

<h3 id="a-id-secondo-scenario-secondo-scenario-a"><a id="secondo-scenario">Secondo scenario</a></h3>

<p>Nel secondo scenario, ribalterò il punto di vista e prenderò in esame il caso in cui sia un host del sito B a contattare un endpoint esterno con wireguard (sito-punto).
Non il classico scenario road-warrior in cui un endpoint deve raggiungere la rete aziendale o domestica, ma il suo opposto.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/9e2db7367-e375b7/1eWNsrbMjsVI/FByQcZ9tq4Ekl2LRtujHv64MNvKe6rTsgYrF6An9.png" alt="site-to-point">
<em><small>Site-To-Point</small></em></p>

<p><strong>Obiettivo</strong>:
L&#39;host del sito A (192.168.10.10) ha un servizio web https sulla porta 1443, che non è raggiungibile dall&#39;esterno ma vogliamo che lo sia dal sito B.
Con wireguard, possiamo usare l&#39;interfaccia virtuale per esporre il servizio su 10.0.0.2, verso gli endpoint del sito B, per mezzo dell&#39;host wireguard B.
Affinché l&#39;host B possa inoltrare i pacchetti dall&#39;Endpoint B all&#39;Endpoint A si ricorre al <strong>DNAT (PORT FORWARDING)</strong>.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/c537ce87c-f5971d/hN8OLKexz4gJ/nu9txh6VlDxnkMctuOGqgfJJrtI9csJLwpSoKYju.png" alt="point-to-site-port-forwarding">
<em><small>Site-To-Point: Port-Forwarding</small></em></p>

<p>La configurazione di wireguard su host B rimane sostanzialmente identica rispetto a prima.
A cambiare sarà soprattutto la parte di filtering e routing.</p>

<h4 id="a-id-stp-configurazione-wireguard-endpoint-a-configurazione-wireguard-endpoint-a-a"><a id="stp-configurazione-wireguard-endpoint-a">Configurazione wireguard Endpoint A</a></h4>

<pre><code class="language-bash">[Interface]
Address = 10.0.0.2/32
SaveConfig = true
PrivateKey = &lt;Contenuto di endpoint-a_wg.key&gt;

[Peer]
PublicKey = &lt;Contenuto di server_wg.pub&gt;
PresharedKey = &lt;Contenuto di endpoint-a.psk&gt;
Endpoint = 200.76.182.23:51820
AllowedIPs = 192.168.1.0/24
PersistentKeepalive = 25
</code></pre>

<p>Su Endpoint A c&#39;è una piccola modifica.</p>

<p><strong>Dettagli:</strong></p>
<ul><li><strong>PersistentKeepalive</strong>: Il NAT davanti all&#39;Endpoint A potrebbe troncare la connessione dopo un po&#39; visto che non è lui ad avviarla. Dal momento che è Endpoint A a dare servizio, si ricorre al keepalive per mantenere la connessione persistente.</li></ul>

<h4 id="a-id-stp-configurazione-wireguard-host-b-configurazione-wireguard-host-b-a"><a id="stp-configurazione-wireguard-host-b">Configurazione wireguard Host B</a></h4>

<pre><code class="language-bash">[Interface]
Address = 10.0.0.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = &lt;Contenuto di server_wg.key&gt;

# endpoint A
[Peer]
PublicKey = &lt;Contenuto di endpoint-a_wg.pub&gt;
PresharedKey = &lt;Contenuto di endpoint-a.psk&gt;
AllowedIPs = 10.0.0.2/32
</code></pre>

<p>La configurazione di Host B rimane sostanzialmente invariata.</p>

<h4 id="a-id-stp-configurazione-routing-filtering-host-b-configurazione-routing-filtering-host-b-a"><a id="stp-configurazione-routing-filtering-host-b">Configurazione routing/filtering Host B</a></h4>

<p>Affinchè i pacchetti possano viaggiare dall&#39;Endpoint B all&#39;Endpoint A:</p>
<ul><li>i pacchetti arriveranno sull&#39;interfaccia reale di host B (eth0),</li>
<li>una regola di pre-routing riscriverà i pacchetti cambiandone l&#39;ip di destinazione con quello virtuale dell&#39;Endpoint A</li>
<li>poi verranno inoltrati dall&#39;interfaccia reale di host B (eth0) all&#39;interfaccia virtuale della VPN (wg0) che li recapiterà ad Endpoint A</li></ul>

<p>Quindi</p>
<ul><li>va configurato un inoltro (eventualmente filtrato) dall&#39;interfaccia reale dell&#39;host B (eth0) a quella virtuale wireguard (wg0)</li>
<li>deve essere configurato il DNAT affinché l&#39;Endpoint B possa <strong>contattare</strong> l&#39;Endpoint A.</li></ul>

<pre><code class="language-bash">...
# IP forwarding
# abilita il forward
PreUp = sysctl -w net.ipv4.ip_forward=1
# inoltra tutto il traffico in arrivo da eth0 verso l&#39;Endpoint A
PreUp = ufw route allow in on eth0 out on wg0 proto tcp to 10.0.0.2 port 443
PostDown = ufw route delete allow in on eth0 out on wg0 proto tcp to 10.0.0.2 port 443

# IP port forwarding
# inoltro della porta 1443 dall&#39;interfaccia lan verso la porta 443 dell&#39;Endpoint A
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.0.0.2:1443
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.0.0.2:1443

# IP filtering
PreUp = ufw allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;
PostDown = ufw delete allow in on eth0 proto udp from 0.0.0.0/0 to 192.168.1.2 port 51820;
...
</code></pre>

<h4 id="a-id-stp-test-test-a"><a id="stp-test">Test</a></h4>

<p>Da Endpoint B (192.168.1.3) possiamo raggiungere il servizio sull&#39;interfaccia virtuale dell&#39;Endpoint A passando dalla porta dell&#39;host B, quindi:</p>

<pre><code class="language-bash">curl https://192.168.1.2
</code></pre>

<p>risponderà al browsing.</p>

<h4 id="a-id-stp-tips-tips-a"><a id="stp-tips">Tips</a></h4>

<p>In questa rappresentazione, ogni host del sito B viene indirizzato solo verso la vpn wireguard.
L&#39;host B inoltra:</p>
<ul><li>la porta 443 di ogni host del sito B verso l&#39;Endpoint A</li>
<li>tutto il traffico della lan verso la vpn wireguard.</li></ul>

<p>Se volessimo che solo determinati endpoint del sito B potessero inoltrare il loro traffico, si dovrebbero rendere le regole di inoltro più puntuali.
Supponiamo che Endpoint A (<strong>10.0.0.2</strong>) esponga un servzio <i>httpd</i> sulla porta <strong>10080</strong> e vogliamo che solo gli host <strong>192.168.1.9-192.168.1.14</strong> del sito B lo possano raggiungere sulla canonica porta <strong>80</strong>.</p>

<p><strong>Port Forwarding di un solo endpoint</strong></p>

<pre><code class="language-bash">ufw route allow from 192.168.1.4 to 10.0.0.2 port 10080 proto tcp
iptables -t nat -A PREROUTING -s 192.168.1.4 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:10080
</code></pre>

<p><strong>Port Forwarding di una subnet</strong></p>

<pre><code class="language-bash">ufw route allow from 192.168.1.8/29 to 10.0.0.2 port 10080 proto tcp
iptables -t nat -A PREROUTING -s 192.168.1.9-192.168.1.14 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:10080
</code></pre>

<h3 id="a-id-terzo-scenario-terzo-scenario-a"><a id="terzo-scenario">Terzo scenario</a></h3>

<p>Il terzo scenario può essere considerato un&#39;unione dei primi due.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/9e2db7367-e375b7/Tr8CQXQYASs1/uMnrW3IOWLPfQa2GH9HLDFSRarSgmIrs0RqOQvVH.png" alt="point-to-site-to-point">
<em><small>Point-To-Site-To-Point</small></em></p>

<p><strong>Obiettivo</strong>:
L&#39;host del sito A (<strong>192.168.10.10</strong>) espone un servizio di remote desktop (porta 3389), l&#39;endpoint del sito B (<strong>192.168.1.3</strong>) espone un servizio web https sulla porta 443. Vogliamo che l&#39;Endpoint A raggiunga il servizio web e che l&#39;Endpoint B acceda al desktop remoto dell&#39;Endpoint A.</p>

<p><img src="https://pixelfed.uno/storage/m/_v2/489827599091373610/c537ce87c-f5971d/LRMwMdT8xPWR/SMZh2fF9ityxKdDatlJvoz9i0s1qHArvLGusPMhL.png" alt="point-to-site-gateway">
<em><small>Point-To-Site: Gateway</small></em></p>

<p>Se viene configurato il routing sul <strong>gateway</strong> per indirizzare wireguard, il traffico potrà essere bidirezionale. Non ci sarà bisogno di manipolare i pacchetti perché:</p>
<ol><li>Da Endpoint A a Endpoint B, i pacchetti inoltrati da host B avranno come sorgente l&#39;ip della rete wireguard di Endpoint A.</li>
<li>Attraverso il gateway, Endpoint B potrà rispondere/contattare direttamente l&#39;indirizzo sorgente wireguard di Endpoint A.</li></ol>

<p>La configurazione di wireguard su Endpoint A e Endpoint B è assimilabile allo scenario 2 con l&#39;impostazione del <em>PersistentKeepAlive</em> su Endpoint A</p>

<h4 id="a-id-gtw-configurazione-routing-filtering-host-b-configurazione-routing-filtering-host-b-a"><a id="gtw-configurazione-routing-filtering-host-b">Configurazione routing/filtering Host B</a></h4>

<p>Al solito va configurato l&#39;inoltro su Host B da Endpoint A a B e viceversa</p>

<pre><code class="language-bash">...
PreUp = ufw route allow in on wg0 out on eth0 to 192.168.1.3 port 443 proto tcp
PostDown = ufw route delete allow in on wg0 out on eth0 to 192.168.1.3 port 443 proto tcp
PreUp = ufw route allow in on eth0 out on wg0 from 192.168.1.3 port 3389 proto tcp
PostDown = ufw route delete allow in on eth0 out on wg0 from 192.168.1.3 port 3389 proto tcp
...
</code></pre>

<h4 id="a-id-gtw-configurazione-gateway-host-sito-b-configurazione-gateway-host-del-sito-b-a"><a id="gtw-configurazione-gateway-host-sito-b">Configurazione gateway host del Sito B</a></h4>

<p>A parte attivare il solito inoltro su host B, bisognerà avere la possibilità di configurare il routing anche sul nostro router (<strong>192.168.1.1</strong>), in maniera che Endpoint B, che presumbilmente ha proprio <strong>192.168.1.1</strong> come gateway di default, indirizzando Endpoint A, venga rediretto verso Host B. Ad es.</p>

<pre><code class="language-bash">ip route add 10.0.0.2/32 via 192.168.1.2 dev eth0
</code></pre>

<p>In alternativa, se non si ha la possibilità/voglia di configurare il router, bisognerà configurare Endpoint B con la rotta statica indicata prima.</p>

<h4 id="a-id-gtw-test-test-a"><a id="gtw-test">Test</a></h4>

<p>Da Endpoint A (<strong>192.168.10.10</strong>) possiamo raggiungere il servizio come se fossimo nella lan del sito B, quindi:</p>

<pre><code class="language-bash">curl https://192.168.1.3
</code></pre>

<p>Da Endpoint B (<strong>192.168.1.3</strong>) raggiungiamo il desktop remoto dell&#39;Endpoint A attraverso la sua interfaccia virtuale (<strong>10.0.0.2</strong>)</p>

<pre><code class="language-bash">rdesktop 10.0.0.2
</code></pre>

<h4 id="a-id-gtw-tips-tips-a"><a id="gtw-tips">Tips</a></h4>

<p>Si potrebbe pensare di aggregare le potenziali rotte statiche considerando l&#39;intera subnet  wireguard per avere un&#39;unica rotta statica su tutti gli host del sito B configurando sul nostro router (oppure su <strong>tutti</strong> gli host del sito B):</p>

<pre><code class="language-bash">ip route add 10.0.0.0/24 via 192.168.1.2 dev eth0
</code></pre>

<p>In questo modo, ogni host del sito B può indirizzare vicendevolmente il suo traffico verso endpoint esterni purché le regole wireguard lo consentano (<i>AllowedIPs</i>)</p>

<h3 id="a-id-differenze-3-approcci-differenze-fra-i-3-approcci-a"><a id="differenze-3-approcci">Differenze fra i 3 approcci</a></h3>

<p><strong>Primo scenario</strong>: l&#39;Endpoint A contatta l&#39;Endpoint B sul suo indirizzo reale ma l&#39;Endpoint B non ha idea di chi siano gli endpoint, lato “punto”, che lo contattano (per effetto del masquerading, le connessioni agli Endpoint B partono da host B).</p>

<p><strong>Secondo scenario</strong>: l&#39;Endpoint B non può contattare direttamente gli endpoint lato “punto” ma contatterà l&#39;host B e sarà il DNAT a veicolare i pacchetti agli endpoint lato “punto”.</p>

<p><strong>Terzo scenario</strong>: potendo configurare il router (o gli host del sito B), è l&#39;approccio più semplice e garantisce bidirezionalità senza manipolazione dei pacchetti.</p>

<p><small> <strong>Riferimenti</strong>:</p>
<ul><li><a href="https://www.wireguard.com/" rel="nofollow">https://www.wireguard.com/</a>
</small></li></ul>

<p><a href="/aytin/tag:vpn" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">vpn</span></a> <a href="/aytin/tag:openvpn" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">openvpn</span></a> <a href="/aytin/tag:wireguard" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">wireguard</span></a> <a href="/aytin/tag:CryptokeyRouting" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">CryptokeyRouting</span></a></p>
]]></content:encoded>
      <guid>https://noblogo.org/aytin/vpn-con-wireguard-semplice-e-veloce</guid>
      <pubDate>Thu, 16 Mar 2023 15:02:34 +0000</pubDate>
    </item>
  </channel>
</rss>