easy-rsa 3 jako CA do obsługi infrastruktury OpenVPN (na przykładzie CentOS 6)

Wprowadzennie

Jest to wpis przedstawiający sposób instalacji, konfiguracji i użytkowania easy-rsa w wersji 3 jako narzędzia do zarządzania infrastrukturą PKI CA w kontekście usługi OpenVPN, która wykorzystuje certyfikaty do uwierzytelniania serwera i końcówek klienckich oraz do generacji tzw. parametrów Diffie Hellman-a wykorzystywanych przy negocjacji kluczy sesyjnych.

Przedstawiony opis jest oparty o środowisko CentOS 6.

Kompatybilność z OpenVPN

Oprogramowanie OpenVPN, zarówno pobrane bezpośrednio ze strony projektu OpenVPN (https://openvpn.net/index.php/open-source/downloads.html), jak i te zainstalowane z pakietów dostępnych w repozytorium EPEL (https://fedoraproject.org/wiki/EPEL), zawiera przykładowe pliki konfiguracyjne które mogą posłużyć jako wzór dla własnych plików konfiguracyjnych. Stan na wrzesień 2014 jest taki, że przykładowe pliki konfigurujące klienta OpenVPN posiadają wpis wprowadzający trochę zamieszania w kontekście współpracy z certyfikatami:

Powyższy wpis przekłada się na bardzo konkretny wymóg co do formatu certyfikatu serwera OpenVPN. Certyfikat serwera musi posiadać pole “nsCertType” ustawione na wartość “server“. Ponieważ jednak jest to pole oznaczone jako przestarzałe (ang. deprecated), to domyślnie, easy-rsa w wersji 3 nie dodaje tego pola do certyfikatów serwera (easy-rsa w wersji 2 dodawało takie pole). W konsekwencji, okazuje się, że OpenVPN skonfigurowany w oparciu o dostarczone z nim, przykładowe pliki konfiguracyjne, nie działa z  certyfikatami wystawionymi przy pomocy domyślnie skonfigurowanego easy-rsa 3.

Sposób konfiguracji easy-rsa 3, pozwalający na uzyskanie certyfikatów zgodnych z ustawieniami wynikającymi z przykładowych plików konfiguracyjnych OpenVPN, zostanie przedstawiony w dalszej części wpisu.

Instalacja (pobranie) easy-rsa

Pewnie najprościej było by zainstalować easy-rsa z jakiegoś repozytorium pakietów, korzystając z narzędzia yum. Ponieważ jednak, w żadnym z popularnych repozytoriów, nie znalazłem pakietu z easy-rsa w wersji 3, to postanowiłem pobrać stosowną paczkę bezpośrednio ze strony projektu na portalu GitHub (https://github.com/OpenVPN/easy-rsa). Jednak jako że narzędzie easy-rsa korzysta z openssl, to na początku należy się upewnić, że openssl jest zainstalowany w systemie.

Jeśli polecenie,

zwróci komunikat,

to openssl-a nie ma, i musimy zainstalować odpowiedni pakiet,

Następnie, bezpośrednio z witryny GitHub, pobieramy paczkę z plikami implementującymi easy-rsa.

Rozpakowujemy pobraną paczkę.

Ponieważ easy-rsa jest oparte na skryptach powłoki, które pod spodem korzystają z komend openssl, to nie ma potrzeby kompilacji projektu. Głównym skryptem służącym za interfejs użytkownika jest skrypt o nazwie easyrsa. Po rozpakowaniu paczki master.zip, skrypt tej znajduje się w katalogu easy-rsa-master/easyrsa3.

Inicjalizacja struktury katalogów

Bezpośrednio po rozpakowaniu paczki z easy-rsa, należy uruchomić skrypty inicjalizujące i konfigurujące środowisko dla CA. Przy założeniu, że zgodnie z powyższą instrukcją, znajdujemy się w katalogu ze skryptem easyrsa, przygotowanie struktury katalogów na certyfikaty, klucze prywatne, itp. dane z którymi pracuje CA, następuje po wydaniu komendy:

Konfiguracja kluczowych parametrów CA

Zanim wygenerujemy certyfikat CA, który będzie służył do podpisywania innych certyfikatów, skonfigurujemy najważniejsze parametry naszego CA. Wzorcowy plik z parametrami to vars.example. Plik ten należy przegrać pod nazwę vars i ustawić w nim interesujące nas parametry.

Plik vars zawiera listę możliwych do ustawienia parametrów wraz z komentarzami tłumaczącym znaczenie poszczególnych parametrów. Wyjściowo, wszystkie parametry są zakomentowane (linijki w których znajdują się komentarze rozpoczynają się od znaku #), co oznacza, że zostaną użyte domyślne wartości tych parametrów. Jeśli chcemy zmienić jakiś parametr, to należy najpierw go odkomentować (lub skopiować do innej linii z pominięciem znaku #) i ustawić mu oczekiwaną wartość.

Poniżej przedstawiam listę najważniejszych parametrów z pliku vars, wraz z przykładowymi wartościami.

Długość pary kluczy w bitach

EACYRSA_KEY_SIZE określa długość pary kluczy RSA. Domyślnie, wartość parametru wynosi 2048. W prezentowanym przykładzie zwiększam tą wartość do 4096. Większa wartość oznacza dłuższy czas uwierzytelniania i negocjacji kluczy sesyjnych.

EASYRSA_CA_EXPIRE określa w dniach czas po jakim straci ważność certyfikat CA służący do podpisywania innych certyfikatów (jest to tzw. ROOT CA).

EASYRSA_CERT_EXPIRE, wyrażony w dniach czas po jakim tracą ważność certyfikaty podpisane przez CA (czyli przy pomocy certyfikatu CA, którego czas ważności określa poprzedni parametr).

EASYRSA_NS_SUPPORT, bardzo ważny parametr z punktu widzenia kompatybilności certyfikatów z OpenVPN (patrz sekcja “Kompatybilność z OpenVPN”).  Żeby OpenVPN działał poprawnie w konfiguracji sugerowanej przez dostarczane z nim przykładowe pliki konfiguracyjne, to wartość EASYRSA_NS_SUPPORT, należy ustawić na “yes”. Proszę zwrócić uwagę, że wartość domyślna to “no”, więc odkomentowanie wiersza z tym parametrem nie wystarczy, trzeba jeszcze jawnie wpisać nową wartość.

Kolejny bardzo ważny element certyfikatu CA, to zapisana w formacie X.500, tzw. nazwa wyróżniona jednostki certyfikującej. Wartości poszczególnych składowych elementów tej nazwy, również można ustawić w pliku vars przy pomocy parametrów EASYRSA_REQ_COUNTRYEASYRSA_REQ_PROVINCE, EASYRSA_REQ_CITY, EASYRSA_REQ_ORG, EASYRSA_REQ_EMAIL, EASYRSA_REQ_OU. Jeśli nie ustawimy tych parametrów, to zostaną użyte ich wartości domyśle (mimo, że z funkcjonalnego punktu widzenia nie ma to znaczenia, to jest duże prawdopodobieństwo, że wartości domyślne nie będą pasować logicznie do naszego środowiska). Bardzo ważny element nazwy wyróżnionej to tzw. Common Name (CN), którego nie ustawia się w pliku konfiguracyjnym, bo wartość dla CN ustala się w trybie interaktywnym, przy budowie CA (patrz następny punkt).

Budowa CA

Po spersonalizowaniu głównych parametrów określających CA, należy wygenerować certyfikat CA i pliki pomocnicze stanowiące dane CA. W tym celu wydajemy polecenie:

Podczas budowy CA, zostaniemy poproszeniu o podanie hasła które będzie chronić klucz prywatny związany z certyfikatem CA. Hasło to trzeba będzie podać za każdym razem gdy będzie potrzebny dostęp do klucza prywatnego CA, a więc np. przy podpisywaniu innych certyfikatów.

Zostaniemy też poproszeni o podanie wartości dla już wspomnianego elementu Common Name będącego częścią nazwy wyróżnionej jednostki certyfikującej.

Proszę zwrócić uwagę, że podczas budowy CA, wyświetlane są komunikaty informacyjne ze ścieżkami do plików z kluczem prywatnym i certyfikatem CA.

Żądanie podpisania certyfikatu

Zanim CA podpisze (lub innymi słowy wystawi) jakiś certyfikat, najpierw trzeba wygenerować specjalne żądanie. Jest to po prostu plik z kluczem publicznym oraz innymi atrybutami określającymi podmiot na rzecz którego ma być wystawiony certyfikat. Takie żądanie trafia do CA (szczegóły techniczne poniżej), a następnie na podstawie informacji zawartych w żądaniu, konstruowany i podpisywany jest certyfikat. Ważne jest żeby zrozumieć, że podczas tworzenia żądania, generowany jest również klucz prywatny, który będzie odpowiadał kluczowi publicznemu zawartemu w certyfikacie.  Ponieważ, klucz prywatny nigdy nie powinien być ujawniony, to oznacza to, że żądanie podpisania certyfikatu powinno być generowane na maszynie osoby czy podmiotu zainteresowanego otrzymaniem certyfikatu podpisanego przez nasze CA. W praktyce, w warunkach testowych, żądania można generować na tym samym węźle na którym został zainstalowany i skonfigurowany CA, ale w poważnych, produkcyjnych zastosowaniach jest to raczej niedopuszczalne.

Generacja żądania na węźle zewnętrznym

Zanim wygenerujemy żądanie na zewnętrznym węźle, pierw koniczna jest, na nim inicjalizacja PKI. Wygląda to tak samo jak początek instalacji CA.  Najpierw pobieramy paczkę ze skryptami easy-rsa, następnie, paczkę tę rozpakowujemy, przechodzimy do katalogu z głównym skryptem easyrsa i inicjujemy PKI.

Przed wygenerowaniem żądania, możemy jeszcze chcieć zwiększyć długość pary kluczy generowanych razem z żądaniem. W tym celu kopiujemy plik vars.example do vars.

A następnie, w pliku vars odkomentowujemy i ustawiamy na żądaną wartość parametr EASYRSA_KEY_SIZE. Poniższy przykład, pokazuje ustawienie zwiększające długość pary kluczy na 4096 bity.

W tej chwili można już wygenerować żądanie podpisu. Należy jednak pamiętać, że jeśli potrzebujemy certyfikatu i klucza prywatnego, które będą używane np. do uwierzytelniania się klienta OpenVPN, to żeby dało się łatwo zautomatyzować zestawianie sieci VPN, klucz prywatny nie powinien być chroniony hasłem. Dlatego w poleceniu generującym żądanie użyjemy parametru nopass, dzięki czemu, wygenerowany klucz prywatny nie będzie zaszyfrowany (w przeciwnym razie, podczas generowania żądania, bylibyśmy poproszeni o zdefiniowanie hasła chroniącego klucz).  W trakcie generowania żądania pojawi się jeszcze prośba o podanie nazwy Common Name podmiotu dla którego  ma być wystawiony certyfikat. Nie ma jednak potrzeby wprowadzania tej nazwy, ponieważ wartością domyślną jest wartość jednego z parametrów komendy generującej żądanie. W poniższym przykładzie, zakładamy, że żądanie jest generowane dla klienta OpenVPN, który będzie uruchamiany na węźle o nazwie komputerowiec.nasza-strefa.net, oraz że klucz prywatny nie ma być szyfrowany.

Z wyświetlonych komunikatów dowiemy się, gdzie zostały złożone pliki z kluczem prywatnym i z żądaniem certyfikatu.

Żądanie, czyli plik komputerowiec.nasza-strefa.net.req, należy przesłać do CA. Ponieważ w żądaniu nie ma żadnych poufnych danych, to można w tym celu użyć zwykłej poczty email lub dowolnego innego kanału komunikacji. W przypadku produkcyjnych CA, często jest to moment w którym podmiot ubiegający się o wystawienie certyfikatu musi w jakiś sposób uwierzytelnić swoje żądanie. W przypadku certyfikatów osobistych, uwierzytelnienie może polegać nawet na pojawieniu w wyznaczonym punkcie z dowodem osobistym potwierdzającym tożsamość.

Po stronie CA, zanim na podstawie żądania wystawiony zostanie certyfikat,  pierw żądanie musi zostać zaimportowane. Zakładając, że plik z żądaniem jest w pliku /path/to/komputerowiec.nasza-strefa.net.req, to komenda importująca wygląda jak poniżej. Ostatni parametr wywołania to nazwa umowna, nie koniecznie taka sama jak Common Name podmiotu. Nazwy tej tej będzie się później używać np. w poleceniu podpisującym certyfikat w celu wskazania żądania w oparciu o które należy wygenerować i podpisać certyfikat.

Po zaimportowaniu żądania, można wystawić certyfikat (opis w punkcie  “Podpisanie certyfikatu”).

Generacja żądania bezpośrednio na węźle z CA

Mimo że teoria mówi, że żądanie powinno być generowane na węźle zewnętrznym, to technicznie jest możliwe wygenerowanie żądania bezpośrednio na tej samej maszynie na której zainstalowaliśmy CA.

Do wygenerowania żądania na węźle z CA, wydajemy takie samo polecenie jak na węźle zewnętrznym. Poniżej widać polecenie generujące żądanie certyfikatu dla podmiotu o Common Name zdefiniowanego jako blog.nasza-strefa.net.


Żądań wygenerowanych bezpośrednio na węźle z CA, nie trzeba już importować (tak jak to miało miejsce przy żądaniach przysłanych z zewnętrznych węzłów). Nazwa żądania, przez którą będziemy się odwoływać do żądania przy jego podpisywaniu, to pełna nazwa podmiotu (czyli blog.nasza-strefa.net). Długość pary kluczy wygenerowanych razem z żądaniem jest określona przez parametr EASYRSA_KEY_SIZE w lokalnym pliku vars (ten sam w którym ustawialiśmy główne parametry CA).

Podpisanie certyfikatu

Na podstawie zaimportowanych lub bezpośrednio wygenerowanych na węźle z CA żądań, wystawia się certyfikaty podpisane przez CA. Oczywiście certyfikaty wystawia się na węźle na którym wcześniej zainstalowaliśmy i skonfigurowaliśmy CA.

UWAGA: Podczas podpisywania certyfikatów dla OpenVPN, ważne jest żeby pamiętać, że jeden z parametrów polecenia służącego do wystawienia certyfikatu, określa czy certyfikat jest wystawiany dla serwera OpenVPN czy dla klienta OpenVPN.

Nawiązując do powyższych przykładów generacji żądań, w celu podpisania certyfikatu dla klienta OpenVPN o  nazwie komputerowiec.nasza-strefa.net (czyli dla żądania zaimportowanego), należy wydać następujące polecenie:

Ponieważ do podpisania certyfikatu konieczne jest użycie klucza prywatnego CA, to skrypt uruchomiony przez powyższe polecenie, zażąda podania hasła chroniącego ten klucz.

Gdyby certyfikat był wystawiany dla serwera OpenVPN, to w miejsce parametru o wartości client należało by wstawić parametr o wartości server.

Analogicznie, wystawienie certyfikatu dla żądania, które powyżej, było wygenerowane na węźle CA, wyglądało by tak:

Śledząc komunikaty wyświetlane przez skrypt podpisujący certyfikaty, dowiemy się w jakim pliku i pod jaką ścieżką zostały one zapisane. Tak wystawione certyfikaty można przegrać na węzły docelowe. Jeśli żądanie certyfikatu było generowane lokalnie, to należy pamiętać, że na węzeł docelowy trzeba przegrać również klucz prywatny związany z kluczem publicznym umieszczonym w certyfikacie.

Generacja parametrów Diffie-Hellmana

Serwer OpenVPN, do negocjacji kluczy szyfrujących sesje, posługuje się algorytmem Diffie-Hellmana, dlatego po stronie serwera wymagany jest plik z tzw. parametrami Diffie-Helmana (ścieżkę do tego pliku wskazuje się w pliku konfiguracyjnym OpenVPN). Do wygenerowania parametrów Diffie-Hellmana służy polecenie:

Gdy generacja parametrów się zakończy, wyświetlony zostanie komunikat ze ścieżką do pliku wynikowego. Plik ten należy przegrać na serwer OpenVPN.

Podsumowanie

Przedstawiony opis skupia się na szybkim uruchomieniu testowego lub amatorskiego CA. Z bardziej zaawansowanych tematów, w ogólnie nie poruszono tematów związanych z unieważnianiem certyfikatów. Dokładniejszy opis easy-rsa można znaleźć bezpośrednio na stornie projektu https://github.com/OpenVPN/easy-rsa. Dokumentacja znajduje się w plikach typu README i w katalogu doc. Te same pliki z dokumentacją powinny być dostępne lokalnie w katalogu w którym rozpakowaliśmy pobrany ze strony projektu plik master.zip.

Napisano w Administracja, Bezpieczeństwo