Stunnel: Cos'è e come si configura

(pubblicato il 7 gennaio 2023) Stunnel Fonte: stunnel.org

Introduzione

Da documentazione, Stunnel agisce come un proxy per aggiungere crittografia TLS a server e/o a client già esistenti.

Risulta quindi molto comodo quando si vuole aggiungere, attraverso un tunnel TLS, quella crittografia che manca alle nostre applicazioni per rendere le comunicazioni più sicure.

Come in ssh, è possibile “tunnellizzare” solo connessioni TCP.

Di stunnel esaminerò in particolare la fase di autenticazione attraverso certificato o PSK.

Gli scenari possibili, in base alle combinazioni, sono tre:

Nel primo caso, occorre configurare stunnel in server mode, definendo un receiver ssl, a cui il client potrà connettersi. stunel server Scenario 1: stunnel server

Nel secondo caso, occorre configurare stunnel in client mode, definendo un sender ssl che il client userà per connettersi al server stunnel client Scenario 2: stunnel client

Nel terzo caso, occorre configurare uno stunnel client e uno server stunnel client e server Scenario 3: stunnel client e server

Come ulteriore evoluzione per quel che riguarda le tratte in chiaro (e non solo) di client-stunnel client, stunnel client-stunnel server, stunnel server-server, sarebbe buona norma limitarne l’accesso con un firewall. stunnel client e server e firewall Stunnel e firewall

Se invece stunnel fosse locale (installato direttamente sul client e/o sul server), la richiesta del client o il listener del servizio, avverrebbero sull’interfaccia di loopback. Altrimenti, in assenza di firewall, sarebbe consigliabile accertare che la rete di collegamento fra i proxy stunnel e i rispettivi client/server, sia almeno di tipo “trusted”.

Stunnel consente un certo tuning sulla parte tls, potendo discriminare fra le cipher suites da abilitare, specificare comandi o configurazioni specifiche per openssl. Quando si deve incapsulare una connessione in chiaro in un tunnel ssl bisogna tenere presente gli scenari menzionati prima.

Convenzioni

Configurazione stunnel

Verranno mostrate le configurazioni relative agli scenari mostrati nel modo più semplice possibile.

Primo scenario

Nel primo caso, una configurazione minimale lato server, ha bisogno:

  1. host e porta dello stunnel server che riceve il traffico cifrato
  2. host e porta del server su cui girare il traffico in chiaro
  3. certificato pubblico e chiave privata necessari per la cifratura

Stunnel Server:

[myService]
accept = ip_stunnel_server:port_sts
connect = ip_server:port_server
cert = /server_crt.pem<br>
key = /server_key.pem

Secondo scenario

Nel secondo caso, una configurazione minimale lato client, ha bisogno:

  1. host e porta dello stunnel client da cui partirà la richiesta
  2. host e porta del server da cui stunnel client avvierà la sessione tls

Stunnel Client:

[myService]
client = yes
accept = ip_stunnel_client:port_stc
connect = ip_server:port_server

Terzo Scenario

Il terzo caso, è una fusione dei primi due. Sono gli stunnel a gestire il grosso della comunicazione. E nei casi in cui lo stunnel viene installato sulle macchine di servizio, client e server reali usano solo l’interfaccia di loopback.

Una configurazione minimale per il client ha bisogno di:

  1. host e porta dello stunnel client da cui partirà la richiesta
  2. host e porta del server da cui stunnel client avvierà la sessione tls

Stunnel Client:

[myService]
client = yes
accept = ip_stunnel_client:port_stc
connect = ip_stunnel_server:port_server

Una configurazione minimale per il server ha bisogno:

  1. host e porta dello stunnel server che riceve il traffico cifrato
  2. host e porta del server su cui girare il traffico in chiaro certificato pubblicato e chiave privata necessari per la cifratura

Stunnel Server:

[myService]
accept = ip_stunnel_server:port_sts
connect = ip_server:port_server
cert = /server_crt.pem
key = /server_key.pem

Piccola nota: se client e/o server dovessero supportare chiavi PSK, si potrebbe usare PSK in luogo dei certificati. Ci ritornerò più avanti.

Autenticazione dei client

Le impostazioni viste finora, mostrano come incapsulare un traffico in chiaro all’interno di un tunnel tls e si basano sulla sola autenticazione lato server.

Per migliorare la configurazione possiamo ricorrere alla mutua autenticazione facendo in modo che anche i client si autentichino.

Una mutua autenticazione, con tutte le verifiche del caso, aumenta il grado di sicurezza comunicazione TLS ed è un efficace deterrente contro eventuali attacchi MITM. L’autenticazione sul client si può ottenere sempre con i certificati oppure, più semplicemente, con chiavi PSK.

Autenticazione dei client con certificato

Ad una configurazione minimale per una mutua autenticazione, lato server, si richiede che i client esibiscano il certificato e i client (che sia stunnel in client mode, un browser o qualunque altra cosa) dovranno essere in grado di esibire i certificati nel momento in cui il server li richiederà.

Su stunnel server, alle configurazioni viste in precedenza, si aggiunge requireCert impostato a yes, che richiede ai client l’esibizione di un certificato. Se, durante l’handshake TLS, il client non esibisce un certificato, l’handshake fallisce e la connessione viene rifiutata.

Stunnel Server:

[myService]
…
requireCert = yes
…

È sufficiente questo se i client possono manipolare i propri certificati. Altrimenti, se c’è uno stunnel client che intermedia le richieste dei client effettivi, si deve aggiungere alla sua configurazione la chiave e il certificato del client

Stunnel Client:

[myService]
…
cert = /server_crt.pem
key = /server_key.pem
…

Autenticazione dei client con PSK

Per l’autenticazione PSK bisogna disporre della lista di utenti abilitati con relative chiavi esadecimali di almeno 16 bytes (ossia almeno 32 caratteri esadecimali visto che con un byte si rappresentano due esadecimali).

La creazione di una chiave esadecimale può essere fatta velocemente con openssl. Supponiamo di creare due utenze per Frodo e Gandalf con chiavi da 20 e 42 bytes.

echo -e "frodo:"$(openssl rand -hex 20) > frodo_psk.txt
echo -e "gandalf:"$(openssl rand -hex 42) > gandalf_psk.txt

Tutte le identità dovranno confluire nel file che, nella configurazione stunnel, sarà indicato da PSKsecrets. Ad es:

cat frodo_psk.txt gandalf_psk.txt > psksecrets.txt
…
frodo:84196825fab3389624dcc83eb61189e5b21099fe<br>gandalf:5daf128419855993a2d95ba0a337c51b3f373df88e594441f2979eba6461f25676f1f825b0c76df392f2
…

E, come detto, nella configurazione dello stunnel server dovrò indicare il file delle identità:

Stunnel Server

[myServer]
accept = ip_stunnel_server:port_sts
connect = ip_server:port_server
PSKsecrets = <path_identity_file>/psksecrets.txt

Se il client supporta PSK, dovrà fornire identità e password. Ad es. facendo un test con openssl:

openssl s_client -port <porta> -psk_identity frodo -psk 84196825fab3389624dcc83eb61189e5b21099fe -tls1_2 -connect <host>

Altrimenti si configura stunnel client indicando sia l’identità, sia il file individuate da PSKsecrets.

Stunnel Client

[myClient]
client = yes
accept = ip_stunnel_client:port_stc
connect = ip_stunnel_server:port_server
PSKidentity = frodo
PSKsecrets = <path_identity_file>/psksecrets.txt

In alternativa, per non far viaggiare il file delle identità fra tutti i client, possiamo sfruttare a nostro vantaggio il default delle identità.

In assenza della direttiva PSKidentity, viene assunta come identità di default la prima riga del file indicato da PSKSecrets. Basta quindi creare un file con la sola identità che mi occorre, ad es. frodo_psk.txt

frodo:84196825fab3389624dcc83eb61189e5b21099fe

e indicare quello in PSKSecrets. La configurazione che segue è equivalente alla precedente.

Stunnel Client

[myClient]
client = yes
accept = ip_stunnel_client:port_stc
connect = ip_stunnel_server:port_server
PSKsecrets = <path_identity_file>/frodo_psk.txt

Ulteriori considerazioni di sicurezza

Autenticazione con certificato

La richiesta di autenticazione dei client mediante certificato è una buona misura preventiva ma può essere resa migliore.

Nelle configurazioni viste finora, stunnel server autorizza l’accesso al servizio solo se il client si presenta con un certificato ma non c’è nulla che vincoli il certificato al servizio. In altre parole, un client in possesso di un qualunque certificato, può accedere alla risorsa.

È possibile rafforzare il trusting fra le parti facendo in modo che stunnel autorizzi solo alcuni certificati invece che qualunque. Questo tipo di controllo può essere fatto sia su stunnel sia in client mode che in server mode.

verifyChain Impone che si possa verificare la fullchain del certificato presentato. Se uno degli issuer non viene trovato, la connessione fallisce. La fullchain viene indicata attraverso CAfile o CApath.

CAfile È il file contenente le CA con cui stunnel valida i certificati che gli vengono presentati. Se stunnel è in server mode, sarà la fullchain relativa ai client. Altrimenti sarà la fullchain relativa al server.

CApath È il path in cui si trovano le CA con cui stunnel valida i certificati che gli vengono presentati. Se lo stunnel è in server mode, sarà la fullchain realtiva ai client. Altrimenti sarà la fullchain relativa al server.

verifyPeer Se con CAfile e CApath si verifica la fullchain dei certificati presentati a stunnel, con verifyPeer = yes si verifica che questi certificati siano presenti anche nel suo keystore (CAfile o CApath). Permette di “legare” a stunnel i certificati che dovrà validare.

checkEmail, checkHost, checkIP Come per verifyPeer, sono direttive che permettono di stringere il legame fra il certificato che viene presentato e stunnel. Verifica che l’email, il CN o l’IP del certificato che viene presentato corrispondano a quelli presenti nella configurazione. In una configurazione lato server posso avere molteplici occorrenze di questi due campi relative ad altrettanti certificati. Il caso in cui ad es. si debbano autenticare n client.

Se i certificati sono self-signed, verifyChain perde di significato (coinciderebbe con verifyPeer). La possibilità di generare i certificati attraverso una CA, anche interna, renderebbe il processo più strutturato anche se più complesso (si dovrà trovare un modo per distribuire la CA, se interna). Si tratta di trovare il giusto compromesso fra ampiezza del servizio (quanti utenti coinvolge?) e complessità richiesta.

Se si tratta di realizzare un canale sicuro fra due apparati per una comunicazione server-2-server, vanno bene anche i certificati self-signed o un’autenticazione PSK. Altrimenti, soprattutto nel caso in cui l’autenticazione dei client è una fase critica, conviene valutare l’uso di una CA e una validazione il più possibile restrittiva sui client e sul server.

Autenticazione PSK

A differenza dell’autenticazione con certificato, l’autenticazione con PSK non prevede enhancement di sicurezza ulteriori a meno di specificare opportuni algoritmi di cifratura (cfr. paragrafo successivo).

Cifratura

Come sempre succede, negli scenari di cifratura asimmetrica orientatia alla connessione, l’autenticazione, per quanto possa essere accurata, costituisce solo uno degli aspetti di cui tenere conto nella fase di messa in sicurezza del servizio.

Avere un’autenticazione con certificato generato con tutti i crismi da una CA, è certamente una gran cosa ma mette in sicurezza solo l’aspetto dell’autenticazione, per l’appunto.

l transito dei dati è affidato alle suite di cifratura supportati da openssl e, volendo lavorare di fino, bisognerebbe stringere anche su quelli.

Altrimenti, paradossalmente, si avrà un’autenticazione robustissima ma con algoritmi colabrodo di cifratura dei dati che, ad attaccanti ben motivati, lascerebbero delle porte spalancate per sferrare attacchi MITM per intercettare direttamente i dati, piuttosto che provare il furto di identità.

Ad ogni modo, il default, per ragioni di compatibilità legacy, dei parametri di cifratura (da settare eventualmente su client e sul server) è il seguente:

ciphers: HIGH:!aNULL:!SSLv2:!DH:!kDHEPSK
ciphersuites: TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256

dove ciphers raggruppa le suite di cifratura relativi a TLS1.2 in giù e ciphersuites riguarda invece TLS1.3.

Configurazione servizio

Ulteriori restrizioni possono essere aggiunte a livelllo di sistema:

  1. regolando i bit di setuid e setgid se stunnel gira come root
  2. delimitando l’esecuzione del processo in una gabbia chroot
  3. disabilitando le regonetiation (se supportato dalla versione di openssl in uso) che mitiga in parte attacchi dos di tipo CPU-exhaustion
  4. ecc..

Caso reale: tunnelizzare Transmission.

Transmission è un client bittorrent che può essere controllato da remoto via rpc attraverso un’interfaccia web o altri client.

Transmission, nelle sue varie declinazioni, non incapsula il traffico rpc in una connessione tls.

Se si vuole che il dato in transito sia cifrato e che la connessione sia autenticata, si può ricorrere:

  1. ad un tunnel ssh;
  2. all’intermediazione di un webserver come apache o nginx ;
  3. ad uno stunnel server

Sugli ultimi due punti si può configurare una mutua autenticazione con certificato (complessa e articolata e, per tanti client, ha un impatto significativo). Scegliamo il 3° caso.

Esposizione dell’interfaccia web

Scenario: abbiamo una macchina (il nostro serverino di fiducia o un nas) con transmission a bordo, presumibilmente dietro un firewall che natta il suo indirizzo privato (192.168.70.15).

Transmission Stunnel Esposizione transmission attraverso stunnel server

Obiettivo: Vogliamo poter raggiungere transmission e vogliamo che i client autentichino la loro connessione prima di accedere al servizio. In base allo scenario, sappiamo che dovremmo configurare un port forwarding dall’AP fino allo stunnel server. Il server transmission rimarrà confinato nella nostra rete locale.

Utilizzo di un client esterno

Supponiamo di utilizzare diversi client: il browser, transmission-remote-gtk o transmission-remote-gui (transgui), tremotesf (mobile).

La prima cosa da fare è configurare un port forwarding sul nostro AP

Rule1: 9091 ⇒ 192.168.70.10:9091

Dopodichè, configureremo stunnel in server mode davanti a transmission

[transmission]
accept = 192.168.70.10:9091
connect = 192.168.70.15:9091
cert = <path stunnel conf>/ssl/server/certs/stunnel_crt.pem
key = <path stunnel conf>/ssl/server/private/stunnel_key.pem
requireCert = yes
verifyChain = yes
verifyPeer = yes
CApath = <path stunnel conf>/ssl/client/certs

Alcune note sulla configurazione:

A questo punto basta che i web-client puntino all’host pubblico (151.25.77.205) sulla porta 9091 e il gioco è fatto.

Per gli altri client come transmission-remote-gtk, transgui o tremotesf, per i quali al massimo posso chiedere di usare TLS (ma non sono riuscito ad usare un’autenticazione lato client), conviene installare stunnel in client mode :

[transmission-client]
accept = localhost:9091
connect = 151.25.77.205:9091
client = yes
cert = <path stunnel conf>/ssl/client/laptop_crt.pem
key = <path stunnel conf>/ssl/client/laptop_key.pem
verifyChain = yes
verifyPeer = yes
CAPath = <path stunnel conf>/ssl/server/certs

Il client (ad es. sul laptop) si connetterà su localhost:9091 e dovrà disporre anche del certificato del server e della sua fullchain affinchè i check su verifyChain e verifyPeer non falliscano.

#ca #DigitalCertificate #AsymmetricEncryption #SymmetricEncryption #cryptography #fullchain #psk #ssh #ssl #stunnel #tls #x509 #openssl