aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-06-19 02:59:17 +0200
committerWojciech Kosior <kwojtus@protonmail.com>2020-06-19 02:59:17 +0200
commit20b885bc9302e4937d0ec624d061497b68a9229a (patch)
tree71449610b7cf5a51bfb8dff7b601033387b9d4e5
parentdfa1a7d0c3b8d3132453511bf48e9c9eec47f40f (diff)
download0tdns-20b885bc9302e4937d0ec624d061497b68a9229a.tar.gz
0tdns-20b885bc9302e4937d0ec624d061497b68a9229a.zip
użytkowanie na zaliczenie
-rw-r--r--doc/uzytkowanie/main.tex340
1 files 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/<sha256_z_zawarto?ci_configu>.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}