MikroTik Dojo · prova di esistenza (OpenTimestamps) Versione: 1 Registrato il: 2026-11-03T15:55:21+00:00 Verifica: ots verify mikrotikdojo-2767-v1.txt.ots (o su https://opentimestamps.org) Indirizzo: https://mikrotikdojo.com/dojo/https-vero-sul-mikrotik-con-lets-encrypt/ ID: 2767 (post) Titolo: HTTPS vero sul MikroTik con Let's Encrypt Pubblicato: 2026-11-02T06:30:00Z Immagini (sha256 del file): e9570328d96299f03785fbc272f9eeec2321c67cdaae161f82e8314985a8fe1c https://mikrotikdojo.com/wp-content/uploads/2026/10/2767.jpg --- Contenuto (HTML originale, in italiano) ---

Il router ha una web interface, un'API, magari un VPN: tutta roba che gira in HTTPS. Ma con quale certificato? Di fabbrica RouterOS ne usa uno auto-firmato, e il browser protesta ad ogni accesso. In questo articolo ci facciamo dare da Let's Encrypt un certificato vero, riconosciuto da tutti i browser, gratis e automatico, usando il client ACME integrato in RouterOS 7. Lo facciamo per davvero in laboratorio: apriamo la porta giusta, guardiamo a pacchetto cosa succede sul filo, ci sbattiamo contro due fallimenti istruttivi, e alla fine sezioniamo il certificato ottenuto fino alla radice della sua catena di fiducia.

Riferimento concettuale: Certificati, CA e la catena di fiducia — cos'è una CA, cosa vuol dire "catena", DV vs OV/EV, OCSP/CRL, Certificate Transparency e CAA. Qui diamo per capiti quei termini.

Passo 1: cosa otteniamo, e cosa serve davvero

ACME (Automatic Certificate Management Environment, RFC 8555) è il protocollo con cui un server chiede a una Certificate Authority un certificato dimostrando di controllare il dominio, senza interventi manuali. Let's Encrypt è la CA gratuita più usata al mondo e parla ACME. RouterOS 7 ha il client ACME dentro: nessun software esterno.

C'è però un prezzo onesto da mettere in chiaro subito, perché è il cuore di tutto l'articolo. Per darti il certificato, Let's Encrypt deve verificare che quel nome sia tuo. Il metodo che useremo (la sfida http-01) funziona così: Let's Encrypt si collega al tuo nome sulla porta 80 e si aspetta di trovare lì un file che solo tu puoi aver messo. Quindi servono due cose:

Aprire la 80 al mondo non è gratis in termini di rischio: lo vedremo letteralmente nello sniffer al Passo 5. Per questo la apriamo solo per la finestra dell'emissione e la richiudiamo dopo (Passo 9).

Passo 2: il comando

Su RouterOS 7 moderno (qui una 7.25 stable) il comando è add-acme. Una riga sola:

/certificate/add-acme \
    directory-url=https://acme-v02.api.letsencrypt.org/directory \
    domain-names=chr01test.mikrotikdojo.com

Il directory-url è il punto d'ingresso dell'API di Let's Encrypt (da lì il router scopre tutti gli altri endpoint). domain-names è il nome (o i nomi) per cui vogliamo il certificato. Esiste anche un vecchio comando enable-ssl-certificate, legato a IP Cloud: funziona, ma add-acme è quello attuale e gestisce il rinnovo automatico da solo.

Perché vada a buon fine, il servizio www del router dev'essere acceso sulla porta 80: è lui che risponderà alla sfida.

Passo 3: la sfida http-01, raccontata

Quando lanci il comando, dietro le quinte si svolge una piccola cerimonia. Il router bussa all'API di Let's Encrypt e dice: «vorrei un certificato per chr01test.mikrotikdojo.com». Let's Encrypt risponde con un gettone — una stringa casuale, il token — e un compito: «mettilo a disposizione all'indirizzo http://chr01test.mikrotikdojo.com/.well-known/acme-challenge/<token>, poi avvisami».

Qui entra in scena il servizio www del router. Non deve fare nulla di speciale: il client ACME gli affida il gettone, e il www lo tiene pronto a quel preciso indirizzo come un portinaio che custodisce una busta col tuo nome. Quando Let's Encrypt verrà a bussare sulla porta 80 e chiederà proprio quella busta, il portinaio gliela porgerà. Il gettone che il router consegna non è il token nudo: è token.impronta-della-chiave — la risposta è legata matematicamente alla chiave privata del router, così nessun altro, pur conoscendo il token, potrebbe fabbricare la risposta giusta. Let's Encrypt la confronta con quello che si aspetta; se combacia, è convinto che quel nome è davvero tuo, e firma il certificato.

Tutto questo scambio — il bussare, il gettone, la busta sulla 80 — avviene in HTTP in chiaro. Ed è esattamente perché è in chiaro che possiamo guardarlo a pacchetto.

Passo 4: al microscopio — e il primo fallimento (dietro NAT)

Mettiamo uno sniffer sull'interfaccia del router rivolta a Internet e lanciamo il comando. Il primo tentativo finisce così:

/certificate print detail
 0 Ea  acme-status="http-01 challenge validation failed,
        urn:ietf:params:acme:error:connection - Fetching
        http://chr01test.mikrotikdojo.com/.well-known/acme-challenge/0WwwuU4...PGwU:
        Error getting validation data"

Guardiamo i pacchetti, non le parole. Il verso in uscita funziona: il router raggiunge l'API di Let's Encrypt sulla 443 (172.65.32.248), apre il dialogo, crea l'account e ottiene il token.

# router  →  API di Let's Encrypt (443): connessione aperta
router.33768  > 172.65.32.248.443:  Flags [S]      # SYN verso l'API
172.65.32.248.443  > router.33768:  Flags [S.]     # SYN-ACK: handshake

Il problema è il verso in entrata. E nello sniffer si vede addirittura un validatore di Let's Encrypt (51.178.174.226) provarci — e non riuscirci: 320 tentativi di connessione sulla porta 80, nessuno che vada a buon fine, e zero GET della challenge completati.

# un nodo di validazione di Let's Encrypt bussa sulla :80... a vuoto
51.178.174.226.51xxx  > router.80:  Flags [S]      # SYN  \
51.178.174.226.51xxx  > router.80:  Flags [S]      # SYN   }  320 SYN, mai un handshake completo
51.178.174.226.51xxx  > router.80:  Flags [S]      # SYN  /
# GET /.well-known/acme-challenge/... ricevuti e serviti: 0

Ecco spiegato Error getting validation data: la busta non è stata consegnata perché l'inoltro della porta 80 dall'esterno non stava ancora recapitando (il SYN arriva, ma la risposta del router non torna indietro → l'handshake non si chiude). Lezione uno: la sfida ha due versi — in uscita verso l'API (basta il NAT normale) e in entrata sulla 80 (serve il port forwarding, fatto bene). Lo sistemiamo e riproviamo.

Passo 5: apri la 80… e il mondo se ne accorge in pochi secondi

Inoltrata la porta 80, rilanciamo. E qui succede una cosa che da sola vale l'articolo. Guardiamo chi bussa sulla 80 appena diventa pubblica:

# SYN in arrivo sulla porta 80, conteggiati per IP sorgente (dallo sniffer)
   1474  40.160.24.53        <-- un solo IP: 1474 tentativi di connessione
     14  44.252.14.108
      7  47.129.199.229
      7  13.60.43.228
      7  13.51.178.31

Gli IP che fanno 6–14 tentativi e completano la connessione sono i nodi di validazione di Let's Encrypt (torniamo tra un attimo sul perché sono tanti). Ma quel primo — 1474 SYN da un indirizzo solo — non è Let's Encrypt: è uno scanner. Appena una porta 80 si affaccia su Internet, i bot che perlustrano la rete la trovano in secondi e cominciano a martellarla. Non è teoria: è successo in diretta, nel nostro lab, la prima volta che abbiamo aperto.

E il martellamento ha un effetto collaterale che fa fallire l'emissione. Il servizio www di RouterOS ha un tetto di sessioni contemporanee (max-sessions, di fabbrica 20). Il diluvio dello scanner lo satura; oltre il tetto il router rifiuta le connessioni in eccesso con un RST. E tra le vittime del rifiuto finisce una delle prospettive di validazione di Let's Encrypt. Risultato:

 acme-status="http-01 challenge validation failed,
   ... During secondary validation: ...
   Timeout during connect (likely firewall problem)"

E lo si vede, pacchetto per pacchetto — è HTTP in chiaro, header e corpo. Un vero nodo di Let's Encrypt chiede la challenge, e il router gli serve il gettone:

# la challenge richiesta da un nodo LE
23.178.112.104 > router:80
    GET /.well-known/acme-challenge/GBjyI0nclef5ifJguzhLO56dde_AMz8PDukkBYRiR3Q HTTP/1.1
    Host: chr01test.mikrotikdojo.com
    User-Agent: Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)
    Accept: */*

# il router risponde, e nel CORPO c'è il gettone (token . impronta-della-chiave)
router:80 > 23.178.112.104
    HTTP/1.1 200 OK
    Content-Length: 87

    GBjyI0nclef5ifJguzhLO56dde_AMz8PDukkBYRiR3Q.NGo2y4WTCYleqL9xJ957-d1OkuWVBem0EJqYT4SGOqs
    \_________ token _________________________/ \________ impronta della chiave __________/

Ma i conteggi sulla porta 80 raccontano la calca — e perché una prospettiva resta tagliata fuori:

SYN in ingresso : 1539     (di cui 1474 da un solo scanner, 40.160.24.53)
SYN-ACK         :  736
RST dal router  :  796     <-- connessioni stroncate oltre max-sessions=20

Il portinaio funziona (il 200 OK lo serve a chi riesce a parlargli); non è un errore di configurazione, è la calca alla porta a impedirgli di servire tutti — e tra i non serviti finisce una prospettiva di validazione di Let's Encrypt.

Perché Let's Encrypt valida da più punti: MPIC

Qui va spiegato il «secondary validation». Fino a qualche anno fa una CA validava da un solo punto della rete. Era un punto debole enorme. Internet instrada i pacchetti con BGP, un protocollo che funziona a fiducia: una rete annuncia «il blocco di indirizzi X si raggiunge da me» e le altre le credono. Una rete malevola può annunciare il prefisso di una vittima — è il dirottamento BGP (BGP hijack) — e per qualche minuto attirare a sé quel traffico. Se lo fa durante la validazione, il validatore della CA finisce sul server dell'attaccante, che risponde alla sfida e si porta a casa un certificato vero e fidato per un dominio che non è suo.

La contromisura è la MPIC (Multi-Perspective Issuance Corroboration), adottata da Let's Encrypt tra il 2024 e il 2025 e oggi richiesta dal CA/Browser Forum. Let's Encrypt non valida da un posto solo: lo fa da più prospettive sparse su reti, cloud e regioni diverse (ecco perché nello sniffer vediamo tanti IP che bussano). Un dirottamento BGP di solito è locale: si propaga a una parte di Internet, non a tutta. Le prospettive «lontane», che raggiungono ancora il server vero, sono in disaccordo con quella dirottata → niente quorum → la CA rifiuta. Per battere MPIC servirebbe un dirottamento quasi globale: enorme e rumorosissimo.

La chicca: è proprio questo scudo ad averci fatto fallire sopra. Una prospettiva non riusciva a connettersi (colpa nostra, il www saturo) e la logica anti-dirottamento, non avendo corroborazione piena, ha detto no. Il meccanismo che ferma gli attaccanti ha fermato anche la nostra porta intasata.

Passo 6: la tentazione sbagliata, e due difese vere

La reazione istintiva è: «allora accetto sulla 80 solo gli IP di Let's Encrypt». Non si può, ed è voluto. Let's Encrypt non pubblica l'elenco degli IP da cui valida, proprio per la MPIC: le prospettive cambiano senza preavviso e sono distribuite apposta. Una address-list = "Let's Encrypt" si romperebbe al primo cambio — e scoraggiano esplicitamente di farla.

La difesa giusta non filtra per sorgente, ma per comportamento: chi apre troppe connessioni contemporanee alla 80 è, con ogni probabilità, uno scanner; i nodi di Let's Encrypt ne aprono poche ciascuno. Una regola mette chi floda in una lista dinamica e lo scarta, senza toccare la validazione:

/ip firewall filter add chain=input protocol=tcp dst-port=80 \
    connection-state=new connection-limit=20,32 \
    action=add-src-to-address-list address-list=port80-flood \
    address-list-timeout=10m
/ip firewall filter add chain=input protocol=tcp dst-port=80 \
    src-address-list=port80-flood action=drop

Chi supera 20 connessioni nuove concorrenti dallo stesso indirizzo (il ,32 conta per /32, cioè per singolo IP) finisce nella lista port80-flood ed è scartato per 10 minuti. L'abbiamo messa alla prova in laboratorio con un flood vero, e aggancia:

/ip firewall address-list print where list=port80-flood
 #   LIST          ADDRESS        TIMEOUT
 0 D port80-flood  198.51.100.7   8m24s        <-- listato per comportamento, non per IP noto

/ip firewall filter print stats
 #  CHAIN  ACTION                    PACKETS
 0  input  add-src-to-address-list       80
 1  input  drop                         475    <-- flood scartato

In alternativa (o in aggiunta), il tampone più semplice è alzare il tetto delle sessioni contemporanee del www, così anche il rumore residuo non soffoca i nodi LE:

/ip service set www max-sessions=100

Rilanciamo l'emissione. Stavolta tutte le prospettive passano e nel log compare la riga che aspettavamo:

 certificate,info acme cert 'acme_cert_chr01test.mikrotikdojo.com' imported,
   next update scheduled at 2027-01-10T...Z

Fatto: certificato emesso e importato, con il rinnovo già schedulato da solo. (La via per evitare del tutto la porta aperta esiste — la sfida DNS-01, un record TXT invece della 80 — e la trattiamo nella KB.)

Passo 7: il certificato, sezionato

Ora il pezzo interessante: cosa ci ha dato davvero Let's Encrypt. Tiriamo fuori i campi del certificato (qui letti con openssl, ma li mostra anche RouterOS):

subject      CN = chr01test.mikrotikdojo.com
issuer       C = US, O = Let's Encrypt, CN = YR1
validità     89 giorni  (Not Before ... Not After, ~3 mesi)
chiave       RSA 2048 bit · firma sha256WithRSAEncryption

X509v3 Subject Alternative Name:   DNS:chr01test.mikrotikdojo.com
X509v3 Key Usage (critical):       Digital Signature, Key Encipherment
X509v3 Extended Key Usage:         TLS Web Server Authentication
X509v3 Basic Constraints (critical): CA:FALSE
X509v3 Certificate Policies:       2.23.140.1.2.1
Authority Information Access:       CA Issuers - URI:http://yr1.i.lencr.org/
X509v3 CRL Distribution Points:    http://yr1.c.lencr.org/5.crl
CT Precertificate SCTs:            (2 Signed Certificate Timestamp)

Cinque cose da leggere con attenzione, tutte attualissime:

Nota pratica: il nostro chr01test.mikrotikdojo.com è finito, da questo momento, nei log CT pubblici per sempre. Non è un segreto (è un sottodominio nostro), ma va saputo: ogni certificato che emetti è un fatto pubblico e permanente.

Vai a verificarlo: cercalo nei log pubblici

Quelle due SCT non sono un vanto teorico: puoi controllarle tu. Un motore che aggrega i log di Certificate Transparency è crt.sh. Cerca il nome dal browser, oppure interroga la sua API in JSON:

# tutti i certificati emessi per il nome (o per % = tutti i sottodomini)
curl 'https://crt.sh/?q=chr01test.mikrotikdojo.com&output=json' | jq .
curl 'https://crt.sh/?q=%25.mikrotikdojo.com&output=json' | jq .

La risposta, per ogni certificato trovato, ha questa forma:

{
  "id": 1......,                       <-- id nel registro CT
  "issuer_name": "C=US, O=Let's Encrypt, CN=YR1",
  "name_value": "chr01test.mikrotikdojo.com",
  "not_before": "2026-10-30T16:37:38",
  "not_after":  "2027-01-28T16:37:37"
}

Due usi, uno curioso e uno serio. Curioso: è la prova che il nostro esperimento è ora un fatto pubblico e permanente. Serio: interrogando %25.tuodominio vedi tutti i certificati mai emessi per il tuo dominio — e se ne spunta uno che non hai chiesto tu, hai scoperto una mis-issuance. È così che Certificate Transparency trasforma un attacco silenzioso in un fatto visibile. (Un certificato appena emesso può metterci da qualche minuto a qualche ora a comparire negli aggregatori.)

Passo 8: la catena di fiducia, fino alla radice

Un certificato non vive da solo: si incatena fino a una radice di cui il tuo dispositivo già si fida. Seguiamo la catena scaricando ogni anello (l'indirizzo da cui prenderlo è nel campo CA Issuers di ciascun certificato):

chr01test.mikrotikdojo.com      (foglia · DV · 90 giorni · CA:FALSE)
   └─ emessa da  YR1         (intermedia · 2025→2028 · CA:TRUE pathlen:0 · EKU=solo TLS server)
        └─ emessa da  ISRG Root YR     (radice · 2026→2032)
             └─ CROSS-FIRMATA da  ISRG Root X1   (la radice storica, in tutti i dispositivi)

C'è una sorpresa in fondo, ed è la lezione più bella. La radice non è la celebre ISRG Root X1, ma una radice nuova, «ISRG Root YR» (comparsa nel 2026). Come fa un dispositivo vecchio, che non la conosce, a fidarsi? Perché ISRG Root YR è cross-firmata da ISRG Root X1, che è dentro ogni browser e sistema operativo da anni. Il dispositivo che non riconosce «Root YR» risale un altro gradino e arriva a «Root X1», che conosce — e si fida. È esattamente così che una CA introduce una radice nuova senza aspettare che milioni di dispositivi la ricevano: la fa firmare da una radice già fidata. L'abbiamo visto sul campo, non raccontato a memoria.

Noti anche che l'intermedia YR1 ha EKU = solo TLS Web Server e pathlen:0: anche l'anello di mezzo è limitato a ciò che deve fare — non può firmare altre CA, né certificati per usi diversi dal TLS server. La catena di fiducia è anche una catena di poteri ristretti.

Passo 9: metterlo in uso, e richiudere

Il certificato c'è: ora lo si usa dove serve. Per avere il Webfig in HTTPS vero, lo si assegna al servizio www-ssl:

/ip service set www-ssl certificate=acme_cert_chr01test.mikrotikdojo.com disabled=no

Il rinnovo è automatico (RouterOS lo rifà prima della scadenza), ma attenzione: al rinnovo serve di nuovo la sfida, quindi la porta 80 dovrà essere di nuovo raggiungibile in quel momento. Se l'avevi aperta solo per l'emissione, pianifica la finestra del rinnovo — oppure passa alla sfida DNS-01 (vedi KB), che non apre porte.

E adesso richiudi la 80: tolto il port forwarding, sparisce anche tutto il traffico degli scanner che abbiamo visto al Passo 5. La superficie esposta si riduce a zero. La 80 si riapre solo quando serve, per il tempo che serve.

Domande frequenti

Posso usarlo senza un mio dominio, con il nome di IP Cloud del MikroTik?

Sì: il nome ...sn.mynetname.net di IP Cloud risolve verso il router e vale come nome pubblico per la sfida. Tieni però presente che quel nome contiene il numero di serie del dispositivo in chiaro, e che il certificato (quindi quel nome) finirà nei log CT pubblici per sempre. Un dominio tuo è più pulito.

Devo per forza aprire la porta 80? Non è un rischio?

Per la sfida http-01 sì, serve la 80 in entrata — e il rischio l'abbiamo mostrato (gli scanner arrivano in secondi). Mitighi tenendola aperta solo nella finestra di emissione/rinnovo e limitando i flood per ritmo, non per IP. Per non aprire nessuna porta esiste la sfida DNS-01 (un record TXT nel DNS): la trattiamo nella KB sui certificati.

Perché non basta accettare solo gli IP di Let's Encrypt sulla 80?

Perché Let's Encrypt non li pubblica, di proposito: valida da molte prospettive che cambiano senza preavviso (è la MPIC anti-dirottamento). Una allow-list si romperebbe, ed è sconsigliata dalla CA stessa.

Il certificato dura 90 giorni: devo ricordarmi di rinnovarlo?

No: add-acme schedula il rinnovo da solo. Il tuo compito è assicurarti che, nel momento del rinnovo, la condizione della sfida sia di nuovo soddisfatta (porta 80 raggiungibile, o DNS-01 configurato).

Posso avere un certificato ECDSA invece di RSA?

Sì, Let's Encrypt emette anche su chiavi a curva ellittica; nel comando si sceglie il tipo di chiave. Qui abbiamo lasciato il default (RSA 2048) per leggibilità, ma ECDSA dà chiavi più piccole a parità di robustezza — comoda su un router. La differenza tra le due famiglie è spiegata nella KB sui certificati.

Provato in laboratorio su CHR RouterOS 7.25 (stable), con uno sniffer sull'interfaccia rivolta a Internet. Emissione reale da Let's Encrypt (directory di produzione) per un sottodominio di prova, via /certificate/add-acme con sfida http-01 e il servizio www sulla porta 80 (inoltrata dal bordo). Catturati i tre esiti: fallimento «Error getting validation data» (80 non raggiungibile in entrata), fallimento «During secondary validation … Timeout during connect» (il www con max-sessions=20 saturato dal diluvio di SYN di uno scanner — 1474 tentativi da un solo IP in pochi secondi dall'apertura — che stronca una prospettiva di validazione MPIC di Let's Encrypt), e successo dopo www max-sessions=100 con importazione del certificato e rinnovo auto-schedulato. Il certificato ottenuto è stato sezionato con openssl: DV (policy 2.23.140.1.2.1), validità ~90 giorni, identità solo-SAN, EKU solo TLS-server, nessuna URL OCSP (solo CRL), due SCT di Certificate Transparency; catena ricostruita scaricando gli anelli — foglia → intermedia YR1 → ISRG Root YR (2026) cross-firmata da ISRG Root X1; presenza del certificato nei log di Certificate Transparency verificabile su crt.sh. Il sottodominio chr01test.mikrotikdojo.com è reale (già nei log CT); gli IP e i percorsi interni del laboratorio sono omessi.