AdGuard Home은 DNS 단계에서 광고와 트래킹 도메인을 걸러내, 브라우저 확장 프로그램 없이도 광고를 차단해주는 셀프호스팅 앱입니다. 앞선 편들에서 만든 서버 위에 컨테이너 하나만 올리면 되지만, 실제로는 53번과 80번 포트 충돌이라는 두 관문을 넘어야 합니다. 이 글에서는 제가 직접 설치하며 겪은 충돌 해결과, 설치 후 실제로 광고가 차단되는 것을 확인한 과정을 정리합니다.
이 글은 8편(SSL 인증서)에서 이어지는 4부(앱 활용)의 첫 편입니다. Docker와 Portainer 환경은 4~5편을 참고하세요.
설치 전 필수 — 53번 포트 충돌 해결
AdGuard Home은 DNS 서버이므로 53번 포트를 써야 하는데, 우분투에서는 systemd-resolved라는 서비스가 이미 이 포트를 점유하고 있습니다. 이 상태로 설치하면 컨테이너가 뜨지 않으므로, 먼저 53번을 비워줘야 합니다. 현재 상태는 아래 명령으로 확인할 수 있습니다.
sudo ss -tulpn | grep :53
systemd-resolve가 53번을 잡고 있다면 설정 파일을 수정합니다. sudo nano /etc/systemd/resolved.conf로 파일을 열고, 주석 처리된 #DNSStubListener=yes 줄을 찾아 DNSStubListener=no로 바꿉니다. 저장 후 sudo systemctl restart systemd-resolved로 적용하고 다시 확인하면, 53번이 비었거나 127.0.0.53만 남아 있을 것입니다. 이제 컨테이너를 올릴 준비가 됐습니다. 작업 폴더를 만들고 docker-compose.yml을 작성합니다.
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
network_mode: host
volumes:
- ./work:/opt/adguardhome/work
- ./conf:/opt/adguardhome/conf
network_mode: host를 쓰는 이유는 DNS 서버가 요청을 보낸 클라이언트의 실제 IP를 확인하려면 호스트 네트워크를 직접 써야 하기 때문입니다. 파일을 저장하고 docker compose up -d를 실행하면 설치가 끝납니다.
80번 포트 충돌 — 리버스 프록시를 이미 쓴다면
설치 후 http://내서버IP:3000으로 접속하면 초기 설정 마법사가 뜹니다. 그런데 여기서 저는 두 번째 벽을 만났습니다. '관리자 웹 인터페이스' 설정 화면에서 포트가 기본값 80으로 잡혀 있었는데, 저장을 시도하니 validating ports: listen tcp 0.0.0.0:80: bind: address already in use라는 빨간 에러가 떴습니다.
원인은 명확합니다. 7편에서 설치한 리버스 프록시(Nginx Proxy Manager)가 이미 80번 포트를 쓰고 있기 때문입니다. 해결은 간단합니다. 관리자 웹 인터페이스 포트를 80에서 3000으로 바꾸면 됩니다. 이어지는 DNS 서버 설정 화면에서는 포트를 53번 그대로 두면 되는데, 앞서 systemd-resolved를 정리해뒀으므로 충돌 없이 넘어갑니다. 관리자 계정을 만들면 대시보드로 진입합니다. 이 계정 정보는 반드시 메모해두세요. 정리하면 리버스 프록시를 먼저 구축한 환경에서는 AdGuard의 웹 UI 포트를 3000번으로 유지하는 것이 필수입니다.


실제로 광고를 차단시키기 — DNS를 AdGuard로 지정
대시보드가 떴다고 광고가 바로 차단되는 것은 아닙니다. AdGuard는 DNS 서버이므로, 우리 기기가 AdGuard에게 주소를 물어보도록 DNS 설정을 바꿔야 비로소 작동합니다. 이 단계를 몰라 "설치했는데 광고가 그대로"라고 하는 경우가 많습니다.
가장 강력한 방법은 공유기의 DNS를 서버 IP로 바꿔 집 전체에 적용하는 것이지만, 저는 이 방법을 권하지 않습니다. 실제로 제 KT 공유기(GiGA WiFi home)를 확인해보니 '인터넷 연결설정'의 DNS 항목은 공유기가 외부로 나갈 때 쓰는 값이라 우리가 원하는 설정이 아니었고, 내부 기기에 나눠줄 DNS를 지정하는 옵션은 사실상 막혀 있었습니다. 더 중요한 이유는 안전성입니다. 우리 AdGuard는 가상머신 안에서 돌고 있어서, PC나 VM을 끄면 집 안 모든 기기가 DNS를 찾지 못해 인터넷이 통째로 끊깁니다.
그래서 처음에는 PC 한 대만 바꿔 테스트하는 것이 안전합니다. 윈도우에서 네트워크 어댑터 속성 → 인터넷 프로토콜 버전 4(TCP/IPv4) → '다음 DNS 서버 주소 사용'을 선택하고 기본 DNS에 서버 IP(제 경우 172.30.1.51)를 넣으면 됩니다.

설정 후 웹서핑을 잠시 하고 대시보드를 새로고침하니 숫자가 실제로 올라갔습니다. DNS 쿼리 99건 중 16건(16%)이 필터에 의해 차단됐고, 클라이언트 목록에는 DNS를 바꾼 PC의 IP만 잡혔습니다.
차단된 도메인 목록에는 googleads.g.doubleclick.net, static.doubleclick.net, tpc.googlesyndication.com 같은 광고 서버와 트래킹 도메인이 그대로 드러났습니다. 즉 100번의 요청 중 16번이 광고·트래킹이었다는 뜻입니다.

쿼리 로그로 진단하기, 그리고 예외 설정의 한계
AdGuard가 실제로 무엇을 막고 무엇을 통과시키는지는 '쿼리 로그' 메뉴에서 실시간으로 확인할 수 있습니다. 대시보드 통계보다 이쪽이 훨씬 정확한데, 24시간 누적이 아니라 지금 이 순간의 요청을 보여주기 때문입니다.
제 로그를 보니 mail-ads.google.com(Gmail 광고)과 분석 툴 도메인은 '차단됨'으로 빨갛게 표시된 반면, claude.ai나 fonts.googleapis.com 같은 정상 서비스는 '처리됨'으로 통과했습니다.
광고만 골라 막고 서비스는 살린다는 것이 눈으로 확인되는 화면입니다.

여기서 한국 사용자가 알아야 할 현실이 하나 있습니다. 제가 네이버 계열 사이트를 방문했을 때 siape.veta.naver.com처럼 네이버의 광고·트래킹 성격 도메인이 '처리됨'으로 통과했습니다. AdGuard의 기본 필터는 해외 광고 도메인에는 강하지만 한국 광고 도메인은 상대적으로 덜 잡는다는 뜻입니다. 차단율을 높이려면 필터 메뉴에서 한국어 차단 목록을 추가로 켜주는 것이 좋습니다.
반대로 특정 광고는 일부러 살리고 싶을 수도 있습니다. 블로그를 운영하는 입장에서 광고 수익이 창작자에게 중요하다는 걸 알기에, 저는 구글 애드센스를 허용하는 규칙을 넣어봤습니다. 필터 → 커스텀 필터링 규칙에 아래처럼 입력하고 '적용'을 누르면 됩니다.
@@||googlesyndication.com^$important
@@||doubleclick.net^$important
@@는 허용 규칙, ||도메인^은 도메인 매칭, $important는 다른 차단 규칙보다 우선 적용을 뜻합니다. 다만 여기에는 구조적 한계가 있습니다. DNS 차단은 '어느 사이트에서 요청했는지'가 아니라 '어느 도메인으로 요청하는지'만 보기 때문에, 내 블로그의 광고만 살리고 다른 사이트의 광고는 막는 식의 사이트별 예외는 불가능합니다. 위 규칙을 넣으면 모든 사이트의 애드센스 광고가 함께 보이게 됩니다. 사이트 단위로 세밀하게 제어하고 싶다면 브라우저 확장 프로그램 방식의 차단기를 함께 써야 합니다. 참고로 규칙을 입력한 뒤에는 반드시 '적용' 버튼을 눌러야 하고, 곧바로 반영되지 않으면 ipconfig /flushdns로 DNS 캐시를 비우면 됩니다.
이제 집 안 기기의 광고를 걷어내는 첫 실전 앱이 완성됐습니다. 다음 편에서는 구글 포토 없이 아이 사진을 무제한으로 백업하는 사진 서버를 직접 구축해봅니다. → 10편. Immich로 구글 포토 없이 아이 사진 무제한 백업