MikroTik Dojo · prova di esistenza (OpenTimestamps) Versione: 1 Registrato il: 2026-11-09T07:36:26+00:00 Verifica: ots verify mikrotikdojo-2771-v1.txt.ots (o su https://opentimestamps.org) Indirizzo: https://mikrotikdojo.com/dojo/acme-ca-interna-mikrotik/ ID: 2771 (post) Titolo: ACME in casa: la tua CA interna sul MikroTik Pubblicato: 2026-11-09T06:30:00Z Immagini (sha256 del file): 1916e0e5c295af7d044f33d74340ec08c77bb626b09230c51e0a4583d2739152 https://mikrotikdojo.com/media/2026/10/2771.jpg --- Contenuto (HTML originale, in italiano) ---
Nell'howto su Let's Encrypt abbiamo preso un certificato pubblico, aprendo la porta 80 al mondo. Ma per i servizi che non vuoi (o non puoi) esporre su Internet — il Webfig, l'API, una VPN interna, un server che vive solo in LAN — c'è una via molto più pulita. Visto che ACME è uno standard, il client integrato in RouterOS non è legato a Let's Encrypt: puoi puntarlo a una CA tutta tua, dentro la tua rete. Il router ottiene e rinnova da solo i certificati della tua PKI interna, con la stessa automazione, senza aprire niente verso l'esterno. Lo montiamo per davvero in laboratorio.
Riferimento concettuale: Certificati, CA e la catena di fiducia — root, intermedia, foglia, trust store, ACME e le sue sfide.
Una CA pubblica come Let's Encrypt è perfetta per ciò che è esposto su Internet con un nome pubblico. Ma ha due requisiti che in LAN diventano scomodi: un nome DNS pubblico e una sfida raggiungibile dall'esterno (la porta 80, o un record DNS pubblico). Per il pannello di gestione di un router, o per un servizio su un nome tipo router.azienda.interna, niente di tutto questo esiste né deve esistere.
La soluzione è una CA interna: una tua Certificate Authority che emette certificati per i tuoi nomi interni. La chiave di tutto è un solo parametro del comando ACME, il directory-url: lo fai puntare alla tua CA invece che a Let's Encrypt, e il resto del meccanismo (emissione, rinnovo automatico) è identico.
Ci serve un server ACME su una piccola macchina Linux della LAN. Usiamo step-ca di smallstep, che parla ACME nativamente (alternative: la CA integrata in Caddy, oppure Boulder, che è letteralmente il software con cui gira Let's Encrypt).
1. Installa i due binari: il CLI step e il server step-ca. Dalle release ufficiali (sostituisci le versioni con le ultime):
CA=0.30.2 ; CLI=0.31.0 ; ARCH=amd64
curl -LO https://github.com/smallstep/certificates/releases/download/v$CA/step-ca_linux_${CA}_${ARCH}.tar.gz
curl -LO https://github.com/smallstep/cli/releases/download/v$CLI/step_linux_${CLI}_${ARCH}.tar.gz
tar xzf step-ca_linux_*.tar.gz ; tar xzf step_linux_*.tar.gz
sudo install step-ca_*/bin/step-ca step_*/bin/step /usr/local/bin/
step version # verifica
(In alternativa, smallstep pubblica anche i pacchetti .deb.)
2. Inizializza la CA: crea la gerarchia (root + intermedia) e attiva un provisioner ACME. Ti verrà chiesta una password con cui proteggere le chiavi:
step ca init \
--deployment-type standalone \
--name "Azienda Internal CA" \
--dns ca.azienda.interna \
--address :9000 \
--provisioner admin@azienda.interna \
--acme
3. Avvia il server. Per una prova veloce, in primo piano:
step-ca $(step path)/config/ca.json
Per una vera installazione, come servizio systemd (così riparte da solo; la password delle chiavi in un file letto all'avvio):
[Unit]
Description=step-ca
After=network.target
[Service]
ExecStart=/usr/local/bin/step-ca /etc/step-ca/config/ca.json --password-file /etc/step-ca/pw
Restart=on-failure
[Install]
WantedBy=multi-user.target
Da qui la CA è in ascolto e la sua directory ACME risponde a https://ca.azienda.interna:9000/acme/acme/directory. La root appena creata è la tua ancora di fiducia: il file che renderà fidati, nei tuoi dispositivi, tutti i certificati che emetterai (è il prossimo passo).
Questo è il passaggio concettualmente più importante, ed è ciò che distingue una PKI privata legittima da un inganno. Il router — come qualunque dispositivo — si fiderà della tua CA solo se la sua root è nel suo trust store. E ce la metti tu, perché il router è tuo. Carichi la root sul router e la importi:
/certificate import file-name=root_ca.crt passphrase=""
/certificate print where common-name~"Internal CA"
# NAME TRUST-STORE COMMON-NAME
0 T root_ca.crt_0 all Azienda Internal CA Root CA
Il flag T dice che il router ora si fida di quella CA. (Serve anche perché la directory ACME è in HTTPS: senza la root, il router non si fiderebbe nemmeno del server della CA.) Infine, dato che useremo il nome della CA, facciamolo risolvere dal router:
/ip dns static add name=ca.azienda.interna address=192.0.2.10
È qui la differenza con l'Howto 3 (la falsificazione): la fiducia non è stata «rubata», è stata concessa, da chi possiede il dispositivo, in modo esplicito e consapevole. Su un dispositivo che non controlli, questo passo non potresti farlo — ed è esattamente perché un MITM fallisce.
Identica a quella pubblica, cambia solo il directory-url:
/certificate/add-acme \
directory-url=https://ca.azienda.interna:9000/acme/acme/directory \
domain-names=router.azienda.interna
Il router crea l'account sulla tua CA, riceve il token, lo serve sulla 80, la tua CA verifica, e firma. In pochi secondi il log conferma:
certificate,info new acme cert 'acme_cert_router.azienda.interna' created
certificate,info acme cert 'acme_cert_router.azienda.interna' imported,
next update scheduled at ...
Mettiamo lo sniffer e confrontiamo con l'howto pubblico. Lì la sfida arrivava da molti nodi sparsi per il mondo (la MPIC di Let's Encrypt), in mezzo al rumore degli scanner. Qui la scena è spoglia e pulita: un solo validatore, la tua CA, che bussa una volta sola.
E siccome la sfida http-01 è in HTTP in chiaro, si vede tutto — header e corpo. Un solo validatore, la tua CA (192.0.2.10), chiede la busta al router (192.0.2.20):
# 1) la CA chiede la challenge
192.0.2.10 > 192.0.2.20:80
GET /.well-known/acme-challenge/1GIDHB0NYfmbrnugcQe3taApSwFesbS4 HTTP/1.1
Host: router.azienda.interna
User-Agent: Go-http-client/1.1 # step-ca è scritto in Go
Accept-Encoding: gzip
# 2) il router consegna il gettone — ed ecco il CORPO della risposta:
192.0.2.20:80 > 192.0.2.10
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Length: 76
1GIDHB0NYfmbrnugcQe3taApSwFesbS4.E0WNGhlk4xi7sixV7prc-WktIWdAFqzU6UJ1OVBHmZ4
\________ token ________________/ \______ impronta della chiave dell'account ______/
Il corpo è esattamente token + «.» + impronta della chiave: la prova che chi risponde possiede la chiave privata dell'account. Il dialogo ACME vero e proprio, invece, viaggia in TLS verso la porta 9000 della CA — lì il contenuto è cifrato, si vede solo l'handshake:
192.0.2.20.35386 > 192.0.2.10.9000: Flags [S] # SYN \
192.0.2.10.9000 > 192.0.2.20.35386: Flags [S.] # SYN-ACK } handshake TLS,
192.0.2.20.35386 > 192.0.2.10.9000: Flags [P.] # dati / contenuto CIFRATO
Due canali, due nature: la sfida in chiaro sulla 80 (il gettone è pubblico, non è un segreto), il protocollo cifrato sulla 9000 (lì viaggiano account e ordini).
Nessuna MPIC (non serve: la CA e il router sono nella stessa rete fidata, non c'è nessun dirottamento BGP da temere). Nessuno scanner, perché non abbiamo aperto niente su Internet. La superficie esposta verso il mondo è zero.
Guardiamo cosa ha firmato la tua CA:
issuer O=Azienda Internal CA, CN=Azienda Internal CA Intermediate CA
subject CN = router.azienda.interna
SAN DNS:router.azienda.interna
chiave RSA 2048 · tls-server
validità 24 ore <-- vita brevissima (default di step-ca)
acme-status next update scheduled ... <-- rinnovo automatico
Nota la validità di 24 ore. In una CA pubblica sarebbe un incubo di gestione; qui è un lusso che puoi permetterti, perché il rinnovo è automatico e la CA è in casa tua. Più breve è la vita, meno conta la revoca: se un certificato interno fosse compromesso, scadrebbe comunque entro un giorno. È la stessa filosofia «vita breve invece di revoca» delle CA pubbliche, portata all'estremo perché qui non costa nulla.
L'emittente è la tua organizzazione, non Let's Encrypt. Il nome è un nome interno. Tutto questo esiste solo dentro la tua rete, per i tuoi dispositivi che si fidano della tua root.
Assegni il certificato al servizio, come al solito:
/ip service set www-ssl certificate=acme_cert_router.azienda.interna disabled=no
E qui viene il bello: non devi ricordarti nulla. Il router rinnova da solo contro la tua CA, che è sempre raggiungibile in LAN — nessuna porta da aprire al momento del rinnovo, nessuna finestra da pianificare, nessun nome pubblico da mantenere. Una volta impostato, i tuoi servizi interni hanno certificati validi e sempre freschi, per sempre, senza che tu ci pensi più.
Sì: è PKI privata, lo strumento standard delle aziende per i servizi interni. La tua CA è fidata solo dai dispositivi su cui tu installi la tua root. Non emette nulla di valido per il resto del mondo, e non intacca le CA pubbliche. È l'opposto di un attacco: la fiducia è concessa dal proprietario, non rubata.
Sì: ogni dispositivo che deve fidarsi dei certificati interni deve avere la tua root nel trust store. In azienda lo si distribuisce con gli strumenti di gestione (MDM, group policy); sul router lo abbiamo fatto a mano con /certificate import.
Sì: la tua CA può usare la sfida dns-01 (un record TXT) o altre modalità. La http-01 qui è comoda perché tutto è in LAN e il rischio è nullo, ma non sei obbligato alla porta 80 nemmeno internamente.
Il certificato auto-firmato di RouterOS non è firmato da nessuna CA: ogni dispositivo lo vede come «sconosciuto» e protesta. Con una CA interna, invece, una sola root (la tua) rende fidati tutti i certificati di tutti i tuoi servizi interni — e li rinnova da sola.
Provato in laboratorio su CHR RouterOS 7.25 (stable). CA interna reale con step-ca (smallstep, binari step-ca 0.30.2 + step 0.31.0 installati su una box Debian/Ubuntu) e provisioner ACME, sullo stesso segmento del router. Importata la root sul CHR (/certificate import → flag T TRUSTED), impostato il DNS statico del nome della CA, ed emesso un certificato via /certificate/add-acme con directory-url verso la CA interna e sfida http-01: emissione e importazione confermate nel log, con rinnovo automatico schedulato. Certificato risultante: emittente Azienda Internal CA (intermedia), CN/SAN router.azienda.interna, RSA 2048, validità 24 ore. Cattura sul filo: un unico validatore interno (la CA) con GET /.well-known/acme-challenge/… → HTTP/1.1 200 OK, e il dialogo ACME in TLS verso la porta della CA. Nessuna esposizione su Internet. Indirizzi di esempio nel range di documentazione; nomi e IP reali del laboratorio omessi.