Homelab od zera, cz. 2: AdGuard Home w Dockerze dla całego domu
Docker, Portainer i AdGuard Home na Ubuntu Server, zwolnienie portu 53, podpięcie DNS w routerze i listy CERT Polska. Filtr reklam, śledzenia i phishingu dla każdego urządzenia w domu, bez instalowania czegokolwiek na telefonach.
Read in EnglishW części 1 postawiliśmy Ubuntu Server ze stałym adresem 192.168.0.200 i dostępem przez SSH. Teraz instalujemy na nim AdGuard Home, czyli serwer DNS, który zanim wyśle zapytanie dalej, sprawdza je z listami reklam, trackerów i złośliwych domen. Jeśli domena jest na liście, urządzenie po prostu jej nie dostanie.
Najlepsze jest to, że działa to na wszystkich urządzeniach w sieci naraz: telefonie mamy, tablecie babci, telewizorze. Nikt nic nie instaluje, a strona phishingowa podszywająca się pod bank nawet się nie otworzy.
Jak to zainstalować?
Mamy kilka opcji: AdGuarda można zainstalować bezpośrednio w systemie albo w kontenerze Dockera. Ja lubię pracować z Dockerem, więc pokażę tę drogę. Jest odrobinę bardziej skomplikowana, ale sprzedam wam protip: użyjemy Portainera, czyli graficznej nakładki na Dockera działającej w przeglądarce. Dzięki niemu kolejne usługi stawia się kilkoma kliknięciami.
Krok 1: Docker
Najpierw czyścimy ekran po aktualizacji z części 1 komendą clear (kurczę, jak mi tu brakuje zsh). Większość komend jest na stronie Dockera. Na początek upewniamy się, że mamy curl:
sudo apt install -y curl
U mnie curl już był, więc przechodzimy do meritum. Docker ma oficjalny skrypt instalacyjny:
curl -fsSL https://get.docker.com | sudo sh
Uwaga z punktu widzenia bezpieczeństwa: curl ... | sudo sh oznacza „pobierz skrypt z internetu i od razu uruchom go jako root”. Tu jest to oficjalny skrypt Dockera pobierany po HTTPS, więc ryzyko jest małe, ale dobrze wiedzieć, co się robi. Ostrożniejsza wersja to pobrać skrypt, przeczytać go i dopiero wtedy uruchomić:
curl -fsSL https://get.docker.com -o get-docker.sh
less get-docker.sh
sudo sh get-docker.sh
Instalacja się powiodła. Zwróćcie uwagę na ostrzeżenie na końcu: dostęp do Dockera to praktycznie dostęp do roota na całej maszynie.
Żeby nie pisać sudo przed każdą komendą Dockera, dodajemy naszego użytkownika do grupy docker, a newgrp od razu odświeża uprawnienia bez wylogowania:
sudo usermod -aG docker $USER
newgrp docker
Pamiętajcie, że przez wspomniane ostrzeżenie grupa docker to w praktyce drugie sudo, więc dodajemy do niej tylko siebie. Sprawdzamy, czy wszystko działa:
docker run --rm hello-world
docker compose version
Krok 2: Portainer
Tworzymy folder dla naszego kolegi i plik docker-compose.yml:
mkdir -p ~/portainer && cd ~/portainer
nano docker-compose.yml
Ja odruchowo wpisałem tu sudo nano, ale w katalogu domowym sudo nie jest potrzebne, a tylko sprawia, że plik należy do roota. Wklejamy:
services:
portainer:
image: portainer/portainer-ce:lts
container_name: portainer
restart: unless-stopped
ports:
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/data
Co tu się dzieje:
portainer-ce:ltsto darmowa wersja Community Edition z gałęzi długoterminowej (LTS);restart: unless-stoppedoznacza, że kontener wstanie sam po restarcie serwera;9443to port panelu (HTTPS);docker.sockdaje Portainerowi kontrolę nad Dockerem, a więc nad całą maszyną. Dlatego hasło do Portainera musi być naprawdę mocne;./datato miejsce, w którym Portainer trzyma swoje ustawienia, żeby przetrwały aktualizację kontenera.
Zapisujemy (Ctrl+S), wychodzimy (Ctrl+X) i wrzucamy Portainera do gry:
docker compose up -d
docker ps
Pierwsze logowanie
W przeglądarce wchodzę na 192.168.0.200:9443 i widzę:
Spokojnie, trzeba tylko dopisać protokół: https://192.168.0.200:9443. Teraz przeglądarka ostrzeże, że połączenie nie jest prywatne. To dlatego, że Portainer używa certyfikatu samopodpisanego, którego nie wystawił żaden zaufany urząd. W naszej własnej sieci i na naszym własnym serwerze możemy kliknąć Zaawansowane → Przejdź do witryny. Na obcych stronach takiego ostrzeżenia nie ignorujemy.
Pokazuje się logo Portainera i ustawiamy hasło dla admina, minimum 12 znaków. Portainer prosi też o setup token, który znajdziemy w logach kontenera:
docker logs portainer
Token jest w ramce z =====, kopiujemy go i wklejamy. Przy okazji, na zrzucie poniżej widać, że najpierw wpisałem docker ps portainer, co oczywiście nie działa. Logi to docker logs.
I wpadka: za długo zwlekałem i dostałem timeout. Ze względów bezpieczeństwa świeżo postawiony Portainer czeka na utworzenie konta admina tylko 5 minut, żeby nikt w sieci nie zdążył go przejąć przed nami. Restartujemy kontener i powtarzamy kroki z nowym tokenem:
docker restart portainer
Po zalogowaniu kreator zapyta o środowisko. Klikamy Get Started, czyli lokalnego Dockera, na którym działa sam Portainer. Opcje Edge pomijamy: służą do zarządzania urządzeniami za NAT-em, a my mamy wszystko w jednej sieci LAN. Zawsze można to dokonfigurować później.
Krok 3: zwolnienie portu 53
Serwer DNS działa na porcie 53. W Ubuntu ten port zajmuje już systemd-resolved, czyli systemowy pośrednik DNS nasłuchujący na 127.0.0.53. Jeśli go nie wyłączymy, AdGuard nie będzie mógł zająć portu. Wpisujemy ten stos komend:
sudo mkdir -p /etc/systemd/resolved.conf.d
printf "[Resolve]\nDNS=127.0.0.1\nDNSStubListener=no\n" | sudo tee /etc/systemd/resolved.conf.d/adguard.conf
sudo mv /etc/resolv.conf /etc/resolv.conf.bak
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemctl restart systemd-resolved
sudo mkdir -p /opt/adguardhome/work /opt/adguardhome/conf
Po kolei:
- tworzymy katalog na dodatkową konfigurację
systemd-resolved; - w pliku
adguard.confwyłączamy nasłuch na porcie 53 (DNSStubListener=no) i mówimy systemowi, żeby sam też pytał AdGuarda (DNS=127.0.0.1); - robimy kopię starego
/etc/resolv.conf; - podmieniamy go na plik z prawdziwymi serwerami DNS zamiast nieistniejącego już pośrednika;
- restartujemy usługę, żeby zmiany weszły;
- tworzymy katalogi na dane i konfigurację AdGuarda.
Dla pewności sprawdzamy, czy na porcie 53 nic już nie nasłuchuje. Komenda nie powinna nic zwrócić:
sudo ss -tulpn | grep :53
Krok 4: AdGuard Home jako stack w Portainerze
W Portainerze wybieramy środowisko local, wchodzimy w Stacks i po prawej klikamy Add stack. Nazywamy go adguard, a w Web editor wklejamy:
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
network_mode: host
volumes:
- /opt/adguardhome/work:/opt/adguardhome/work
- /opt/adguardhome/conf:/opt/adguardhome/conf
network_mode: host oznacza, że kontener korzysta bezpośrednio z sieci serwera, bez przekierowywania portów. Dla serwera DNS to najprostsze rozwiązanie: AdGuard sam zajmuje port 53 i widzi prawdziwe adresy urządzeń, które o coś pytają, więc w statystykach wiemy, kto co odpytuje. Katalogi w volumes sprawiają, że konfiguracja i statystyki przetrwają aktualizację kontenera.
Mała uwaga: :latest oznacza zawsze najnowszą wersję. W domu jest to wygodne, ale na poważnym serwerze lepiej przypiąć konkretną wersję, żeby aktualizacja nie przyszła z zaskoczenia.
Klikamy Deploy the stack na samym dole. Stack ma status running, więc jest klasa światowa, ekstraliga.
Krok 5: konfiguracja AdGuarda
Żeby dostać się do AdGuarda, otwieramy w przeglądarce adres serwera z portem 3000, czyli u mnie http://192.168.0.200:3000. Wita nas kreator konfiguracji. Przeklikujemy go, ale w drugim kroku zatrzymajmy się na chwilę:
- Serwer DNS: wszystkie interfejsy, port 53. Tego nie zmieniamy;
- Interfejs administratora: tu wybieramy, na jakim porcie będzie panel po instalacji. Domyślnie kreator proponuje 80. Jeśli planujecie postawić na tym serwerze więcej usług z interfejsem webowym, lepiej zostawić port 80 wolny i dać panelowi inny port, na przykład 3000.
Potem ustawiamy login i hasło do panelu. Nawet jeśli AdGuard jest dostępny tylko w sieci lokalnej, nie chcemy, żeby ktokolwiek z domowników albo gości mógł w nim grzebać. Na koniec otwieramy panel dowodzenia. Na razie wszystkie statystyki są zerowe, bo nikt jeszcze z niego nie korzysta.
Krok 6: cały dom przez AdGuarda
Teraz najważniejsze: musimy sprawić, żeby wszystkie urządzenia pytały o DNS nasz serwer. Robimy to w routerze, bo to router przez DHCP rozdaje urządzeniom adresy i serwery DNS.
Ja mam TP-Linka Archer AX55, więc loguję się na 192.168.0.1 i wchodzę w Advanced → Network → DHCP Server. Tam ustawiam:
- Primary DNS:
192.168.0.200 - Secondary DNS:
192.168.0.200
U was panel routera może wyglądać inaczej, ale szukajcie ustawień DHCP i pól DNS.
Dlaczego dwa razy ten sam adres? Gdybym jako zapasowy wpisał publiczny DNS, np. 1.1.1.1, urządzenia czasem pytałyby właśnie jego i reklamy zaczęłyby przeciekać. Ceną jest to, że jeśli serwer padnie, cały dom straci internet, bo nic nie przetłumaczy nazw domen. U mnie host z Fedorą działa 24/7, więc to akceptuję, ale miejcie to z tyłu głowy, zanim wyłączycie komputer, na którym stoi AdGuard.
Potem trzeba zrestartować router (nie resetować, bo przycisk reset przywraca ustawienia fabryczne!) albo po prostu odłączyć i podłączyć urządzenia do sieci, żeby pobrały nowe ustawienia.
Szybki test na jednym komputerze
Jeśli nie chcecie jeszcze ruszać routera, możecie najpierw sprawdzić AdGuarda na jednym komputerze z Windowsem: Ustawienia → Sieć i Internet → Ethernet (albo Wi-Fi) → Przypisanie serwera DNS → Edytuj i wpisujecie adres serwera.
Krok 7: listy filtrów
Domyślna lista AdGuarda jest dobra na start, ale dorzućmy polskie. W panelu wchodzimy w Filtry → Listy zablokowanych DNS → Dodaj listę zablokowanych → Wybierz z listy i w sekcji regionalnej zaznaczamy:
- POL: CERT Polska List of malicious domains: lista domen phishingowych i złośliwych prowadzona przez CERT Polska. To ona chroni bliskich przed fałszywymi stronami banków, kurierów i „dopłatami do paczki”;
- POL: Polish filters for Pi-hole: polskie domeny reklamowe i śledzące.
Resztę dobierzcie według uznania. Każda lista to więcej blokowania, ale też większa szansa, że coś potrzebnego przestanie działać. Wtedy w Dzienniku zapytań łatwo znaleźć winną domenę i dodać ją do wyjątków.
Efekt
Wchodzę na mocno zareklamowaną stronę, np. Onet, i nie ma reklam. Po kilku minutach statystyki wyglądały tak:
- 237 zapytań DNS, z czego 17 (7%) zablokowanych, choć korzystał z niego praktycznie jeden komputer;
- wśród zablokowanych domen są m.in.
onet.hit.gemius.pl(statystyki i śledzenie),events.ocdn.euicsr.onet.pl; - średni czas odpowiedzi wyniósł 15 ms, więc nikt nie odczuje spowolnienia.
A to jedno urządzenie i kilka minut. Przy całym domu i całym dniu robi się z tego naprawdę dużo.
Co dalej
Pobawcie się. List jest mnóstwo, a dziennik zapytań świetnie pokazuje, co wasze urządzenia robią w tle. Czasem można się zdziwić, gdzie dzwoni telewizor.
Ja mam do tego jeszcze VPN na Tailscale: niezależnie od tego, gdzie jestem, telefon łączy się z moją siecią domową i zapytania DNS idą do mojego AdGuarda, więc reklamy są wycinane nawet poza domem. Jak to ustawić, żeby być chronionym 24/7, pokażę w następnym wpisie. Na liście czekają jeszcze klucze SSH zamiast haseł i liczenie podsieci.
Pamiętajcie: jeśli możecie, chrońcie swoich bliskich. Nie każdy ma czas i ochotę siedzieć w komputerach, każdy ma inne zainteresowania. Ale każdy zasługuje na to, żeby nie wpaść na fałszywą stronę banku.