Kort svar
SNI (Server Name Indication) er en TLS-extension hvor klienten allerede i Client Hello oplyser hvilket domæne den vil til. Det lader én server med én IP-adresse vælge det rigtige certifikat blandt mange — afgørende fordi serveren skal sende certifikatet før den ser noget HTTP (hvor Host-headeren ellers ville røbe domænet). Uden SNI får klienten serverens standardcertifikat, som ofte ikke matcher, og handshaken fejler.
Problemet SNI løser
TLS-handshaken sker før HTTP. Når serveren skal sende sit certifikat, har den endnu ikke set HTTP-requesten — og dermed ikke Host-headeren der fortæller hvilket domæne brugeren vil til. På en server med ét domæne pr. IP er det intet problem. Men i en verden hvor IPv4-adresser er knappe, deler hundredvis af sites typisk samme IP. SNI løser dette ved at flytte domænenavnet helt frem til Client Hello, hvor det er tilgængeligt allerede før certifikatet skal vælges. Hele rækkefølgen ses i TLS handshake forklaret.
Sådan virker det i praksis
Klienten sætter feltet server_name i sin Client Hello. Serveren læser det, slår op hvilket virtuelt host det matcher, og sender det tilhørende certifikat. Du kan se feltet i en handshake:
openssl s_client -connect example.com:443 -servername example.com # uden -servername sendes ingen SNI — serveren returnerer sit standardcertifikat openssl s_client -connect example.com:443
Prøv begge mod en server der hoster flere domæner: med -servername får du det rigtige certifikat, uden det får du standardcertifikatet — ofte for et helt andet domæne.
Hvad sker der uden SNI?
Sender klienten ingen SNI, gætter serveren — typisk ved at returnere det første eller default-certifikat. Det fører til en hostname mismatch hvis det ikke matcher det domæne brugeren bad om. To typiske årsager til manglende SNI:
- Meget gamle klienter (fx Windows XP's IE, Java før 7) understøtter slet ikke SNI.
- API-biblioteker og scripts der forbinder til en IP direkte, eller som ikke sætter servernavnet korrekt.
SNI i nginx: flere certifikater på én IP
Hver server-blok med sit eget server_name og certifikat fungerer som et virtuelt host. nginx vælger den rigtige ud fra SNI:
server {
listen 443 ssl;
server_name a.example.com;
ssl_certificate /etc/ssl/a/fullchain.pem;
ssl_certificate_key /etc/ssl/a/privkey.pem;
}
server {
listen 443 ssl;
server_name b.example.com;
ssl_certificate /etc/ssl/b/fullchain.pem;
ssl_certificate_key /etc/ssl/b/privkey.pem;
}
Begge lytter på samme IP og port; SNI afgør hvilket certifikat der serveres. Den server-blok der står først (eller har default_server) bruges når klienten ikke sender SNI.
Privatlivshullet: SNI sendes i klartekst
Fordi SNI sendes i Client Hello — før krypteringen er etableret — kan en aflytter se hvilket domæne du forbinder til, selv på en HTTPS-forbindelse. Det er et kendt privatlivsproblem. Løsningen er Encrypted Client Hello (ECH), der krypterer hele Client Hello inklusive SNI. ECH er under udrulning i moderne browsere og CDN'er, men er endnu ikke universelt. Som vi forklarer i HTTPS forklaret, lækker selve domænet altså stadig i de fleste forbindelser i dag.
Hvordan CertControl bruger SNI
Når CertControl scanner et endpoint, sender den korrekt SNI for det domæne den tester — præcis som en rigtig browser — så den får det rigtige certifikat valideret og ikke serverens standardcertifikat. Den markerer også endpoints hvor certifikatets navn ikke matcher det domæne der serveres, hvilket ofte skyldes en SNI- eller virtuel host-fejlkonfiguration.
Ofte stillede spørgsmål
Hvorfor er SNI nødvendigt?
Fordi serveren skal vælge og sende sit certifikat under TLS-handshaken, før den ser HTTP-requestens Host-header. SNI flytter domænenavnet frem til Client Hello, så serveren kan vælge det rigtige certifikat blandt flere på samme IP.
Hvad sker der hvis klienten ikke sender SNI?
Serveren returnerer sit standardcertifikat, som ofte ikke matcher det ønskede domæne. Resultatet er typisk en hostname mismatch eller en handshake-fejl. Det er derfor -servername er vigtigt når du tester med openssl.
Krypterer SNI hvilket domæne jeg besøger?
Nej, ikke i standard TLS. SNI sendes i klartekst i Client Hello, så en aflytter kan se domænet. Encrypted Client Hello (ECH) løser dette ved at kryptere hele Client Hello, men er endnu ikke universelt udbredt.
Kan jeg have flere certifikater på én IP uden SNI?
I praksis nej, ikke til navngivne domæner. Før SNI krævede hvert HTTPS-certifikat sin egen IP. SNI er netop det der gør virtuel hosting med separate certifikater på delt IP muligt.
Hvad er Encrypted Client Hello (ECH)?
En nyere TLS-mekanisme der krypterer hele Client Hello, inklusive SNI, så domænet ikke længere lækker til aflyttere. Det rulles gradvist ud i browsere og CDN'er, men kræver understøttelse i både klient og server.