Uwaga:
Oryginalna wersja tego artykułu została opublikowana w IBM developerWorks i
jest własnością Westtech Information Services. Poniższy dokument jest
poprawioną przez zespół GDP wersją oryginalnego tekstu i nie jest już
aktualizowany.
|
Zarządzanie kluczem OpenSSH, Część 2
1.
Wprowadzenie do ssh-agent i keychain
Kilka słów o ssh-agent
ssh-agent (część pakietu OpenSSH), to program specjalnie zaprojektowany do
pracy z kluczami RSA i DSA (więcej informacji w pierwszym artykule z tej serii
od wstępu do uwierzytelnienia RSA i DSA). ssh-agent jest demonem
zaprojektowanym w celu buforowania odszyfrowanych kluczy prywatnych.
ssh zawiera wbudowane wsparcie, umożliwiające mu komunikację z ssh-agent i
pozwala na posiadanie odszyfrowanych kluczy prywatnych bez konieczności
potwierdzania hasła przy każdym nowym połączeniu. W tym celu należy po prostu
użyć ssh-add żeby dodać klucz prywatny do pamięci podręcznej agenta ssh. Jest
to jednorazowy proces; po użyciu ssh-add, ssh przechwyci klucz prywatny od
ssh-agent, zamiast czekać na potwierdzenie hasła.
Używanie ssh-agent
Spójrzmy jak działa system buforowania kluczy. Kiedy ssh-agent się uruchamia,
zwraca kilka ważnych zmiennych środowiskowych przed odłączeniem od powłoki i
kontynuowaniem pracy w tle. Oto kilka przykładowych wydruków wygenerowanych
przez ssh-agent w momencie uruchomienia:
Listing 1.1: Uruchomienie demona ssh-agent |
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-XX4LkMJS/agent.26916; export SSH_AUTH_SOCK;
SSH_AGENT_PID=26917; export SSH_AGENT_PID;
echo Agent pid 26917;
|
Jak widać wydruk ssh-agenta jest w rzeczywistości serią komend basha; jeżeli
zostaną wykonane, spowodują ustawienie pary zmiennych środowiskowych,
SSH_AUTH_SOCK i SSH_AGENT_PID. Za sprawą komendy export, zmienne te będą
dostępne dla innych komend uruchomionych później. Wszystko to stałoby się
jeżeli zmienne te były używane przez powłokę, ale teraz są po prostu drukowane
na standardowe wyjście. Aby to naprawić można wywołać ssh-agent w następujący
sposób:
Listing 1.2: Różne sposoby wywołania ssh-agent |
$ eval `ssh-agent`
|
Komenda ta mówi bashowi żeby uruchomił ssh-agent a następnie ocenił wyjście
ssh-agenta. Wywołanie w ten sposób (z odwrotnym cudzysłowem) powoduje, że
zmienne SSH_AGENT_PID i SSH_AUTH_SOCK są ustawiane i exportowane przez powłokę,
są dostępne dla każdego nowego procesu uruchomionego w trakcie sesji logowania.
Najlepszym sposobem na uruchomienie ssh-agent jest dodanie powyższej linii do
pliku ~/.bash_profile. W ten sposób, wszystkie programy
uruchomione w powłoce logowania zobaczą zmienne środowiskowe, będą w stanie
zlokalizować ssh-agent i w razie potrzeby zapytać go o klucze. SSH_AUTH_SOCK
jest zmienną środowiskową szczególnie ważną; SSH_AUTH_SOCK zawiera ścieżkę do
gniazda domeny UNIX, którego ssh i scp moga użyć w celu nawiązania łączności z
ssh-agent.
Używanie ssh-add
ssh-agent startuje z pustym buforem odszyfrowanych kluczy prywatnych. Zanim
będzie można użyć ssh-agent, trzeba najpierw dodać klucz(e) prywatny(e) do
bufora ssh-agentam, co umożliwia polecenie ssh-add. W poniższym przykładzie,
użyto ssh-add w celu dodania ~/.ssh/identity klucza prywatnego RSA
do bufora ssh-agenta:
Listing 1.3: Ładowanie klucza prywatnego RSA do bufora ssh-agenta |
$ ssh-add ~/.ssh/identity
Need passphrase for /home/drobbins/.ssh/identity
Enter passphrase for /home/drobbins/.ssh/identity
(enter passphrase)
|
Jak widać, ssh-add zapytał o hasło po to aby gotowy do użycia klucz prywatny
mógł być odszyfrowany i przechowany w buforze ssh-agenta. Kiedy użyto ssh-add w
celu dodania klucza(kluczy) prywatnego do bufora ssh-agenta i zmienna
SSH_AUTH_SOCK jest zdefiniowana w bieżącej powłoce (i tak powinno być, ponieważ
uruchomiono ssh-agent z ~/.bash_profile), wtedy mona użyć scp i ssh w celu
nawiązania połączenia ze zdalnymi systemami bez podawania hasła.
Limity ssh-agenta
ssh-agent jest naprawdę wspaniały, ale jego trudna konfiguracja wciąż
pozostawia nas z kilkoma pomniejszymi niedogodnościami. Oto one:
Po pierwsze, z eval `ssh-agent` w pliku ~/.bash_profile,
nowa kopia ssh-agent jest uruchamiana dla każdej sesji logowania. Oznacza to że
trzeba użyć ssh-add żeby dodać klucz prywatny dla każdej nowej kopii ssh-agent.
Jeśli jest otworzony jeden terminal lub konsola, nie ma to wielkiego znaczenia,
ale zazwyczaj otwartych jest kilka terminali i trzeba wpisać hasło za każdym
razem gdy otwierana jest nowa konsola. Technicznie rzecz biorąc, nie ma powodu
dla którego trzeba by to robic, ponieważ pojedynczy proces ssh-agent powinien
wystarczyć.
Inny problem z domyślnym ustawieniem ssh-agent jest taki, że nie jest zgodny z
żądaniami crona. Odkąd procesy są uruchomione przez crona, nie będą dziedziczyć
zmiennej SSH_AUTH_SOCK z ich środowiska i przez to nie będą wiedziały, że proces
ssh-agent jest uruchomiony albo jak się z nim skontaktować. Ten problem można
naprawić.
Wprowadzenie keychain
Aby rozwiązać te problemy, napisano w bashu program o nazwie keychain. keychain
umożliwia używanie procesu ssh-agent jednego na system, a nie na sesje
logowania. Oznacza to, że dla każdego klucza prywatnego trzeba wykonać tylko
raz ssh-add. Jak widać keychain pomaga również optymalizować proces ssh-add
poprzez próbę dodania kluczy prywatnych, które nie są w buforze działającego
ssh-agenta.
Oto przebieg działania keychain. Jeżeli jest uruchomiony z
~/.bash_profile, w pierwszej kolejności sprawdzi czy ssh-agent
został już uruchomiony. Jeżeli nie, wtedy uruchomi ssh-agent i zapisze ważne
zmienne SSH_AUTH_SOCK i SSH_AGENT_PID w pliku ~/.ssh-agent dla
bezpieczeństwa i do przyszłego użycia. Oto najlepszy sposób na uruchomienie
keychain; tak jak w przypadku użycia czystego ssh-agent, umieszczamy
odpowiednie ustawienia wewnątrz ~/.bash_profile:
Listing 1.4: Ustawienia dla ssh-agent w pliku ~/.bash_profile |
#!/bin/bash
#example ~/.bash_profile file
/usr/bin/keychain ~/.ssh/id_rsa
#redirect ~/.ssh-agent output to /dev/null to zap the annoying
#"Agent PID" message
source ~/.ssh-agent > /dev/null
|
Jak widać, za pomocą keychain pobieramy plik źródłowy ~/.ssh-agent
zamiast oceniać wydruk wyjściowy jak to było robione w przypadku bezpośredniego
użycia ssh-agent. Jednak rezultat jest taki sam -- zmienna SSH_AUTH_SOCK jest
zdefiniowana, ssh-agent uruchomiony i gotowy do użycia. Ponieważ zmienna
SSH_AUTH_SOCK jest zapisana w ~/.ssh-agent, skrypty powłoki i
zadania crona mogą w prosty sposób połączyć się z ssh-agent pobierając plik
źródłowy ~/.ssh-agent. Sam keychain również korzysta z tego pliku.
W momencie uruchomienia sprawdza czy ssh-agent jest uruchomiony. Jeżeli tak,
używa pliku ~/.ssh-agent do pobrania właściwych ustawień
SSH_AUTH_SOCK, umożliwiających mu użycie istniejącego agenta zamiast
uruchamianie nowego. keychain uruchomi nowy proces ssh-agent tylko jeżeli plik
~/.ssh-agent jest przestarzały (wskazuje na nieistniejący
ssh-agent) lub jeśli ~/.ssh-agent po prostu nie istnieje.
Instalacja keychain
Instalacja keychain jest prosta. Najpierw, zaglądamy na stronę projektu keychain
i sciągamy najnowszą dostepną wersję spakowanych źródeł keychain lub
instalujemy go w następujący sposób używając emerge:
Listing 1.5: Instalacja keychain |
# emerge keychain
|
Teraz kiedy keychain jest w /usr/bin/, należy go dodać do
~/.bash_profile, podając ścieżki do kluczy prywatnych jako
argumenty. Oto standardowy plik z poprawnie aktywowanym keychain
~/.bash_profile:
Listing 1.6: Aktywowanie keychain w pliku ~/.bash_profile |
#!/bin/bash
#on this next line, we start keychain and point it to the private keys that
#we'd like it to cache
/usr/bin/keychain ~/.ssh/id_rsa ~/.ssh/id_dsa
source ~/.ssh-agent > /dev/null
#sourcing ~/.bashrc is a good thing
source ~/.bashrc
|
Keychain w akcji
Po skonfigurowaniu pliku ~/.bash_profile żeby wywoływał keychain
przy każdym logowaniu, wylogowaniu i powtórnym logowaniu, keychain będzie
uruchamiał ssh-agent, zapamiętywał ustawienia zmiennych środowiskowych agenta w
pliku ~/.ssh-agent, a potem prosił o podanie hasła dla każdego
klucza prywatnego podanego jako argument wiersza poleceń w pliku
~/.bash_profile:
Ilustracja 1.1: Keychain uruchomiony po raz pierwszy |
 |
Po wpisaniu hasła klucze prywatne zostaną dodane do bufora i keychain zakończy
działanie. Następnie pobierane są informacje z pliku ~/.ssh-agent i zostaje
zainicjowana sesja logowania do użycia przez ssh-agent. Teraz, jeżeli nastąpi
wylogowanie i powtórne logowanie, keychain sam odnajdzie istniejący proces
ssh-agent, który nie zakończył się gdy nastąpiło wylogowanie. Dodatkowo,
keychain zweryfikuje to czy klucze prywatne które były wpisane znajdują się
już w buforze ssh-agenta. Jeżeli nie, wtedy trzeba będzie podać właściwe hasło,
ale jeżeli wszystko pójdzie dobrze, istniejąca wersja ssh-agenta wciąż będzie
zawierać poprzednio dodane klucze prywatne. Dzięki temu nie trzeba ponownie
podawac hasła:
Ilustracja 1.2: Keychain odnajduje istniejącego ssh-agenta |
 |
Po zalogowaniu będzie można kopiować (scp) i logować (ssh) się zdalnie. Nie
trzeba korzystać z ssh-add po zalogowaniu się, również ssh i scp nie będą
prosiły o podanie hasła. W rzeczywistości, dopóki początkowy proces ssh-agenta
jest uruchomiony, będzie można się zalogować i nawiązać połączenia ssh bez
konieczności podawania hasła. ssh-agent może kontynuować swoje działanie do
momentu, gdy komputer zostanie ponownie uruchomiony. W związku z tym, że zwykle
tych ustawień dokonuje się na Linuksie, istnieje możliwość pominięcia
wpisywania hasła przez kilka miesięcy. Witamy w świecie bezpiecznych połączeń z
uwierzytelnianiem RSA i DSA bez konieczności podawania hasła.
Nawet po stworzeniu kilku nowych sesji logowania widać, że keychain podłączy
się za każdym razem do tego samego procesu ssh-agenta. Można również podłączyć
skrypty i działające procesy crona do uruchomionego ssh-agenta. Żeby używać
komend ssh lub scp ze skryptów powłoki i procesów crona, należy się upewnić, że
najpierw pobierają informacje z pliku ~/.ssh-agent:
Listing 1.7: Pobieranie informacji z pliku ~/.ssh-agent |
$ source ~/.ssh-agent
|
Następnie każda kolejna komenda ssh lub scp będzie mogła znaleźć bieżącego
ssh-agenta i nawiązać bezpieczne połączenie bez konieczności podawania hasła,
tak jak można to wykonać z powłoki.
Opcje keychaina
Kiedy keychain jest uruchomiony i działa, można wydać polecenie keychain
--help, które wyświetli listę paramtetrów tego programu. Tu zajmiemy się
szczególnie opcją --clear.
W pierwszej części wytłumaczyłem, że używanie niezaszyfrowanych kluczy
prywatnych jest niebezpieczne, ponieważ ktoś mógłby ukraść klucz prywatny i
użyć go do zalogowania się na zdalne konto z jakiegokolwiek systemu bez
konieczności podawania hasła. Dopóki keychain nie jest wrażliwy na tego typu
nadużycia (dopóki klucze prywatne są zaszyfrowane), istnieje potencjalna wada
bezpośrednio związana z faktem, że keychain umożliwia łatwe podłączenie się do
długo działającego procesu ssh-agenta. Co by się stało gdyby ktoś odgadł hasło
i zalogował się do lokalnego systemu? Jeżeli byłby w stanie zalogować się jako
normalny użytkownik, keychain automatycznie dałby mu dostęp do odszyfrowanych
kluczy prywatnych, umożliwiając dostęp do innych kont użytkownika.
Nim przejdziemy dalej. Zatrzymajmy się przy wątku dotyczącym bezpieczeństwa.
Jeżeli jakiś złośliwy użytkownik był w stanie zalogować się na nasze konto,
keychain rzeczywiście umożliwi mu dostęp do naszych zdalnych kont. Jednak
intruzowi będzie bardzo ciężko ukraść nasze odszyfrowane klucze prywatne
ponieważ one wciąż znajdują sią na dysku i są zaszyfrowane. Dodatkowo, aby
zdobyć dostęp do kluczy prywatnych intruz musi zalogować się jako użytkownik, a
nie tylko przejrzeć pliki z jego katalogu. Zatem ominięcie ssh-agenta będzie o
wiele trudniejszym zadaniem niż zwykła kradzież niezaszyfrowanego klucza
prywatnego, które wymaga tylko dostępu intruza do plików w katalogu
~/.ssh. Jeśli jednaki intruz był w stanie zalogować się jako
użytkownik, mógł uczynić spore szkody przez używanie zaszyfrowanych kluczy
prywatnych. Zatem jeżeli używamy keychain na serwerze, na który się nie
logujemy bardzo często lub nie prowadzimy monitorowania naruszenia
bezpieczeństwa, wtedy należy używać opcji --clear.
Opcja --clear umożliwia przekazanie keychain, że każde nowe logowanie na
konto użytkownika powinno byc traktowane jako potencjalne włamanie, chyba, że
zostanie udowodnione, że jest inaczej. Kiedy uruchomimy keychain z opcją
--clear, natychmiast wyczyści on wszystkie klucze prywatne z bufora
ssh-agenta kiedy nastąpi logowanie, przed rozpoczęciem normalnego działania.
Zatem keychain poprosi o podanie hasła zamiast dać dostęp intruzowi do
istniejącego zbioru kluczy z bufora. Jednak, nawet to ulepszenie bezpieczeństwa
wprowadza pewne niedogodności i jest podobne do działania samego ssh-agenta,
bez keychain. Trzeba dokonać wyboru pomiędzy bezpieczeństwem, a wygodą.
Pomimo tego, używanie keychain z opcją --clear wciąż jest lepszym
rozwiązaniem niż używanie samego ssh-agent. Należy pamiętać, że kiedy używamy
keychain --clear procesy crona i skrypty wciąż będą mogły nawiązać
połączenie bez konieczności podawania hasła. Dzieje się tak, ponieważ klucze
prywatne zostały wyczyszczone przy zalogowaniu, a nie wylogowaniu. Odkąd
wylogowanie z systemu nie stanowi potencjalnego naruszenia bezpieczeństwa, nie
ma potrzeby żeby keychain był odpowiedzialny za czyszczenie kluczy ssh-agenta.
Zatem opcja --clear stanowi idealny wybór dla niezbyt często używanych
serwerów.
Gotowe!
Omówiliśmy metody pracy z kluczami RSA i DSA. Pokazaliśmy jak używać ich do
codziennej pracy z OpenSSH w sposób wygodny, ale i z zachowaniem zasad
bezpieczeństwa. Poniżej znajduje się kilka adresów, które pozwolą na szersze
poznanie tej tematyki.
2.
Źródła
|