DKIM (podpis domenowy) – czyli krok drugi w walce ze spamem. Wstęp do kryptografii klucza publicznego.

DKIM (DomainKeys Identified Mail) rekord DNS zwany czasami „podpisem domenowym”.

W poprzednim artykule zapoznaliśmy się z rekordami SPF, które pozwalają na weryfikację serwera pocztowego pod kątem praw do wysyłania poczty dla danej domeny. W tym momencie, ktoś może zapytać, skoro mamy ten mechanizm to po co kombinować dalej? Niestety nie jest tak różowo. Zastanówmy się chwilę – rekord SPF pozwala nam sprawdzić jakie adresy IP mają prawo wysyłać pocztę z domeny zxy i to wiemy, co jednak w następujących sytuacjach:

  1. ktoś dokonuje modyfikacji pakietów, zmieniając adres źródłowy, na prawidłowy przekazywany przez rekordy SPF
  2. ktoś dokonuje przechwycenia poczty i podmienia adresy pocztowe (źródłowe i/lub docelowe)
  3. podobnie jak w punkcie 2 następuje podmiana treści wiadomości na oprogramowanie szkodliwe, przy okazji zmieniając informację w email o rodzaju treści i podmienia pole „content-type” wpływając na mechanizmy klientów pocztowych skłaniając je do uruchomienia złośliwego oprogramownia

Takich potencjalnych scenariuszy może być wiele. Tak czy owak, rekordy SPF pomimo swojej bardzo dużej przydatności (i prostoty wdrożenia, co jest bardzo ważne) nie rozwiązują wszystkich problemów związanych z uwierzytelnieniem serwera, a w zasadzie uwierzytelnieniem przesyłanych wiadomości. Zauważając ograniczenia SPF i jednocześnie bezpieczeństwo jakie zapewnia współczesna kryptografia postanowiono wykorzystać mechanizm klucza publicznego w celu weryfikacji wysyłanych emaili. Aby dokładniej zrozumieć działanie rekordów DKIM, należy przypomnieć sobie:

Kryptografia klucza publicznego – uwierzytelnienie adresata

Fajny opis jest na wiki, ale w dużym skrócie: opiera się na parze komplementarnych kluczy kryptograficznych, których najważniejszą cechą jest to, że wiadomość zaszyfrowaną kluczem A, można odszyfrować tylko kluczem B i odwrotnie, szyfrując B można odszyfrować tylko A. Nie ma możliwości szyfrowania A i odszyfrowywania A, lub szyfrowania B i odszyfrowywania B. Skoro ta para tak działa, to wybiera się jeden z kluczy (wybiera się, ponieważ z punktu widzenia matematyki oba są identyczne), ewentualnie zabezpiecza się go hasłem i nazywa kluczem prywatnym (czyli takim, który posiada tylko właściciel), natomiast drugi z pary nazywa się kluczem publicznym, który nie jest w żaden sposób zabezpieczony – a nawet więcej „wszem i wobec” się go ogłasza, tak aby każdy zainteresowany miał do niego dostęp. W tym momencie, jeżeli ktoś chce wysłać wiadomość i mieć pewność, że odbierze go właściwa osoba, szyfruje się go kluczem publicznym tej osoby, a z właściwości opisanej wcześniej wiadomo, że tylko posiadacz klucza prywatnego będzie mógł tą wiadomość odszyfrować ponownie. Mamy załatwioną sprawę zapewnienia, aby wiadomość trafiła do właściwego adresata (pod warunkiem, że mamy jego klucz publiczny), nam jednak przy wysyłaniu poczty nie zależy na uwierzytelnieniu adresata, ale odwrotnie, na uwierzytelnieniu nadawcy – czy to da się zrobić tym samym mechanizmem? Chyba już znacie odpowiedź – tak to mechanizm nazwany podpisem elektronicznym. I znowu, jest wiele implementacji podpisu, ale ja opowiem jak wygląda idea, która jest wykorzystywana w DKIM (bo tutaj właśnie mamy do czynienia z mechanizmem podpisu elektronicznego).

Kryptografia klucza publicznego – podpis elektroniczny, jako metoda uwierzytelnienia nadawcy

Wyobraźmy sobie taką sytuację: ogłosiliśmy nasz klucz publiczny, tak że każdy zainteresowany (a przynajmniej nasz adresat) ma do niego dostęp. Następnie tworzymy wiadomość, którą na końcu szyfrujemy naszym kluczem prywatnym. Na końcu wysyłamy zaszyfrowaną wiadomość i wraz z wiadomością niezaszyfrowaną. Teraz adresat odczytuje list, ale jednocześnie korzystając z naszego klucza publicznego odszyfrowuje też wiadomość zaszyfrowaną i … porównuje z niezaszyfrowaną. W tym momencie, wiedząc że odszyfrowana wiadomość musiała być zaszyfrowana kluczem prywatnym i że obie wiadomości: zaszyfrowana i nieszyfrowana są identyczne ma pewność, że wiadomość nie została zmanipulowana, czyli ma zapewnioną tzw: integralność wiadomości. Zaraz jednak podniosą się głosy – co za bezsensowne rzeczy wypisuję, skoro całą wiadomość mieliśmy zaszyfrowaną i ją odszyfrowaliśmy, to po co jeszcze porównywać ją z nieszyfrowaną … Co by jednak było, gdyby nadawca zamiast szyfrować całą wiadomość, wykorzystałby funkcję skrótu taką jak md5, sha1, sha256 (które w założeniach generują stały w długości wynik, który jest niepowtarzalny dla każdej różnej wiadomości, a jednocześnie jest taki sam dla każdej takiej samej wiadomości) w celu wyliczenia wartości z całej wiadomości, następnie ten wynik zaszyfrowałby swoim kluczem prywanym i tylko ten zaszyfrowany wynik funkcji skrótu z wiadomości wysłałby razem z niezaszyfrowaną wiadomością jako jej załącznik. Teraz odbiorca czyta sobie „jak biały człowiek” wiadomość, bez potrzeby jej deszyfrowania, a jeżeli ma potrzebę sprawdzenia integralności wiadomości, samodzielnie wylicza skrót wiadomości, odszyfrowuje kluczem publicznym skrót nadawcy i oba wyniki funkcji skrótu porównuje ze sobą. Jeżeli są identyczne, ma pewność (o ile korzysta z nieskompromitowanych funkcji skrótu o czym później) że wiadomość wysłał właściciel klucza prywatnego oraz że nie została zmanipulowana jej treść. Pojawia się pytanie dlaczego nie szyfrować całej wiadomości, a korzystać z funkcji skrótu… otóż takie rozwiązanie ma ona następujące zalety:

  1. zawsze tworzy identycznej długości odpowiedź (MD5 – 128 bitów, SHA1 – 160 bitów, SHA256 – 256 bitów …) co ważne bez względu na długość wiadomości (no prawie, bo SHA1 ma ograniczenie wiadomości 2 do potęgi 64 bitów, czyli w sumie baaardzo dużo) , zatem bez problemu można wyliczyć skrót z pliku który ma kilka GB i też wynik będzie wiarygodny
  2. odbiorca nie musi poświęcać czasu na odszyfrowywanie wiadomości, aby zapoznać się z jej treścią (oszczędność czasu i wygoda)
  3. skrót można przekazać inną drogą a treść inną, co dodatkowo podnosi bezpieczeństwo transmisji

Żeby nie było tak różowo, teraz przysłowiowa „łyżka dziegciu” , taki podpis wiadomości jest tak dobry, jak dobra jest funkcja skrótu. Dzisiaj już jest udowodnione, że jest możliwe utworzenie dwóch różnych plików, takich aby wynik MD5 był identyczny… owszem nie ma dowolności w tych plikach, ale sam fakt możliwości wystąpienia takiej sytuacji powoduje, że MD5 jako funkcja skrótu nie może być wykorzystywana. Na dzień dzisiejszy w miarę bezpieczną funkcją jest SHA1, ale w przypadku DKIM używa się SHA-256.

Zatem podpis elektroniczny, to nic innego jak skrót wiadomości zaszyfrowany kluczem prywatnym nadawcy.

Wracamy zatem do tematu podpisu domenowego. Pewnie już Wam świta, jak to wykorzystać w przypadku poczty … wyliczyć funkcję skrótu z określonych pól nagłówka email (najczęściej nadawca, odbiorca, temat), a następnie zaszyfrować wynik kluczem prywatnym. Pozostaje kwestia udostępnienia zainteresowanym klucza publicznego … ale zaraz przecież i tak wszyscy, którzy chcą wysłać do nas list muszą korzystać z serwera DNS, który utrzymuje naszą domenę i wskazuje adresy serwerów pocztowych. Zatem jako nośnik klucza publicznego wykorzystujemy – serwer dns. Teraz umieszczamy dla danej domeny odpowiedni rekord z polem tekstowym zawierającym odpowiednio sformatowany klucz publiczny i … nazywamy go … rekordem DKIM.

Zwracam uwagę, że podpisuje się tylko nagłówek listu, a nie jego treść. Dlaczego? Wynika to z tego, że ma to być zabezpieczenie uwierzytelniające serwer nadawczy, a nie zabezpieczający transmisję wiadomości. Zresztą, gdyby serwer pocztowy miał wyliczać skrót każde wiadomości w całości, a użytkownicy wysyłali by załączniki po kilka MB, moce obliczeniowe serwera w całości  byłby wykorzystywane na potrzeby DKIM, a nie na szybkie wysyłanie ewentualne skanowanie poczty, co jest naczelnym zadaniem takiego systemu. Zatem jeżeli użytkownik potrzebuje zabezpieczyć swoją korespondencję musi sam zająć się ewentualnym podpisywaniem treści wiadomości.

Wiemy co to jest rekord DKIM, jak działa. Pora na trochę szczegółów technicznych (wszystkie są opisane w RFC4871). DKIM wymaga:

  1. funkcji skrótu min. SHA1, ale zalecana jest SHA256 (aczkolwiek DKIM wspiera też inne). SHA1 wykorzystywane, tylko w przypadkach gdzie są małe moce komputerów, a nie zależy mocno na bezpieczeństwie
  2. kryptografia klucza publicznego oparta na kluczach RSA, z tym że podpisujący MUSI wspierać klucze RSA o długości min. 1024 bitów, natomiast weryfikujący MUSI mieć możliwość korzystania z kluczy RSA od 512 do 2048 bitów i jednocześnie powinien mieć możliwość weryfikowania dłuższych kluczy
  3. należy pamiętać, że wykorzystanie dłuższych kluczy RSA niż 2048 bitów, w szczególności od 4096 bitów i więcej może spowodować, że odpowiedź serwera DNS z kluczem może się nie zmieścić w 512 bitowy pakiet UDP odpowiedzi serwera DNS

Zatem znając formalne wymagania minimalne na DKIM, bezpiecznie jest przyjąć, że korzystamy z funkcji skrótu SHA256 oraz kluczy RSA o długości 2048 bitów. Co jest kompromisem wydajności i bezpieczeństwa.

Wcześniej opisałem, że wykorzystuje się 2 klucze: prywatny oraz publiczny. Właściciel musi mieć oba, dlatego przyjęło się, że klucz prywatny, to tak naprawdę plik zawierający oba klucze, natomiast „świat” otrzymuje tylko jeden z nich, nazywany umownie kluczem publicznym.

Tworzenie rekordu DKIM

Tworzenie kluczy zrealizujemy w oparciu o pakiet OpenSSL dostępny na każdej platformie. Ja korzystam z CentOS 6, ale składnia powinna być taka sama też w innych dystrybucjach linuksa.

Jak już wspomniałem wcześniej DKIM wykorzystuje klucze RSA o zalecanej długości 2048 bitów. Klucz prywatny, ze względu że będzie wykorzystywany przez serwer pocztowy powinien być utworzony bez hasła. Zatem:

  1. Tworzenie pliku zawierającego klucze prywatne i publiczne (dla serwera pocztowego naszej domeny): openssl genrsa -out private.key 2048
  2. „Wydobycie klucza publicznego” i zapisanie go do pliku: openssl rsa -in private.key -pubout -out public.key
  3. Ewentualna konwersja klucza prywatnego do formatu PEM wymaganego przez niektóre serwery pocztowe (np. mam nadzieję opisany później przeze mnie serwer iRedmail): openssl rsa -in private.key -out private.key.pem -outform PEM

Dla ułatwienia proponuję skrypt w bash, który za argument będzie przyjmował nazwę domeny, a w wyniku jego działania pojawią się 3 klucze: prywatny, prywatny w standardzie PEM oraz publiczny.

#!/bin/bash
openssl genrsa -out $1.private.key 2048
openssl rsa -in $1.private.key -pubout -out $1.public.key
openssl rsa -in $1.private.key -out $1.private.key.pem -outform PEM

Po utworzeniu pary kluczy RSA należy utworzyć odpowiednio sformatowany rekord DKIM. Polecam następującą stronę z automatyzującą generowanie DKIM. Formularz wypełniamy następująco:

  • „Your domainame” – nasza_domena.pl
  • „Selector” – najczęściej: default lub dkim, w zależności od serwera. W przypadku iRedMail należy wpisać dkim
  • „Granularity” – podobnie jak przy rekordzie SPF, określamy adresy serwerów, które mogą podpisywać listy – domyślnie wszystkie serwery pocztowe danej domeny określone rekordami mx w dns – pozostawiamy domyślne „Allow any…
  • „Allowed Hash Algorithms” – jeżeli zależy nam na bezpieczeństwie, zaznaczamy SHA256 jako jedyna funkcja skrótu dopuszczalna do użycia przez serwer pocztowy, domyślnie jest „all„, czyli dopuszcza zgodnie z RFC też SHA1
  • „Notes” – nieobowiązkowy opis, może być puste
  • „Public key” – najważniejsze pole, tutaj wklejamy zawartość pliku z kluczem publicznym bez pierwszej i ostatniej linii zawierającej „BEGIN PUBLIC KEY” oraz „END PUBLIC KEY”
  • „Service type” – wybieramy „mail
  • „Testing” – jeżeli podpis ma być wykorzystywany produkcyjnie pozostawiamy „…NOT testing DKIM” Jest to informacja dla serwerów pocztowych, czy może niewłaściwy podpis DKIM być powodem odrzucenia poczty, czy też DKIM jest w testach i ma tylko wspomagać pracę serwerów przyjmujących pocztę.
  • „Subdomain” – jeżeli planujemy wykorzystanie tej samej pary kluczy do DKIM dla poddomen to zmieniamy na „are allowed”, domyślnie przyjmuje się że każda domena / poddomena posiada „swój” rekord DKIM

Ostatnim elementem jest utworzenie wygenerowanego ciągu znaków jako rekord DKIM na serwerze autorytatywnym dla nasza_domena.pl, podobnie jak to widać na poniższym rysunku (obraz pokazuje dla selektora „default”):

rekordy domeny

I to już koniec.

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany.