Szyfrowanie logów w OpenWRT (syslog-ng)

Spis treści

We wpisie dotyczącym logread została podniesiona kwestia przesłania logów przez sieć. OpenWRT jest w stanie tego typu zadanie realizować po określeniu kilku dodatkowych opcji w pliku /etc/config/system . Trzeba jednak zdawać sobie sprawę, że tak przesyłane komunikaty nie będą w żaden sposób zabezpieczone. W sieci domowej raczej nie musimy sobie zawracać głowy tym mankamentem. Niemniej jednak, gdy w grę wchodzi przesyłanie logów do zdalnego serwera zlokalizowanego gdzieś w internecie, to taką komunikację należy zabezpieczyć przed podsłuchem. Niestety OpenWRT standardowo nie wspiera takich udziwnień ale dysponuje on pakietami, które mogą nam zapewnić taką funkcjonalność. Szyfrowanie logów możemy w łatwy sposób wdrożyć za pomocą pakietu syslog-ng3 . W nim znajduje się demon syslog-ng , który jest kompatybilny w pełni z innymi linux'owymi demonami logowania. Nie powinno zatem być problemów ze skonfigurowaniem tego całego mechanizmu.

W OpenWRT w wersji Chaos Calmer nie ma pakietu syslog-ng3 . W efekcie szyfrowanie logów routera nie jest obecnie możliwe. Ten wpis dotyczy jedynie wydania Barrier Breaker i zostanie zaktualizowany jak tylko wspomniany pakiet trafi do repozytorium.

Certyfikaty

Będzie nam potrzebny szereg narzędzi, by wygenerować odpowiednie certyfikaty. Jeśli mamy mało miejsca na flash'u routera, generowanie certyfikatów możemy przeprowadzić spod innego systemu operacyjnego. Najlepiej jest do tego zaprzęgnąć pierwszą lepszą dystrybucję linux'a. Możemy także posłużyć się płytką czy pendrive z wgranym systemem live. Temat generowania certyfikatów z wykorzystaniem narzędzi easy-rsa jak i przy pomocy certtool był już poruszany i nie będziemy tutaj opisywać tego procesu. Niemniej jednak, dalsza część tego artykułu zakłada, że dysponujemy już odpowiednimi certyfikatami.

Wyłączenie standardowego logowania w OpenWRT

OpenWRT ma własny mechanizm logowania, który jest odpalany via skrypt /etc/init.d/log . To za jego pomocą wszystkie komunikaty są zapisywane w pamięci operacyjnej RAM. Jeśli zamierzamy przesyłać logi na zdalny serwer logów, będziemy zmuszeni zrezygnować z logd oraz logread , które są odpowiedzialne za logowanie komunikatów na routerze. W przeciwnym razie, syslog-ng otrzyma jedynie tylko część logów. Komunikaty takie jak próby logowania na SSH nie zostaną przesłane przez sieć. A chcemy raczej otrzymać wszystkie wiadomości generowane na routerze. Wyłączamy zatem skrypt /etc/init.d/log z autostartu poniższym poleceniem:

# /etc/init.d/log disable

Poniższa konfiguracja routera zakłada, że dysponujemy już zewnętrznym serwerem logów, do którego zamierzamy przesłać komunikaty z routera. Jeśli by się zdarzyło tak, że nie posiadamy jeszcze takiej maszyny, to wyżej jest link do materiału, który pomoże nam postawić serwer logów na debianie w oparciu o oprogramowanie rsyslog .

Konfiguracja syslog-ng w OpenWRT

Logujemy się na router i dociągamy potrzebne oprogramowanie. Znajduje się ono w pakiecie syslog-ng3 :

# opkg update
# opkg install syslog-ng3

Następnie na router przy pomocy scp kopiujemy uprzednio przygotowane certyfikaty. Pamiętajmy, by utworzyć na nim pierw katalog /etc/syslog-ng.cert/ . W przeciwnym wypadku, to poniższe polecenie zwróci błąd:

# scp ca_192.168.1.150.crt client_192.168.1.1.crt client_192.168.1.1.key root@192.168.1.1:/etc/syslog-ng.cert/

Musimy także przepisać nazwę certyfikatu CA. syslog-ng wymaga, by nazwa tego certyfikatu zawierała jego hash. Ten hash możemy wyciągnąć przy pomocy narzędzia openssl . Poniżej przykład:

# openssl x509 -noout -hash -in ca_192.168.1.150.crt
f31e2e50

Wracamy na router i przechodzimy do katalogu /etc/syslog-ng.cert/ . Tworzymy w nim dowiązanie symboliczne do certyfikatu CA, z tym, że do widocznej wyżej nazwy dodajemy końcówkę .0 :

# ssh root@192.168.1.1
# cd /etc/syslog-ng.cert/
# ln -s ./ca_192.168.1.150.crt f31e2e50.0

Katalog z certyfikatami dla syslog-ng powinien się prezentować następująco:

# ls -al
drwxr-xr-x    2 root     root          4096 Oct 10 20:03 .
drwxr-xr-x    1 root     root          4096 Oct 10 15:27 ..
-rw-r--r--    1 root     root          1525 Oct 10 19:36 ca_192.168.1.150.crt
-rw-r--r--    1 root     root          1643 Oct 10 19:36 client_192.168.1.1.crt
-rw-------    1 root     root          8394 Oct 10 19:36 client_192.168.1.1.key
lrwxrwxrwx    1 root     root            22 Oct 10 20:03 f31e2e50.0 -> ./ca_192.168.1.150.crt

Edytujemy teraz plik konfiguracyjny /etc/syslog-ng.conf . Dokładna jego budowa jest opisana na stronie projektu. Na nasze potrzeby, do tego pliku dodajemy poniższą treść (aktualna wersja pliku znajduje się na moim github'ie):

@version:3.0

options {
    chain_hostnames(off);
    time_reopen (600);
    time_reap(0);
    flush_lines(0);
    log_fifo_size(256);
    create_dirs(no);
    owner(root);
    perm(0600);
    use_dns(no);
    log_msg_size(1024);
    stats_freq(0);
    mark_freq (3600);
    keep_hostname(yes);
    use_fqdn(no);
    long_hostnames(off);
};

source s_all {
    internal();
    unix-stream("/dev/log");
    file("/proc/kmsg" program_override("kernel"));
};

source s_localhost {
    tcp(ip(127.0.0.1) port(514));
    udp(ip(127.0.0.1) port(514));
};

destination d_messages {
    file("/var/log/messages");
};

destination d_network {
#   tcp( "192.168.1.150" port(514) );
    tcp( "192.168.1.150" port(514)
        tls( ca_dir("/etc/syslog-ng.cert")
            key_file("/etc/syslog-ng.cert/client_192.168.1.1.key")
            cert_file("/etc/syslog-ng.cert/client_192.168.1.1.crt")
            peer_verify(required-trusted)
            )
       );
};


log {
    source(s_all);
    source(s_localhost);
    destination(d_messages);
    destination(d_network);
};

Konfiguracja demona syslog-ng sprowadza się do zdefiniowania bloków, w których umieszczamy źródła pochodzenia logów ( source ), oraz takich samych bloków dotyczących miejsca przeznaczenia przetwarzanych komunikatów ( destination ). Blok source s_all zbiera logi z domyślnych lokalizacji systemowych. Dalej jest source s_localhost ale to tylko na wypadek, gdyby jakieś usługi nie łapały się do tego powyższego bloku. Z kolei destination d_messages określa, że logi mają powędrować do sprecyzowanego tam pliku. Kolejny blok ( destination d_network ) odpowiada za przesyłanie logów przez sieć. Ostatni kawałek spina źródła z miejscami docelowymi. W skrócie, wszystkie logi w systemie OpenWRT powędrują zarówno do lokalnego pliku jak i do zdalnego serwera logów.

Przyjrzyjmy się nieco bliżej blokowi odpowiedzialnemu za przesył logów przez sieć. Gdybyśmy odkomentowali pierwszą linijkę i zakomentowali wszystko poniżej do znaku pierwszego średnika ( ; ), to przesył logów przez sieć nie byłby szyfrowany. Czyli mieli byśmy takie samo zachowanie, co w przypadku określania zdalnego logowania via plik /etc/config/system . Z tym, że ten wbudowany mechanizm nie umożliwia szyfrowania komunikatów. I tu właśnie do gry wchodzi pozostała część bloku destination d_network . Pierwsza linijka, ta zaczynająca się od tcp , określa gdzie przesłać logi (adres IP oraz port). W następnej linijce definiujemy, że chcemy zaszyfrować logi przy pomocy modułu tls , na którego konfigurację składa się szereg parametrów. Pierwszy z nich to ca_dir i określa on katalog z certyfikatami, tymi, które wcześniej utworzyliśmy i przesłaliśmy na router. Dodatkowo, to w tym katalogu trzeba umieścić certyfikat CA oraz link z nazwą jego hasha. Dalej mamy key_file oraz cert_file wskazujące na nazwy kluczy routera, odpowiednio prywatnego i publicznego. Ostatnia opcja ( peer_verify ) określa czy weryfikować tożsamość serwera logów (na podstawie certyfikatu CA).

Testowanie komunikacji z serwerem logów

Aktywujemy skrypt /etc/init.d/syslog.ng i generujemy sobie testową wiadomość:

# /etc/init.d/syslog.ng start
# logger -t test my syslog-test-message

Powinna ona zostać zapisana w pliku /var/log/messages . Jeśli tak się stało, oznacza to, że część roboty wykonaliśmy prawidłowo. Trzeba także zalogować się na zdalny serwer logów i zobaczyć czy wiadomość również powędrowała przez sieć i została odszyfrowana. W tym przypadku wszystko gra:

Oct 25 15:27:28 the-mountain.mhouse.lh s_all@the-mountain syslog-ng[2782] syslog-ng starting up; version='3.0.5'
Oct 25 15:27:28 the-mountain.mhouse.lh s_all@the-mountain syslog-ng[2782] Syslog connection established; fd='11', server='AF_INET(192.168.1.150:514)', local='AF_INET(0.0.0.0:0)'
Oct 25 15:27:28 the-mountain.mhouse.lh s_all@the-mountain syslog-ng[2782] Certificate subject matches configured hostname; hostname='192.168.1.150', certificate='192.168.1.150'

Oct 25 15:27:31 the-mountain.mhouse.lh s_all@the-mountain test: my syslog-test-message

Z tym, że by sprawdzić czy komunikat jest faktycznie szyfrowany, a jego treść jest nieczytelna dla osób próbujących podsłuchać transmisję, trzeba posłużyć się jakimś sniffer'em, np. wireshark.

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.