aboutsummaryrefslogtreecommitdiff
path: root/doc/uzytkowanie/main.tex
blob: 362516088515e0a052a6eaa5ae5930b640061eb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
\documentclass{hitec}
\usepackage{polski}
\usepackage[utf8]{inputenc}
\usepackage{url}
\usepackage{xcolor}
\usepackage[ampersand]{easylist}
\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}}}
\author{Mateusz Bielesz, Wojciech Kosior, Marek Moryl, Kamil Szarek}
\title{Użytkowanie 0TDNS}
\begin{document}
\maketitle

\begin{sloppypar}

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}
\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/} 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/}.

Przy wywołaniu \file{install.sh} można ustawić odpowiednią zmienną środowiskową

\begin{verbatim}
$ INSTALL_ROOT=/some/path/ ./install.sh
\end{verbatim}

lub podać argument do skryptu

\begin{verbatim}
$ ./install.sh /some/path/
\end{verbatim}

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.

\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}
# ./setup.sh
\end{verbatim}

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ć (jako
root)

\begin{verbatim}
# ./uninstall.sh
\end{verbatim}

Jeśli z systemu mają być usunięte także pliki zainstalowane przez skrypt
\file{install.sh}, można użyć następującej flagi

\begin{verbatim}
# uninstall.sh --delete-files
\end{verbatim}

\section{Działanie części back-endowej systemu}
\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}