From 20b885bc9302e4937d0ec624d061497b68a9229a Mon Sep 17 00:00:00 2001 From: Wojciech Kosior Date: Fri, 19 Jun 2020 02:59:17 +0200 Subject: użytkowanie na zaliczenie MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/uzytkowanie/main.tex | 340 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 296 insertions(+), 44 deletions(-) diff --git a/doc/uzytkowanie/main.tex b/doc/uzytkowanie/main.tex index 2339c93..3625160 100644 --- a/doc/uzytkowanie/main.tex +++ b/doc/uzytkowanie/main.tex @@ -4,7 +4,7 @@ \usepackage{url} \usepackage{xcolor} \usepackage[ampersand]{easylist} -\newcommand{\dir}[1] {\texttt{\color{teal} \detokenize{#1}}} +\newcommand{\dir}[1] {\texttt{\color{teal} \detokenize{#1}}} \definecolor{orange}{rgb}{1,0.5,0} \newcommand{\file}[1] {\texttt{\color{orange} \detokenize{#1}}} \newcommand{\filepath}[1] {\texttt{\color{violet} \detokenize{#1}}} @@ -14,28 +14,66 @@ \maketitle \begin{sloppypar} -\section{Instalacja części back-endowej} +Przykłady komend konsolowych w niniejszym dokumencie idą za konwencją, wg. +której komenda wykonywana jako użytkownik root poprzedzona jest znakiem '\#', +a komenda wykonywana jako inny użytkownik - znakiem '\$'. + +\section{Wymagania części back-endowej systermu} +\subsection{System} +Ze względu na użycie linuksowych przestrzeni nazw, back-end 0tdns działa obecnie +wyłącznie pod systemami z rodziny GNU/Linux. + +Dodatkowo, konieczne jest wsparcie jądra dla przekazywanie pakietów IP +(forwarding), sieciowych przestrzeni nazw (namespace'ów), iptables i urządzeń +tun. + +\subsection{Zależności} +\begin{enumerate} +\item cron (w dużej części dystrybucji automatycznie zainstalowany) +\item libunbound z bindingiem do pythona3; w rodzinie Debiana możliwy do + zainstalowania przez +\begin{verbatim} +# apt install python3-unbound +\end{verbatim} +\item python3 (system był tworzony pod pythonem 3.5.3) +\item openvpn; w rodzinie Debiana możliwy do zainstalowania przez +\begin{verbatim} +# apt install openvpn +\end{verbatim} +\item iptables; w rodzinie Debiana możliwe do zainstalowania przez +\begin{verbatim} +# apt install iptables +\end{verbatim} +\end{enumerate} + +\subsection{Uwagi} +Skrypty systemu są uruchamiane cyklicznie przez demona crona. Aby system +działał, musi być uruchomiony demon crona. Najskuteczniejszym rozwiązaniem jest +uruchamianie crond przy starcie systemu (w niektórych dystrybucjach, +w szczególności tych z rodziny Debiana, domyślnie włączone). + +\section{Instalacja części back-endowej} +\subsection{Pobranie systemu} W celu zainstalowania systemu klonujemy repozytorium: \url{https://repo.or.cz/0tDNS.git} -i wykonujemy jako root: +\begin{verbatim} +$ git clone https://repo.or.cz/0tDNS.git && cd 0tdns +\end{verbatim} + +\subsection{Instalacja plików wchodzących w skład systemu} +Wykonujemy jako użytkownik root: \begin{verbatim} # ./install.sh \end{verbatim} Skrypt \file{install.sh} przekopiowuje do \dir{/var/lib/0tdns/} -oraz do \dir{/usr/sbin/} skrypty wchodzące w skład systemu. - +oraz do \dir{/usr/sbin/} i \dir{/usr/bin/} skrypty wchodzące w skład systemu. Oprócz tego \file{install.sh} umieszcza importowany przez inne skrypty \file{ztdnslib.py} w \dir{/usr/lib/python3/dist-packages/} oraz kopiuje \file{db_connection_config.yml} do katalogu \dir{/etc/0tdns/}. -Programy działające w ramach systemu automatycznie sukają konfiguracji -systemu pod \filepath{/etc/0tdns/db_connection_config.yml}. Dostarczony plik -jest domyślną konfiguracją, którą administrator systemu powinien zmodyfikować -precyzując w niej adekwatny adres bazy danych i inne parametry. - Przy wywołaniu \file{install.sh} można ustawić odpowiednią zmienną środowiskową \begin{verbatim} @@ -52,7 +90,8 @@ Efekt jest w obu przypadkach taki sam - wszystkie pliki zostaną zainstalowane w \dir{/some/path/}, co może zostać wykorzystane do instalacji wewnątrz chroot'a lub do stworzenia pakietu dystrybucji. -Po instalacji plików w systemie konieczne jest utworzenie użytkownika +\subsection{Automatyczna część konfiguracji systemu} +Po instalacji plików w systemie konieczne jest utworzenie użytkownika 0tdns i dodanie wpisów do crontaba, co wykonać można wywołaniem skryptu \begin{verbatim} @@ -62,9 +101,182 @@ i dodanie wpisów do crontaba, co wykonać można wywołaniem skryptu Funkcjonalność \file{setup.sh} i \file{install.sh} została rozdzielona z myślą o dystrybucji systemu. +\subsection{Ładowanie niezbędnych modułów jądra} +Dla działania systemu potrzebne są sterowniki tun i ip\_tables. +W zależności od dystrybucji mogą one być wbudowane w jądro lub dostarczone +w postaci modułów. W tym drugim przypadku konieczne jest załadowanie modułów: + +\begin{verbatim} +# modprobe tun +# modprobe ip_tables +\end{verbatim} + +Tak załadowany moduł działa do momentu ponownego uruchomienia systemu +operacyjnego. Aby moduły były automatycznie ładowane przy starcie, należy wpisać +je do odpowiedniego pliku konfiguracyjnego: + +\begin{verbatim} +# echo tun >> /etc/modules +# echo ip_tables >> /etc/modules +\end{verbatim} + +\subsection{Włączenie przekierowywania pakietów} +Aby 0tdns działał, jądro musi przekazywać pakiety IP z domyślnego urządzenia +sieciowego na urządzenia veth, które będą tworzone (za włączenie przekazywania +pakietów w drugą stronę - od urządzenia veth - odpowiadają skrypty systemu). +Ta funkcjonalność jest domyślnie wyłączona w przypadku większości dustrubucji. +Jeśli dane jądro ją wspiera, można ją włączyć poprzez zapis do odpowiedniego +pliku w systemie plików \filepath{/proc}. + +\begin{verbatim} +# echo 1 > /proc/sys/net/ipv4/conf/all/forwarding +\end{verbatim} + +Powyższy przykład pokazuje, jak włączyć przekazywanie ruchu ze wszystkich +urządzeń. Znając nasze główne urządzenie (tj. to łączące nas z siecią internet), +możemy włączyć przekazywanie jedynie pakietów przychodzących z niego. +Przykładowo, jeśli tym urządzeniem jest eth0: + +\begin{verbatim} +# echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding +\end{verbatim} + +Tak wprowadzona zmiana nie jest jednak persystentna ze względu na ponowne +uruchomienia systemu operacyjnego. Aby tak się stało, należy zmodyfikować +odpowiedni plik konfiguracyjny: + +\begin{verbatim} +# echo 'net.ipv4.conf.eth0.forwarding=1' >> /etc/sysctl.conf +\end{verbatim} + +\subsection{Uzupełnienie pliku konfiguracyjnego} +Programy działające w ramach systemu automatycznie sukają konfiguracji +systemu pod \filepath{/etc/0tdns/db_connection_config.yml}. Dostarczony plik +jest domyślną konfiguracją, którą administrator systemu powinien zmodyfikować +precyzując w niej adekwatny adres bazy danych i inne parametry zgodnie +ze specyfikacją w rozdziale poniżej. + +\section{Konfiguracja części back-endowej} \label{config} +Konfiguracja systemu odbywa się poprzez plik +\filepath{/etc/0tdns/db_connection_config.yml}. Domyślna, wymagająca +uzupełnienia konfiguracja, jest dostarczona z systemem. + +Wykorzystany jest tu format yaml. Możliwe jest dodawanie komentarzy +zaczynających się od znaku '\#'. + +Poniżej wyjaśnione jest znaczenie poszczególnych zmiennych w pliku +konfiguracyjnym. + +\subsection{Zmienna user} +Zawiera nazwę używanego użytkownika (roli) w bazie danych. Nazwa może - choć +jeśli nie zawiera znaków specjalnych, to nie musi - być zamknięta w cudzysłów. + +Przykład: +\begin{verbatim} +user: postgres +\end{verbatim} + +\subsection{Zmienna password} +Zawiera hasło do bazy podanego w zmiennej user użytkownika. Nazwa może - choć +jeśli nie zawiera znaków specjalnych, to nie musi - być zamknięta w cudzysłów. + +Przykład: +\begin{verbatim} +password: postgres +\end{verbatim} + +\subsection{Zmienna host} +Zawiera adres bazy danch. Może to być zarówno nazwa domenowa, jak i adres IP. + +Przykład: +\begin{verbatim} +host: "127.0.0.1" +\end{verbatim} + +\subsection{Zmienna port} +Zawiera port, na którym należy łączyć się z bazą danych. Port może, choć nie +musi, być wzięty w cudzysłów. + +Przykład: +\begin{verbatim} +port: "5432" +\end{verbatim} + +\subsection{Zmienna database} +Zawiera nazwę używanej bazy w systemie bazodanowym. Nazwa może - choć jeśli nie +zawiera znaków specjalnych, to nie musi - być zamknięta w cudzysłów. + +Przykład: +\begin{verbatim} +database: "ztdns" +\end{verbatim} + +\subsection{Zmienna enabled} +Precyzuje, czy instancja back-endu ma pracować. Jeśli zmienna ustawiona jest na +``yes'' - system działa normalnie i cogodzinnie wykonywane są zapytania. Jeśli +ustawiona jest na ``no'' - system jest wyłączony. + +Dzięki tej zmiennej możliwe jest czasowe wyłączenie danej instancji systemu, +np. w wypadku awarii. W dostarczonym szablonie pliku konfiguracyjnego system +nie jest włączony. + +Wartość zmiennej może - choć nie musi - buć wzięta w cudzysłów. + +Przykłady: +\begin{verbatim} +enabled: no +\end{verbatim} +\begin{verbatim} +enabled: "yes" +\end{verbatim} + +\subsection{Zmienna handled\_vpns} +Ma ona zawierać listę bazodanowych id serwerów VPN, które ta instancja back-endu +ma obsługiwać. Tym samym możliwe jest rozdzielenia pracy na kilka maszym. + +Ta zmienna może pozostać nieustawiona - wtedy dana instancja systemu będzie +obsługiwała wszystkie połączenia VPN w bazie danych. + +W liście mogą się znaleźć także id, które nie występują w bazie danych. + +Przykład: +\begin{verbatim} +handled_vpns: [1, 2, 17] +\end{verbatim} + +\subsection{Zmienna parallel\_vpns} +Zmienna, która decyduje o tym, ile połączeń VPN może być zestawionych +jednocześnie. System w żadnym momencie nie nawiąże więcej połączeń VPN, niż +wynosi wartość tej zmiennej. Umożliwia to administratorowi kontrolowanie +obciążenia maszyny i łącza sieciowego. + +Zmienna powinna być liczbą, nieotoczoną cudzysłowami. + +Przykład: +\begin{verbatim} +parallel_vpns: 20 +\end{verbatim} + +\subsection{Zmienna private\_addresses} +Zmienna zawiera listę zakresów adresów IP, które system może nadawać parom +veth. Format pojedynczego zakresu to +``{\textless}adres\_ipv4{\textgreater} - {\textless}adres\_ipv4{\textgreater}''. +Znaki białe naokoło myślnika są +opcjonalne. Spośród podanych w tej zmiennej zakresów powinno dać się wybrać +przynajmniej tyle podsieci z maską /30, ile wynosi wartość zmiennej +parallel\_vpns (niespełnienie tego wymogu objawi się odpowiednimi +wpsami w logach). + +Przykład: +\begin{verbatim} +private_addresses: ["10.25.25.0 - 10.25.25.59", "10.25.26.0 - 10.25.26.255"] +\end{verbatim} + + \section{Deinstalacja części back-endowej} -W celu odwrócenia zmian dokonanych przez \file{setup.sh} należy wywołać +W celu odwrócenia zmian dokonanych przez \file{setup.sh} należy wywołać (jako +root) \begin{verbatim} # ./uninstall.sh @@ -78,38 +290,78 @@ Jeśli z systemu mają być usunięte także pliki zainstalowane przez skrypt \end{verbatim} \section{Działanie części back-endowej systemu} -Demon crona co gdzin uruchamia skrypt \file{hourly.py}, który łączy się -z bazą (używając funkcji z \file{ztdnslib.py}, która czyta -konfigurację \filepath{/etc/0tdns/db_connection_config.yml}). - -Skrypt \file{hourly.py} pobiera z bazy id wszystkich połączeń VPN, -które nawiąże w celu odpytywania serwerów DNS. - -Dla każdego VPN \file{hourly.py} sprawdza, czy jego plik konfiguracyjny -znajduje się w systemie. Jeżli nie, jest pobierany z bazy i zapisywany -jako \filepath{/var/lib/0tdns/.ovpn}. - -Następnie dla każdego VPN wywoływany jest skrypt \file{vpn_wrapper.sh} -(nie powinien on być uruchamiany manualnie, a jedynie wywoływany przez -\file{hourly.py}), któremu jako argumenty podawane są kolejno: -\begin{easylist} - & ścieżka do pliku konfiguracyjnego OpenVPN - & fizyczny adres ip systemu (tj. adres źródłowy, który powinny mieć nieroutowane - przez VPN datagramy IP) - & zawarte w jednym argumencie oddzielone od siebie znakami białymi adresy - podsieci, do których ruch nie powinien być routowany przez VPN - & polecenie (plik wykonywalny) do uruchomienia wewnątrz namespace'a - (jest nim \filepath{/var/lib/0tdns/perform_queries.py}, który również - czyta konfigurację 0TDNS i łączy się z bazą danych przed wykonaniem - zapytań DNS) - & argumenty do programu wykonywanego wewnątrz namespace'u skryptu - && godzina wywołania \file{hourly.py} - && id VPN w bazie -\end{easylist} - -Skrypt \file{vpn_wrapper.sh} otwiera połączenie VPN, tworzy namespace, -przekierowuje ruch z namespace przez VPN i uruchamia podaną komendę wewnątrz -namespace'a. Po jej zakończeniu zamyka połączenie VPN i usuwa namespace. +\subsection{Cogodzinne odytywanie serwerów DNS} +Demon crona co godzinę uruchamia skrypt \file{hourly.py}, który czyta +konfigurację \filepath{/etc/0tdns/db_connection_config.yml}, następnie łączy się +z bazą danych i pobiera z niej id wszystkich serverów VPN, z którymi ma nawiązać +połączenie w celu odpytywania serwerów DNS. + +Dla każdego serwera VPN \file{hourly.py} sprawdza, czy jego plik konfiguracyjny +znajduje się w systemie. Jeżli nie, jest pobierany z bazy i zapisywany pod +\dir{/var/lib/0tdns/}. + +Przez zestawione połączenia VPN odpytywane są odpowiednie serwery DNS, a wyniki +są umieszczane w bazie danych. + +\subsection{Sprawdzanie zakończenia wykonania} +Skrypt \file{hourly.py} na początku działania tworzy plik +\filepath{/var/lib/0tdns/lockfile}, który na końcu działania usuwa. Jeśli plik +istnieje w systemie, oznacza to, że jakaś instancja \file{hourly.py} pracuje. + +Jeśli w momencie rozpoczęcia wykonania \file{hourly.py} plik lockfile istnieje, +skrypt, aby uniknąć kolizji ze swoją wcześniejszą instancją, zakończy działanie +bez wykonania zapytań DNS. Ten mechanizm stanowi zabezpieczenie na wypadek +sytuacji szczególnej, jak np. błąd systemu. W normalnych warunkach +\file{hourly.py} powinien zakończyć działanie w czasie dużo krótszym, niż +godzina. + +Dodatkowo, 15, 30 i 45 minut po każdej godzine uruchamiany jest przez demon +crona skrypt \file{check_if_done.py}, który sprawdza, czy plik lockfile istnieje +i jeśli tak - wykonuje zapis do logów oraz wysyła maila do administratora +(niezaimplementowane). + +Na wypadek nagłego wyłączenia systemu operacyjnego, do crontaba dodawane jest +polecenie usunięcia pliku lockfile w momencie ponownego uruchomienia. + +\subsection{Powiadamienie mailowe} +O każdej równej godzinie uruchamiany jest skrypt send\_emails, +który sprawdza w bazie danych, jakie błędne adresy były zwrócone w poprzedniej +godzinie i wysyła alert do odpowiednich użytkowników. + +\subsection{Logi} +Logi zapisywane są do pliku \filepath{/var/log/0tdns.log}. Znajdują się tam +oznaczone godziną informacje m.in. o nawiązywanych i nieudanych połączeniach +VPN, działających zbyt długo instancjach skryptu \file{hourly.py} i błędach +w podanych w konfiguracji zakresach adresów IP. + +\subsection{Zmiany w bazie danych} +Wraz z wykonaniem zapytań DNS dodawane są do tabeli +user\_side\_responses oraz ew. user\_side\_response +wpisy z wynikami. Możliwe wartości pola 'results' +w user\_side\_responses to: +\begin{itemize} + \item 'successful' - od serwera DNS przyszła odpowiedź, że domena istnieje + (jedyny przypadek, kiedy mogą (choć nie muszą) być do tego rekordu dowiązane + rekordy w user\_side\_response) + \item 'not exists' - serwer DNS twierdzi, że domena nie istnieje + \item 'no reponse' - nie przyszła żadna odpowiedż od serwera DNS + \item 'DNS error: \textless jaki błąd\textgreater ' - jeśli zwrócony został + inny kod błędu, niż powyższe + \item 'internal failure: out of memory' - wykorzystywany libunbound zwrócił + wartość informującą, że zapytanie DNS się nie powiodło z powodu braku + pamięci + \item 'internal failure: vpn\_connection\_failure' - nie udało się + nawiązać danego połączenia VPN + \item 'internal failure: process\_crash' - błąd skryptu + wchodzącego w skład systemu +\end{itemize} + +Nie rozróżniamy na tym etapie, czy ip zwrócone zgadzają się z oczekiwanymi. + +Razem z dodaniem wpisu innego typu, niż 'internal failure:', zmniejszany +jest licznik ważności odpowiedniego rekordu w tabeli +user\_side\_queries lub rekord jest usuwany +(jeśli licznik osiągnął 0). \end{sloppypar} \end{document} -- cgit v1.2.3