Szyfrowany i przenośny katalog domowy w systemie Linux
W tym artykule opisuję jak ja osobiście podchodzę do kwestii szyfrowania swoich danych na maszynach, na którym pracuję, a niejako przy okazji, jak dzięki temu upraszczam kwestię backupu i przenośności swojego profilu pomiędzy tymi maszynami, a nawet pomiędzy hostem a wirtualną maszyną - to tutaj nie ma znaczenia. Jeżeli interesuje Cię moje podejście w tym zakresie, to zapraszam do artykułu i do filmu na YT, który będzie dodatkowym uzupełnieniem tego artykułu.
- Co szyfrować?
- Szyfrowanie całego dysku
- Czym jest tak naprawdę szyfrowanie
- Usypianie i hibernacja
- Szyfrowany przenośny kontener jako /home/$USER
- Tworzymy prosty szyfrowany kontener typu LUKS
- Odmontowywanie kontenera
- Automontowanie przy starcie
- Kopia zapasowa
- Film na YT
Co szyfrować?
W dystrybucjach linuksowych są różne podejścia do tematu szyfrowania. Przy instalacji możemy wybrać, czy chcemy szyfrowanie katalogu domowego czy np. całego dysku.
Teraz zatrzymajmy się nad tym przez chwilę, jak chodzi o szyfrowanie całego dysku. Choć brzmi ono na bezpieczniejsze, to warto tutaj pamiętać, że normalny użytkownik zwykle operuje na danych w obrębie swojego katalogu domowego. Nie spotkałem jeszcze sytuacji, by jakieś dane konfiguracyjne lub ogólnie dane jakiegoś programu dla danego użytkownika były zapisywane poza jego katalogiem domowym.
Czyli przykładowo, jeśli na użytkowniku mateusz
używam programu Mozilla Thunderbird (klient poczty) to wszelkie dane do skrzynki, czyli konta, hasła do nich, wiadomości offline, załączniki itp są przechowywane w katalogu /home/mateusz/.thunderbird
. Tak na marginesie, ten katalog u mnie zajmuje już 5 GB, bo posiadam wieloletnią konfigurację, która trzyma część wiadomości offline oraz sporo filtrów i katalogów.
W każdym razie chodzi tu o to, że wszystkie moje dane są w moim katalogu domowym, z kolei w katalogach nazwijmy to „systemowych” czyli /usr
czy /opt
są tylko pliki powiązane z samym programem, czyli binarka, pliki z ikonami, bibliotekami itp. Przy pierwszym uruchomieniu program odpala się z katalogu systemowego, a potem tworzy konfigurację w katalogu użytkownika, który go uruchomił i tam zapisuje już specyficzne dla tego użytkownika informacje, czyli konta, hasła, załączniki itp.
W dystrybucjach Linux takie zachowanie programów jest regułą, gdyż historycznie systemy POSIXowe kładły nacisk na odpowiednią separację katalogów użytkowników, a nie jak to miało miejsce (i czasem jeszcze ma w przypadku niektórych programów) w systemach Windows, gdzie ustawienia użytkownika lądowały w systemowym katalogu z programami, np. C:\Program Files
Szyfrowanie całego dysku
I tu dochodzimy do sedna sprawy: szyfrowanie całego dysku to zazwyczaj overkill, który niewiele wnosi, skoro wszystkie ważne dane są składowane w katalogu domowym. Oczywiście, takie szyfrowanie może mieć sens, jeśli ktoś ma ważne dane lub ustawienia poza swoim katalogiem domowym, np. konfigurator noip.com
domyslnie odwołuje się do pliku binarnego z loginem i hasłem w /etc, ale oczywiście można to zmienić w opcjach jego uruchamiania. Pewnie znajdzie się kilka takich incydentalnych przypadków jak ten, ale będą to raczej pojedyncze przypadki nie zmieniające sytuacji.
Powinniśmy jednak trochę sobie powiedzieć o problemach związanych z szyfrowaniem całego dysku.
Jeśli zaszyfrujemy cały dysk, a pod tym pojęciem rozumiem wszystkie partycje, to będziemy mieć pod górkę przy ewentualnym odzyskiwaniu systemu, gdyby np. coś po aktualizacji się zepsuło i np. trzeba było odpalić jakieś sysrescuecd i naprawić np. boot loadera. Nie mówię, że jest to jakieś niemożliwe czy coś - z poziomu sysrescuecd można bez problemu montować partycje szyfrowane, ale staje się to bez wątpienia upierdliwe.
Jednym z najgorszych rodzajów faili, które można “popełnić” przy szyfrowaniu całego dysku lub całych partycji, to zapomnienie się i zrepartycjonowanie dysku lub nawet mały resize partycji. Tego typu operacja jest praktycznie całkowicie nieodwracalna i równoznaczna z zapomnieniem hasła czyli z utratą zaszyfrowanych danych.
Czym jest tak naprawdę szyfrowanie
Dlaczego tak - otóż dużym uproszeniu szyfrowanie to proces zamiany znanych nam danych w dane “śmieci”, które są “rozróżniane” jedynie przy pomocy algorytmów szyfrujących wraz z właściwym kluczami (często są to po prostu hasła). Dane w formie zaszyfrowanej są jakby “niczym” - zajętą przestrzenią na dysku, którą żaden program nie jest w stanie użyć, bo “nie wie co to jest”. Nawet sam program szyfrujący, który otrzyma nieprawidłowe hasło do zaszyfrowanego dysku/partycji/kontenera, nie będzie w stanie “poskładać” danych do formy wyjściowej i też nie będzie “wiedział” co to jest, tylko, że on wtedy nam powie, że po prostu podane hasło jest nieprawidłowe.
Innym problemem staje się backup takiego dysku - zaszyfrowane całe partycje lub cały dysk, trzeba kopiować metodą całościową, sector by sector. To oznacza, że jak masz zaszyfrowany dysk lub partycję 500 GB, i trzymasz tam rzeczywiście powiedzmy 100 GB danych, pozostałe ~400 jest “puste” to backup takiego dysku/partycji wymaga skopiowania całości danych, bo tak działa tego typu szyfrowanie.
Fani programów typu np. Acronis mogą tu od razu się oburzyć, że tego typu programy na Windowsie z BitLockerem robi backup tylko rzeczywiście użytych danych. To prawda, jednak działanie tego programu to tak naprawdę “wyciąganie” kopiowanych danych poza obręb szyfrowany i pakowanie ich do swojego formatu danych - wówczas ten format danych, będący backupem trzeba szyfrować już zupełnie osobno, jeśli chcemy zachować ochronę naszych danych (Acronis ma oczywiście opcję szyfrowania backupu)
I żeby mnie tutaj dobrze zrozumiano - nie jestem przeciwko szyfrowaniu całego dysku, tylko moim zdaniem, tak jak opisuję, mamy z tego niewiele więcej zalet, a zaczyna dochodzić sporo problemów.
Usypianie i hibernacja
Użytkownicy, którzy korzystają z usypiania (suspend to ram), hibernacji (suspend to disk) lub jakiegoś miksu obu tych technik, czyli zazwyczaj użytkownicy laptopów, muszą pamiętać o szyfrowaniu “obrazów” pamięci swoich systemów, czy to w RAMie czy na dysku.
Jeśli jest włączone szyfrowanie całego dysku, zrzucany nań obraz stanu systemu, czy to do ramu, czy na dysk, nie jest szyfrowany, to jest sytuacja rodem jak z posiadania pancernych drzwi do domu i otwartego okna obok. Jednym słowem: nie ma sensu. Choćby z tego powodu, że klucz deszyfrujący dane musi rezydować w pamięci RAM (lub być pobierany z TPMa - o tym przypadku nie traktuje mój wpis), co oznacza, że robiąc suspend to disk, czyli hibernację, zrzucamy go w zasadzie w postaci czystego tekstu na dysk.
Jeżeli więc używasz usypiania/hibernacji i chcesz bawić się w szyfrowanie dysków, partycji, odsyłam Cię do odpowiednich poradników dla Twojej dystrybucji jak należy prawidłowo skonfigurować coś takiego. Za przykład podaję tutaj artykuł z wiki, oczywiście dystrybucji Arch Linux, która to opisuje
Szyfrowany przenośny kontener jako /home/$USER
Po długim wstępie tu dochodzimy do rozwiązania, które ja stosuję: szyfrowany kontener LUKS (czyli pojedyczny plik), który jest u mnie montowany jako katalog domowy użytkownika, którego używam (w moim przypadku to /home/mateusz
)
Podstawowe zalety tego podejścia:
-
Szyfruję tylko mój katalog domowy, a nie wszystko inne, przez co nie ma dużego narzutu wydajnościowego na system oraz zachowuję sobie “normalne” opcje na wypadek konieczności naprawy dystrybucji po jakiejś knąbrnej aktualizacji
-
Efektywnie mój kontener, a tym samym cały katalog domowy, rezyduje na dysku jako pojedynczy plik dzięki czemu jest bardzo “mobilny” - mimo, że zajmuje te kilkadziesiąt GB, to jednak wystarczy go skopiować na inną dystrybucję, zamontować i mamy wszystko, nie wspominając o robieniu kopii zapasowej.
-
Bardzo łatwo to “zintegrować” w każdą dystrybucję, czyli ustawić, aby automatycznie przy starcie systemu mogło się montować (np. po podaniu hasła) lub montować bez problemu w trakcie działania systemu.
Za największą wadę kontenerów luks uważam brak wsparcia dla ukrytych wolumenów, czyli tego co miał TrueCrypt lub teraz ma VeraCrypt.
Tworzymy prosty szyfrowany kontener typu LUKS
Powinniśmy mieć zainstalowany pakiet cryptsetup
, przynajmniej w ArchLinux/Manjaro oraz powinniśmy mieć załadowany moduł dm_crypt
. Jeżeli używasz innej dystrybucji pokroju Ubuntu/Mint - tam o ile pamiętam, zresztą podobnie jak w Arch/Manjaro, to wszystko jest domyślnie zainstalowane.
Testowo utworzymy “pusty” plik o pojemności 1 GB, polecenie:
$ sudo fallocate -l 1GB kontener.luks
To polecenie utworzy nam zadziwiająco szybko plik o nazwie kontener.luks
o pojemności około 954 MB
- nazwa może być dowolna, ja tutaj będę posługiwał się właśnie nią.
Teraz upewnijmy się jedynie, że ten nowo powstały plik rzeczywiście ma taką pojemność:
$ du -sh kontener.luks
954M kontener.luks
Dodatkowo możemy się upewnić, że ten plik to nie jest już kontener szyfrowany, do tego by to sprawdzić
użyjemy poniższego polecenia cryptsetup
, które może zczytać nagłówki:
$ sudo cryptsetup luksDump kontener.luks
Device kontener.luks is not a valid LUKS device.
Skoro się upewniliśmy, to teraz jako plik kontener.luks
utworzymy nasz szyfrowany kontener:
$ sudo cryptsetup luksFormat kontener.luks
W odpowiedzi dostaniemy pytanie czy chcemy sformatować - to pytanie jest “awaryjnie”, gdyby ktoś chciał celowo lub, co gorsza, omyłkowo, “sformatować” w ten sposób prawdziwą partycję. Ponieważ ja operuję na zwykłym “pustym” pliku, oczywiście wpisują YES
po czym będziemy musieli podać 2 razy hasło, które będzie konieczne do odszyfrowywania naszego kontenera:
$ sudo cryptsetup luksFormat kontener.luks
WARNING!
========
This will overwrite data on kontener.luks irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for kontener.luks:
Verify passphrase:
Jeżeli wszystko jest ok, tj. wprowadzono identyczne hasła (dla pewności), to nie powinien pojawić się żaden komunikat i powinniśmy normalnie “wrócić” do terminala.
Teraz możemy sprawdzić ponownie, z czym teraz mamy do czynienia:
$ sudo cryptsetup luksDump kontener.luks
LUKS header information for kontener.luks
Version: 1
Cipher name: aes
Cipher mode: xts-plain64
Hash spec: sha256
Payload offset: 4096
MK bits: 512
MK digest: 45 b7 ec 3c 71 e5 93 82 78 9c bb 37 fa 9f 19 48 cf b8 f1 46
MK salt: 9e 55 20 dc f7 f7 8c 0e 30 e8 69 e5 2a 26 0d 42
ec 0a c3 78 18 ff a9 c9 96 b8 da 6b e0 fc 16 63
MK iterations: 118940
UUID: c974ca95-92d5-4137-b5f8-aa3542a5ddc4
Key Slot 0: ENABLED
Iterations: 1903040
Salt: e5 05 ba af c5 04 34 17 79 a9 ca e3 09 f8 8a dd
6d 0e 79 c5 32 0d e5 35 d2 1d ae 7f 7c 86 00 30
Key material offset: 8
AF stripes: 4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
Teraz widać, że nie jest to już “pusty” plik - czymś on jest, w naszym przypadku już szyfrowanym kontenerem.
Oczywiście gorąco zachęcam do przejrzenia opcji polecenia cryptsetup luksFormt --help
, bo ja tutaj
operuję na domyślnym ustawieniach, w tym domyślnym algorytmie szyfrującym, itp. Jeśli chcesz zmienić algorytm z
powodów wydajności i/lub bezpieczeństwa jak również np. użyć pliku jako klucza zamiast hasła, to w helpie
znajdziesz odpowiednie opcje do tego.
Na tym etapie mamy nasz szyfrowany kontener, ale teraz musimy go użyć. Do tego celu posłużymy się poleceniem
cryptsetup luksOpen
:
$ sudo cryptsetup luksOpen kontener.luks kontenerfs
Enter passphrase for kontener.luks:
$
Jak widać, jeśli chcemy “otworzyć” kontener musimy podać hasło - to samo hasło co potwierdzaliśmy poprzednio dwukrotnie. Jeśli hasło jest niepoprawne LUB kontener jest uszkodzony to dostaniemy taką informację. Jeśli jest poprawne - pozornie nic się nie stanie, znowu wrócimy do terminala.
Spostrzegawczy zauważą jeszcze, że to polecenie posiada jeszcze tajemniczy parametr kontenerfs
- to może być
dowolna nazwa, ale nazwałem to tak, aby pokazać, “czym” to jest. Otóż pod nazwą kontenerfs
teraz ten
kontener, który na dysku jest plikiem o nazwie kontener.luks
, będzie “mapowany” do urządzenia.
To mapowanie pokaże nam polecenie sudo dmsetup ls
:
$ sudo dmsetup ls
matfs (254:0)
kontenerfs (254:1)
Ponieważ w moim systemie ja już jeden kontener posiadam (szerzej go pokazuję na filmie), to mam dwa takie
wylistowane. Te same kontenery możemy wylistować w katalogu /dev/mapper
:
$ ls -l /dev/mapper
crw------- 1 root root 10, 236 cze 6 20:04 control
lrwxrwxrwx 1 root root 6 cze 7 19:23 kontenerfs -> ../dm-1
lrwxrwxrwx 1 root root 6 cze 6 20:04 matfs -> ../dm-0
Zatem, jesteśmy na etapie, że mamy nasz plik, który jest zaszyfrowanym kontenerem i jest on “otwarty”. Skoro
otwarty, to ktoś pomyśli, że można to od razu używać. Jednak nie tak szybko. Teraz możemy zobaczyć, że to
nasze nowe urządzenie o nazwie kontenerfs
możemy rozpatrywać jako partyję/dysk, bo nawet fdisk
tak
to widzi:
$ sudo fdisk -l /dev/mapper/kontenerfs
Disk /dev/mapper/kontenerfs: 951,69 MiB, 997902848 bytes, 1949029 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Skoro tak, to montujmy:
$ sudo mount /dev/mapper/kontenerfs /disc
mount: /disc: wrong fs type, bad option, bad superblock on /dev/mapper/kontenerfs, missing codepage or helper program, or other error.
Jednak, jak widać na załączonym outpucie, no nie tak szybko - najpierw musimy utworzyć właściwy już system
plików, w taki sam sposób, w jaki tworzymy na “normalnych” partycjach, a zatem, w tym przykładzie, zróbmy z tego
partycję ext4
:
$ sudo mkfs.ext4 /dev/mapper/kontenerfs
mke2fs 1.45.6 (20-Mar-2020)
Creating filesystem with 243628 4k blocks and 60928 inodes
Filesystem UUID: 290b5069-8d08-4c47-9ac6-86c6d98d8ba0
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
No i teraz próbujemy montować znowu:
$ sudo mount /dev/mapper/kontenerfs /disc
$ ls /disc
lost+found/
Tym razem zadziałało i w miejscu katalogu /disc
mamy zamontowany nasz otwarty szyfrowany kontener typu LUKS, który, gdy jest otwarty, jest partycją z systemem plików ext4
. System plików możesz wybrać dowolny, który posiada odpowiednią komendę mkfs.<costam>
u Ciebie w systemie.
Oczywiście skoro to normalny system plików, to możemy go normalnie używać, tworzyć/usuwać pliki katalogi, kopiować, itp.
Odmontowywanie kontenera
Aby odmontować i zamknąć taki kontener, bo to dwa różne pojęcia - odmontowanie nie oznacza, że go “zamknęliśmy”,
musimy najpierw “standardowo” użyć umount
:
$ sudo umount /disc
A następnie cryptsetup luksClose
, aby “zamknąć” kontener, przy tej komendzie podajemy tą nazwą, pod którą on
“objawia” się nam w katalogu /dev/mapper
:
$ sudo cryptsetup luksClose kontenerfs
I w tym momencie nasz kontener został bezpiecznie zamknięty, a hasło do niego usunięte z pamięci operacyjnej. Możemy jeszcze to zweryfikować poleceniem:
$ sudo dmsetup ls
matfs (254:0)
Czyli na mojej maszynie kontenerfs
zniknął z listy mapowanych urządzeń.
Warto pamiętać, że to wszystko “działo” się tak naprawdę w naszym pliku kontener.luks
, który utworzyliśmy
na początku - wielkość tego pliku jest “ograniczeniem” pojemności naszej partycji, którą utworzyliśmy. Więc
jak chcemy trzymać więcej danych, to trzeba utworzyć większy plik.
Co istotniejsze - bez względu na “zapełnienie” naszego systemu plików wewnątrz kontenera, rozmiar tego kontenera nie ulega najmniejszej nawet zmianie i jest to całkowicie normalne. Dlaczego tak się dzieje, kiedyś wyjaśnię w jakimś wpisie o algorytmach szyfrujących.
Automontowanie przy starcie
Jeśli to co poprzednio przeczytałaś/przeczytałeś wydawało się skomplikowane, to jest w tym trochę racji.
Na szczęście, tą całą “ceremonię” można nieco zautomatyzować, np. zakładając, że kontener.luks
to mój katalog
domowy. W takiej sytuacji, dobrze by było, gdyby ten plik nie rezydował w obecnym katalogu domowym, tylko np.
poziom wyżej w /home
, dlatego na potrzeby tego tutoriala załóżmy, że ścieżka do tego pliku to właśnie /home/kontener.luks
.
I teraz zrobimy tak, aby mógł on być automountowany przy starcie systemu (i zamykany wraz z jego zamknięciem)
Edytujemy plik /etc/crypttab
(lub tworzymy go, jeśli go nie posiadamy) i dodajemy następujący wpis:
kontenerfs /home/kontener.luks none luks
Oczywiście warto pamiętać, że nazwę użytkownika, którą ja używam to mateusz
, a katalog domowy to oczywiście /home/mateusz
. Ponieważ chcemy tego kontenera używać z poziomu naszego użytkownika, to trzeba by nadać mu jeszcze
właściwe uprawnienia, aby użytkownik mógł go w pełni używać (w moim przypadku to mateusz:mateusz
):
$ sudo chown mateusz:mateusz /home/kontener.luks
Plik /etc/crypttab
to nie wszystko. Jeszcze musimy pogrzebać w /etc/fstab
zgodnie z poniższym wpisem:
/dev/mapper/kontenerfs /home/mateusz ext4 defaults,noatime,discard 0 0
Warto zwrócić uwagę, że w /etc/crypttab
podajemy scieżkę do pliku kontenera, a w /etc/fstab
podajemy
już ścieżkę do urządzenia, jak do dysku/partycji, jak jest mapowane z nazwy podanej w /etc/crypttab
.
Dla pewności zalecam dokładnie sprawdzić te ścieżki, ponieważ potem może być problem z wystartowaniem systemu.
W teorii jak ktoś zrobił źle, to dystrybucje powinny dać odczekać 1 minutę 30 sek i zaproponować wejście do konsoli root (z podaniem hasła) lub restart komputera, więc powinna być możliwia naprawa bez startowania nośnika instalacyjnego lub resuce.
Jeżeli wszystko zrobiliśmy dobrze, to jak testowane na Arch, Manjaro, Ubuntu oraz Mint, przy startowaniu systemu powinien nam wyskoczyć monit o hasło do /home/kontener.luks
. Jeśli podane hasło jest poprawne, nasz katalog domowy zostanie automatycznie zamontowany i logując się do środowiska graficznego, logujemy się już do niego.
Tu pewna ciekawostka, dla tych, którzy lubią wieść pewnego rodzaju “podwójne życie” lub po prostu chcą rozdzielić swój profil np. na domowy i związany z pracą.
Jeśli używasz tej metody z szyfrowanym katalogiem domowym, możesz sobie zostawić profil domyślny, czyli taki, który jest aktywny, w przypadku, gdyby szyfrowany katalog domowy nie był podmontowany. Jeśli nie masz potrzeby ciągle pracować i używać zaszyfrowanego /home/USER
, można go nie montować, wtedy w /home/$USER
tworzony jest “normalny” profil, niezaszyfrowany, tak jak w każdym innym systemie. Można tam sobie funkcjonować z zupełnie osobnymi ustawieniami, a jak zajdzie potrzeba, zamontować kontener - którego montowanie nie uszkodzi “normalnego” katalogu, tylko go niejaki “zakryje”. Także tę sztuczkę zostawiam do przemyśleń.
Kopia zapasowa
Na szczęście ten akapit będzie krótki i zwięzły. Ponieważ /home/kontener.luks
to najwyklejszy plik, wystarczy
go skopiować na nośnik/udział, którego używasz do robienia kopii zapasowej - to wszystko!
Film na YT