Wcześniej czy później użytkownik VPN zaproponuje wysłanie klucza prywatnego e-mailem, aby administrator mógł utworzyć certyfikat, i właśnie tej propozycji należy odmówić. Działający przepływ trzyma klucz na kliencie od pierwszego polecenia: klient go generuje, wysyła żądanie podpisania certyfikatu, wystawca je weryfikuje i autoryzuje, a podpisany certyfikat wraca i staje obok klucza, który go utworzył. Poniższa lista kontrolna zawodzi w sposób zamknięty na każdym kroku i o to chodzi, ponieważ dwa z pięciu kroków to właśnie te, które ludzie pomijają, gdy się spieszą.

Krok 1: wygeneruj klucz tam, gdzie będzie mieszkał

Generuj na maszynie, która będzie trzymać klucz, i zostaw go tam. Klucz programowy trafia do pliku z restrykcyjnymi uprawnieniami; klucz oparty na sprzęcie lub w zarządzanym magazynie nigdy nie staje się plikiem, a jego ścieżka rejestracji to zwykle osobne narzędzie, a nie polecenie OpenSSL. Tak czy inaczej, nikt nie musi widzieć prywatnej połowy.

Przepływ programowy wygląda tak, klucz i żądanie powstają w jednej sesji:

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"

Linia umask ma większe znaczenie, niż się wydaje. Bez niej klucz jest zapisywany jako czytelny dla wszystkich w systemie domyślnie zezwalającym, a późniejsze kopiowanie pliku to roznosi. Ponowne użycie istniejącego klucza jest uzasadnione, gdy jest już chroniony i zgodny z polityką; generowanie nowego dla każdego urządzenia łatwiej wytłumaczyć.

Krok 2: umieść tożsamość w żądaniu, nie w e-mailu

Zdecyduj, co VPN faktycznie uwierzytelnia, zanim powstanie żądanie, ponieważ ta odpowiedź należy do wnętrza CSR. OpenVPN tradycyjnie wiąże tożsamość klienta z nazwą pospolitą certyfikatu, a narzędzia takie jak strongSwan dopasowują ciąg tożsamości do podmiotu lub alternatywnej nazwy podmiotu. E-mail, który mówi, że nazywam się alice, nie jest dowodem, a żądanie, którego podmiot mówi to samo, jest tylko nieco lepsze.

Dodaj alternatywną nazwę podmiotu, gdy twój weryfikator ją sprawdza, ponieważ nowoczesne dopasowanie często ignoruje stary CN:

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

Trzymaj CN krótką, stabilną i powiązaną z kontem, a nie z modelem laptopa. Nazwa zawierająca numer seryjny urządzenia użytkownika to problem wsparcia czekający na pierwszą wymianę sprzętu.

Krok 3: zweryfikuj żądanie, zanim je podpiszesz

Wystawca weryfikuje dwie różne rzeczy, a ich mieszanie to klasyczny błąd. Po pierwsze, że żądanie jest wewnętrznie spójne: podpis jest weryfikowany względem klucza publicznego, który niesie. Po drugie, że wnioskodawca ma prawo do tego, czego żąda żądanie, a na to nie odpowie żadna kontrola kryptograficzna.

Część mechaniczna to jedno polecenie i powinno ono wypisać wynik weryfikacji wraz z podmiotem:

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

Zauważ, co to dowodzi. Żądanie, które przechodzi weryfikację, pokazuje tylko, że nadawca miał pasujący klucz prywatny w chwili złożenia; nie dowodzi, że nadawca jest osobą wymienioną w podmiocie, i nie autoryzuje dostępu do żądanej grupy ani trasy. Przegląd rejestracji to osobna brama, a żądanie grupy, której nikt nie zatwierdził, należy odrzucić, a nie po cichu edytować.

Krok 4: autoryzuj, a następnie podpisz z jawnymi rozszerzeniami

Podpisywanie to miejsce, w którym CA decyduje o polityce, a nie przyjmuje żądania dosłownie. Ważność, użycie klucza i rozszerzenie roli należą do pliku rozszerzeń, a nie do ustawień domyślnych, których nie przypomnisz sobie po pół roku. Certyfikat klienta do uwierzytelniania VPN potrzebuje uwierzytelniania klienta jako przeznaczenia.

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

Użyj -CAserial z istniejącym plikiem numerów seryjnych, jeśli jakiś jest już w użyciu, i trzymaj klucz CA poza siecią lub w chronionym magazynie, który wskazuje twoja polityka. Numery seryjne certyfikatów muszą być unikalne dla każdego wystawcy; odtworzenie pliku numerów seryjnych od zera ryzykuje kolizje, które czynią unieważnienie niejednoznacznym.

Zapisz, co zostało wydane: numer seryjny, podmiot, żądaną tożsamość, osobę zatwierdzającą i wygaśnięcie. To ten zapis jest tym, na czym później opiera się decyzja o unieważnieniu, i nie można go odtworzyć wyłącznie z certyfikatu, jeśli ślad rejestracji żyje tylko w skrzynce pocztowej.

Krok 5: zainstaluj go obok pasującego klucza i udowodnij parę

Klient otrzymuje certyfikat i łańcuch wystawcy, nigdy klucz. Przed połączeniem potwierdź, że certyfikat rzeczywiście tworzy parę z kluczem już obecnym na dysku, ponieważ niedopasowana para daje mylący błąd uścisku dłoni znacznie później:

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

Oba skróty muszą się zgadzać. Następnie połącz się i potwierdź, że tożsamość rejestrowana przez serwer to ta, którą autoryzowałeś, a nie tylko to, że tunel się podniósł. Jeśli klucz zostanie utracony lub urządzenie wymienione, odpowiedzią jest unieważnienie plus nowe żądanie z nowego urządzenia; proszenie administratora o odesłanie klucza skądinąd nie odzyskuje oryginału i po cichu łamie model, który czynił żądanie bezpiecznym.

Powiązane artykuły