Förr eller senare erbjuder en VPN-användare att skicka en privat nyckel via e-post så att administratören kan skapa ett certifikat, och det erbjudandet är just det man ska avvisa. Flödet som fungerar behåller nyckeln på klienten från första kommandot: klienten genererar den, skickar en begäran om certifikatsignering, utfärdaren verifierar och auktoriserar den, och det signerade certifikatet kommer tillbaka och ligger bredvid nyckeln som skapade det. Checklistan nedan misslyckas stängt i varje steg, och det är poängen, eftersom två av de fem stegen är just dem folk hoppar över när de har bråttom.

Steg 1: generera nyckeln där den ska bo

Generera på maskinen som ska hålla nyckeln och låt den ligga där. En mjukvarunyckel hamnar i en fil med strikta behörigheter; en hårdvarubackad nyckel eller en nyckel i ett hanterat arkiv blir aldrig en fil, och dess registreringsväg är oftast ett separat verktyg snarare än ett OpenSSL-kommando. Hur som helst behöver ingen se den privata halvan.

Mjukvaruflödet ser ut så här, med nyckeln och begäran skapade i en enda session:

umask 077
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out client.key
openssl req -new -key client.key -out client.csr -subj "/CN=alice-vpn/O=Example"

Raden umask betyder mer än den ser ut att göra. Utan den skrivs nyckeln läsbar för alla på ett system som är tillåtande som standard, och att kopiera filen runt senare sprider det. Att återanvända en befintlig nyckel är legitimt när den redan är skyddad och passar din policy; att generera en ny per enhet är lättare att motivera.

Steg 2: sätt identiteten i begäran, inte i e-postmeddelandet

Bestäm vad VPN:en faktiskt autentiserar innan begäran skapas, eftersom det svaret hör hemma inne i CSR:en. OpenVPN knyter traditionellt klientidentitet till certifikatets vanliga namn, och verktyg som strongSwan matchar en identitetssträng mot subjektet eller ett alternativt subjektnamn. Ett e-postmeddelande som säger att jag heter alice är inte bevis, och en begäran vars subjekt säger samma sak är bara lite bättre.

Lägg till ett alternativt subjektnamn när din verifierare kontrollerar ett, eftersom modern matchning ofta ignorerar det gamla CN:

openssl req -new -key client.key -out client.csr \
  -subj "/CN=alice-vpn/O=Example" \
  -addext "subjectAltName=DNS:alice-vpn"

Håll CN kort, stabilt och knutet till kontot i stället för till en bärbar datormodell. Ett namn som innehåller användarens enhets serienummer är ett supportproblem som väntar på det första hårdvarubytet.

Steg 3: verifiera begäran innan du signerar den

Utfärdaren verifierar två olika saker, och att blanda ihop dem är det klassiska misstaget. För det första att begäran är internt konsekvent: signaturen verifieras mot den offentliga nyckel den bär. För det andra att sökanden har rätt till det begäran kräver, och det kan ingen kryptografisk kontroll svara på.

Den mekaniska delen är ett enda kommando, och det bör skriva ut ett verifieringsresultat tillsammans med subjektet:

openssl req -in client.csr -noout -verify -subject
openssl req -in client.csr -noout -pubkey | openssl pkey -pubin -noout -text

Notera vad det bevisar. En begäran som verifieras visar bara att avsändaren hade den matchande privata nyckeln vid inlämningstillfället; den bevisar inte att avsändaren är personen som namnges i subjektet, och den auktoriserar inte den grupp- eller ruttåtkomst som begärs. Registreringsgranskning är en separat port, och en begäran om en grupp som ingen har godkänt bör avvisas i stället för att tyst redigeras.

Steg 4: auktorisera och signera sedan med explicita tillägg

Signering är där CA:n beslutar policy i stället för att acceptera begäran ordagrant. Giltighet, nyckelanvändning och rolltillägget hör i en tilläggsfil, inte i standardvärden du inte kommer ihåg sex månader senare. Ett klientcertifikat för VPN-autentisering behöver klientautentisering som sitt syfte.

cat > client.ext <<'EOF'
basicConstraints = CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = clientAuth
EOF
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -days 365 -extfile client.ext -out client.crt

Använd -CAserial med den befintliga serienummerfilen om en redan används, och håll CA-nyckeln offline eller i det skyddade arkiv som din policy namnger. Certifikats serienummer måste vara unika per utfärdare; att återskapa serienummerfilen från grunden riskerar kollisioner som gör återkallelse tvetydig.

Registrera vad som utfärdades: serienummer, subjekt, begärd identitet, godkännande person och utgång. Den registreringen är det som ett återkallelsebeslut senare vilar på, och den kan inte byggas upp igen enbart från certifikatet om registreringsspåret bara lever i en brevlåda.

Steg 5: installera det bredvid den matchande nyckeln och bevisa paret

Klienten tar emot certifikatet och utfärdarens kedja, aldrig en nyckel. Innan du ansluter, bekräfta att certifikatet faktiskt parar sig med nyckeln som redan finns på disken, eftersom ett par som inte matchar ger ett förvirrande handskakningsfel mycket senare:

openssl x509 -in client.crt -noout -pubkey | openssl pkey -pubin -outform DER | openssl sha256
openssl pkey -in client.key -pubout -outform DER | openssl sha256

De två sammanfattningarna måste stämma överens. Anslut sedan och bekräfta att identiteten som servern loggar är den du auktoriserade, och inte bara att tunneln kom upp. Om nyckeln tappas bort eller enheten byts ut är svaret återkallelse plus en ny begäran från den nya enheten; att be administratören skicka tillbaka en nyckel från någon annanstans återställer inte originalet och bryter tyst den modell som gjorde begäran säker.

Relaterade artiklar