My boring Blog

Home page di Mauro Frigerio

Esempio mutual TLS con Traefik

10-04-2021 Tempo di lettura 6 minuti Article

Molte guide per la configurazione di server SSH consigliano vivamente di eliminare il login con le password e passare a delle chiavi per server esposti a internet. Ho iniziato a sfruttare questa comodissima e sicura alternativa per il login quando mi sono interessato di Borg.

Poi un giorno su Twitter ho visto questo tweet e mi sono interessato a mTLS.

Mi sono interessato per capire cosa premette di fare mutual TLS o abbreviato mTLS e perchè molti consigliano (come per SSH) di aggiungerlo ai siti privati esposti a internet. Così è possibile proteggere un sito esposto senza la necessità di accedere tramite un VPN (soluzione comunque migliore). Però non sempre si riesce ad usare un VPN causa blocchi sui firewall oppure non è possibile installare software sul computer aziendale.

Detto molto in parole semplici, basta creare un certificato e installarlo nel browser che si vuole usare.

Idea

Voglio implementare mTLS su tutti i servizi ai quali accedo con HTTP e non ho chiamate da device diversi da un browser. In primis tutti i siti ai quali accedo da internet. Grazie a Traefik posso creare un collegamento sicuro TLS e poi aggiungere mTLS, poi l’applicazione stessa presenterà il proprio login quando richiesto.

Spero che funzioni anche con Home Assistant e la sua applicazione per smartphone.

Certificati

Se usi Cloudflare salta i prossimi passaggi e passa al sotto capitolo.

Prima di tutto dobbiamo generare i certificati per i client. Purtroppo la strada non è così diretta come per le chiavi SSH e prima si deve creare una CA o certificate authority. La CA si occupa di firmare i certificati dei client.

mkdir ca

# generare una chiave privata
openssl genrsa -aes256 -out ca/ca.key 4096

# generare un certificato CA
openssl req -new -x509 -sha256 -days 1095 -key ca/ca.key -out ca/ca.crt

Adesso si può passare al certificato client.

mkdir client

# generare una chiave privata
openssl genrsa -out client/client.key 4096

# generazione di un Certificate Signing Request (CSR)
openssl req -new -key client/client.key -sha256 -out client/client.csr

# generazione del certificato client
openssl x509 -req -days 365 -sha256 -in client/client.csr -CA ca/ca.crt -CAkey ca/ca.key -set_serial 1 -out client/client.crt

# generazione del .p12 (file unico certificato + chiave)
openssl pkcs12 -export -clcerts -in client/client.crt -inkey client/client.key -out client/client.p12

Attivare mTLS e certificati per Cloudflare

Cloudflare crea un piccolo problema visto il sistema di cache e proxy per mascherare il server origine. La comunicazione da internet al server web viene divisa in due, da internet al server Cloudflare e da Cloudflare al server web. Il client in internet non vede il certificato del server origine, perchè la comunicazione è terminata sui server Cloudflare.

Ci sono due possibilità per risolvere il problema (con vantaggi e svantaggi):

  1. si disattiva la cache e il proxy
    • PRO: certificato mTLS configurato come descritto sopra
    • CON: l’IP di casa sarà visibile a tutti
  2. si configurano i certificati di Cloudflare
    • PRO: IP di casa mascherato
    • CON: il sito non è consultabile in locale all’interno della rete di casa

Ho scelto la prima soluzione per poter accedere direttamente in locale al sito protetto da mTLS, anche in mancanza di internet.

Config Traefik

Sfrutto la configurazione di Traefik che ho pubblicato sul mio repository su GitHub. Basta aggiungere queste opzioni alla configurazione base di Traefik (nel file FileProvider/file-provider.toml).

[tls.options]
	[tls.options.myTLSOptions]
    [tls.options.myTLSOptions.clientAuth]
		caFiles = ["client.crt"]   # aggiungere tutti i certificati client necessari ["client1","client2"]
		clientAuthType = "RequireAndVerifyClientCert"

Si possono aggiungere più certificati client in base ai bisogni o alla segnmentazione che si vuole fare.

Al container Traefik in docker si deve aggiungere il collegamento ai certificati (per ogni certificato aggiunto nel file .toml):

volumes:
	...
	- /your/path/cert/client/client.crt:/client.crt:ro

Ora è possibile lanciare il docker-compose per ricreare il container di Traefik e attivare mTLS

Docker

Traefik è pronto, ora è il turno dei container ai quali si vuole aggiungere mTLS. Se il container è già ok basta aggiungere una sola riga ed il gioco è fatto! Qui sotto ho messo l’esempio del container whoami.

whoami:
    image: containous/whoami
    container_name: whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.${DOMAIN}`)"
      - "traefik.http.routers.whoami.entrypoints=web-secure"
      - "traefik.http.routers.whoami.tls.certresolver=certificato"
      - "traefik.http.routers.whoami.tls.domains[0].main=*.${DOMAIN}"
      - "traefik.http.routers.whoami.tls.options=myTLSOptions@file"		# la riga speciale da aggiungere per mTLS

La riga da aggiugngere è:

- "traefik.http.routers.CAMBIARE_NOME_ROUTER.tls.options=myTLSOptions@file"

# ATTENZIONE cambiare il nome del router a seconda della propria configurazione

Ricreare il container e prova a raggiungere il sito con il tuo browser. Adesso c’è un problema, a seconda del browser appare un errore (Brave, Chrome) o non appare niente (Firefox). Ma così potete testare che mTLS funziona correttamente.

Si può testare tutto con il terminal con il seguente comando:

curl -sv https://whoami.example.com --cert client/client.crt --key client/client.key

Aggiungere i certificati al browser

Nelle impostazioni del browser cercate certificati e dovete trovare il menu per importare i certificati. Nel browser Brave/Chrome il menu si chiama Gestisci certificati, mentre in Firefox devi cercare Mostra certificati. Selezionate il file con l’estensione .p12. Ora potete richiamare il sito e la prima volta vi verrà richiesto quale certificato volete inviare al server. Se adesso la pagina si apre, complimenti hai configurato mTLS.

Problema cache del browser

Ho avuto alcuni problemi durante i vari tentativi di far funzionare i certificati mTLS e mi sono ritrovato ad avere dei certificanti non funzionanti in Chrome e gli stessi in Firefox funzionavano correttamente. Sono riuscito a trovare la soluzione qui.

Oppure meglio creare un profilo di test, così da poter fare tutti i disastri possibili senza perdere tutti i propri dati nel browser.

Aggiungere i certificati in Android (esempio Samsung)

Scaricare il file formato .p12 sullo smartphone android. Nel menu Impostazioni > Dati biometrici e sicurezza > Altre impostazioni di sicurezza > Installa da memoria dispositivo > Certificato utente app e VPN. Selezionare il certificato appena scaricato e installarlo. Dopo aver inserito la password per sbloccarlo e dato un nome vi basta visitare il sito.

Aggiungere i certificati in iOS

Non sono un grande utilizzatore di iOS quindi ho trovato questa guida.

Mio commento

Una volta capito il meccanismo del mutual TLS e il suo funzionamento con Traefik aggiungerlo ai vari container è un gioco da ragazzi, molto più semplice di un 2FA con Authelia. Naturalmente non è tutto rosa e fiori percHè come in ogni soluzione ci sono svantaggi. Questi iniziano quando non si usa il browser ma delle applicazioni dedicate come sullo smartphone, in questi scenari è difficile implementare mTLS.

Queste sono le mie esperienze con alcuni tipi di servizi, naturalmente il funzionamento dipende dal tipo di utilizzo che faccio io:

  • Home Assistant: funziona se usato con il browser e non con la Companion app (una PR è aperta). Non funzionano più le chiamate http da device non supportano mTLS. Al momento è più importante poter utilizzare l’app e quindi non uso mutual TLS.
  • Grafana: funziona senza problemi
  • Nodered: funziona senza problemi
  • Plex: vista l’esperienza con HA non ho neanche provato, non so se è possibile installare certificati sulla TV
  • Unifi: funziona senza problemi

Ho notato che l’esperienza di utilizzo dei certificati client risulta migliore con Firefox rispetto ai browser basati Chromium (Brave, Chrome, …). In Firefox si può dire al browser di ricordare la scelta e quindi non si è confrontati al avvio con la richiesta del certificato da usare. Questo mi dispiace perchè con Brave mi trovo bene.

Vi consiglio di provare anche voi mutual TLS.


Crediti Ispirazione articolo da guida di Romain Boulanger Foto copertina di Rúben Gál da Pixabay