Håll VPN:ens rot-CA offline och utfärda ändå certifikat
Håll rotnyckeln utanför nätverket, signera lövcertifikat med en mellanliggande CA, publicera en CRL i tid och testa kedjan innan den första klienten ansluter.
Din VPN svarar på anslutningar klockan 3 på natten medan maskinen som signerar dess certifikat står avstängd i en låda. En klient som validerar servercertifikatet kontaktar aldrig din CA, så CA:n behöver inte vara nåbar för någon anslutning. Den del som kräver planering är dagen då ett certifikat måste utfärdas, förnyas eller återkallas medan rotnyckeln förblir inlåst.
Vad en anslutning faktiskt validerar
När OpenVPN-klienten ansluter går den igenom signaturkedjan från serverns lövcertifikat upp till ett CA-certifikat som den redan litar på, kontrollerar giltighetsfönstret och, om profilen säger det, slår upp en återkallningslista. Den letar aldrig upp din rot-CA. Servern gör spegelbilden för klientcertifikat. Vid anslutningstillfället finns bara lövet, mellanliggande certifikat och det förtroendepaket du distribuerade tidigare.
Det som faktiskt misslyckas är en av tre saker: signeringsnyckeln är otillgänglig vid utfärdande, en återkallningslista har blivit inaktuell, eller klientens förtroendepaket är äldre än kedjan servern presenterar. Det första är ett processproblem; de andra två är distributionsproblem. Ingen av dem kräver att rotnyckeln är online, och en hanterad VPN-tjänst som kräver ett privat certifikat för tunnelautentisering flyttar bara signeringsbehörigheten till leverantören. Azure punkt-till-plats fungerar omvänt: du laddar upp ett rotcertifikat och certifikat signerade under det betraktas som betrodda, så fråga vem som signerar, vem som validerar och hur ett certifikat dras tillbaka tidigt.
Bygg roten på en värd som aldrig får en adress
En offline-rot används sällan: för att signera certifikatet för den mellanliggande CA:n och senare för att förnya eller återkalla det. Allt annat sker en nivå lägre. Gör rotarbetet på en maskin som hålls utanför nätverket, om möjligt från ett live-system, och anteckna vem som var i rummet. Kommandona förutsätter OpenSSL 1.1.1 eller nyare, eftersom -addext inte finns i äldre byggen.
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out root.key
openssl req -x509 -new -key root.key -sha256 -days 7300 \
-subj "/CN=Example VPN Root CA" -out root.crt \
-addext "basicConstraints=critical,CA:TRUE" \
-addext "keyUsage=critical,keyCertSign,cRLSign"
Skapa mellanliggande certifikat på signeringsvärden och ta bara med dess begäran till offline-maskinen. Roten signerar begäran med noll sökvägslängd, så den mellanliggande CA:n får signera slutpunktscertifikat men får inte skapa en annan CA under sig. Den enda utökningen hindrar en komprometterad signeringsvärd från att skapa en rotlikvärdig behörighet. Använd ECDSA bara om varje klient kör OpenVPN 2.4 eller nyare; generera annars RSA-nycklar och behåll samma flöde.
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out intermediate.key
openssl req -new -key intermediate.key -subj "/CN=Example VPN Intermediate CA" -out intermediate.csr
openssl x509 -req -in intermediate.csr -CA root.crt -CAkey root.key \
-CAcreateserial -days 3650 -sha256 -extfile intermediate.ext -out intermediate.crt
intermediate.ext innehåller basicConstraints=critical,CA:TRUE,pathlen:0, keyUsage=critical,keyCertSign,cRLSign och authorityKeyIdentifier=keyid:always. Lägg tillbaka rotnyckeln i dess kassaskåp innan signeringsvärden ansluts igen. Om roten måste kunna återkalla mellanliggande certifikat, signera det med openssl ca -config root.cnf -extensions intermediate_ca mot en index.txt på rotnivå i stället för openssl x509 -req, så att serienumret registreras; skicka sedan den resulterande rotlistan i klientprofilen, där en filbaserad crl-verify läser den vid start. Skicka klienterna ett paket med båda CA-certifikaten; ett löv ensamt valideras inte mot roten.
Utfärda löv från mellanliggande CA, med en databas
Signering med openssl x509 -req fungerar tills du behöver återkalla, eftersom ingenting registrerar serienumret. Använd openssl ca från det första certifikatet så att serienummer, utgång och återkallningsstatus lever i en enda databas. Skapa databasfilerna en gång och peka sedan konfigurationen mot dem:
mkdir -p /etc/vpn-ca/intermediate/newcerts
touch /etc/vpn-ca/intermediate/index.txt
echo 1000 > /etc/vpn-ca/intermediate/serial
echo 1000 > /etc/vpn-ca/intermediate/crlnumber
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /etc/vpn-ca/intermediate
database = $dir/index.txt
new_certs_dir = $dir/newcerts
serial = $dir/serial
crlnumber = $dir/crlnumber
certificate = $dir/intermediate.crt
private_key = $dir/intermediate.key
default_md = sha256
default_days = 365
default_crl_days = 30
unique_subject = no
policy = policy_any
[ policy_any ]
commonName = supplied
[ server_cert ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = serverAuth
subjectAltName = @server_names
[ client_cert ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = clientAuth
[ server_names ]
DNS.1 = vpn.example.com
Raden för nyckelanvändning förutsätter en ECDSA-nyckel; lägg till keyEncipherment för RSA. Ge varje klient sitt eget vanliga namn, eftersom OpenVPN identifierar en anslutning efter det fältet, och två bärbara datorer som delar CN=vpn-client kan inte skiljas i loggar, i client-config-dir-regler eller i någon push per användare, och du förlorar den tilldelning som gör ett återkallningsbeslut försvarbart. Utfärda och validera ett löv så här:
openssl req -new -key alice.key -subj "/CN=alice-laptop" -out alice.csr
openssl ca -config intermediate.cnf -extensions client_cert -in alice.csr -out alice.crt -batch
openssl verify -CAfile ca-bundle.crt -untrusted intermediate.crt alice.crt
Håll signeringsnyckeln bakom en policygräns i stället för att kopiera den till VPN-värden: en liten tjänst som autentiserar begäran, kontrollerar det vanliga namnet mot en tillåtelselista och bara returnerar certifikatet. Logga varje serienummer; loggen är den enda länken mellan ett certifikat och personen som bad om det.
Publicera återkallelse utan att väcka roten
Klientcertifikat återkallas av den mellanliggande CA:n, aldrig av roten. Rotlistan spelar roll bara när en mellanliggande CA har bränts. Peka servern mot mellanlistan med crl-verify. En filbaserad CRL laddas vid tjänstestart, så ladda om den efter varje omgenerering; katalogformen läser status vid anslutning och kostar en fil per serienummer.
Återkalla och generera om med två kommandon från samma databas:
openssl ca -config intermediate.cnf -revoke /etc/vpn-ca/intermediate/newcerts/1001.pem
openssl ca -config intermediate.cnf -gencrl -out /etc/openvpn/crl.pem
Håll sedan koll på klockan. En CRL bär ett fält för nästa uppdatering, och när det datumet passerats avvisar en validerande part listan i stället för att ignorera den. Månatlig omgenerering med default_crl_days = 30 ger marginal; årlig gör det inte. Kortare lövtider är den mer pålitliga kontrollen, eftersom återkallelse bara gäller där listan konsulteras.
Testa kedjan och skriv sedan ner ceremonin
Återskapa fyra fel innan du litar på designen. Validera kedjan med openssl verify -CAfile ca-bundle.crt -untrusted intermediate.crt server.crt. Anslut med ett utgånget klientcertifikat och bekräfta att servern avvisar det. Återkalla en testklient, ladda om och bekräfta att listan träder i kraft. Flytta en värds klocka en dag framåt, eftersom en felaktig klocka kan utfärda och avvisa certifikat som ser giltiga ut någon annanstans.
En offline-rot är bara en kontroll om papperen finns: två namngivna personer för ceremonin, en förteckning över varje signerat serienummer, en krypterad säkerhetskopia som förvaras separat från maskinen och ett återställningstest på en isolerad värd. Signera en reserv-mellanliggande CA under samma ceremoni så att en död signeringsvärd inte tvingar dig att låsa upp roten vid midnatt.
Innan du kallar det klart, bekräfta fem saker: rotnyckeln finns inte på en nätverksansluten värd, den mellanliggande nyckeln lever bara på signeringsvärden, klientpaketet bär båda CA-certifikaten, CRL:en har en framtida nästa uppdatering och någon äger en kalenderpost för varje utgång i kedjan. Om en saknas är uppsättningen som ser offline ut bara odokumenterad.