使用 Envoy 和 AdGuard Home 阻擋煩人的廣告

  • 2019 年 10 月 3 日
  • 筆記

原文鏈接:使用 Envoy 和 AdGuard Home 阻擋煩人的廣告

通常我們使用網絡時,寬帶運營商會為我們分配一個 DNS 服務器。這個 DNS 通常是最快的,距離最近的服務器,但會有很多問題,比如:

  1. 訪問某些網絡服務很緩慢,比如 Apple 的 iCloud 服務。
  2. 比較擔心安全問題,希望能通過設置 DNS 來保證你訪問安全的網站。
  3. 厭煩了每當你輸入一個不正確的網址,運營商總會給你跳轉到一個充滿廣告的界面。

這個時候我們就需要自定義 DNS,自定義 DNS 不僅能夠加快網頁開啟的速度,還能夠提高瀏覽網頁的安全性。更重要的一點是,如果你使用過 Google Chrome,應該知道 Google 未來將會限制「攔截廣告」的擴展,要想解決此問題只能裝個全局的攔截廣告軟件或者直接從 DNS 服務器層面攔截廣告(如果你不想換瀏覽器)。

AdGuard Home 是一款全網廣告攔截與反跟蹤軟件,可以將廣告與追蹤相關的域名屏蔽,指向空的主機(DNS 黑洞)。簡單來說它就是一個開源的公共 DNS 服務,使用 Go 語言開發,支持家長控制和廣告過濾!關鍵是它還支持 DNS over TLSDNS over HTTPS,可以運行在 x86 Linux,樹莓派上,也可以通過 Docker 部署在群暉 NAS 上。

1. AdGuard Home 安裝

AdGuard Home 的安裝方法根據你所使用的平台而有所不同,它的二進制文件位於 https://github.com/AdguardTeam/AdGuardHome/releases,可以根據自己的平台下載最新版本。MacOS 的安裝方法如下:

# 下載 AdGuard Home  $ wget https://github.com/AdguardTeam/AdGuardHome/releases/download/v0.98.1/AdGuardHome_MacOS.zip    # 解壓並進入 AdGuardHome_MacOS 目錄  $ unzip AdGuardHome_MacOS.zip && cd AdGuardHome_MacOS    # 將二進制文件拷貝到 $PATH  $ cp ./AdGuardHome /usr/local/bin/    # 創建 Launch Daemon 的 plist 文件並啟動服務  $ AdGuardHome -s install

現在就可以看到服務的配置和狀態信息了:

$ sudo launchctl list AdGuardHome    {      "StandardOutPath" = "/var/log/AdGuardHome.stdout.log";      "LimitLoadToSessionType" = "System";      "StandardErrorPath" = "/var/log/AdGuardHome.stderr.log";      "Label" = "AdGuardHome";      "TimeOut" = 30;      "OnDemand" = false;      "LastExitStatus" = 0;      "PID" = 1464;      "Program" = "/usr/local/bin/AdGuardHome";      "ProgramArguments" = (          "/usr/local/bin/AdGuardHome";          "-s";          "run";      );  };

plist 文件位於 /Library/LaunchDaemons/ 目錄下:

$ cat /Library/LaunchDaemons/AdGuardHome.plist    <?xml version='1.0' encoding='UTF-8'?>  <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"  "http://www.apple.com/DTDs/PropertyList-1.0.dtd" >  <plist version='1.0'>  <dict>  <key>Label</key><string>AdGuardHome</string>  <key>ProgramArguments</key>  <array>          <string>/usr/local/bin/AdGuardHome</string>            <string>-s</string>            <string>run</string>    </array>      <key>WorkingDirectory</key><string>/Users/freya/Downloads/Compressed/AdGuardHome_MacOS</string>  <key>SessionCreate</key><false/>  <key>KeepAlive</key><true/>  <key>RunAtLoad</key><true/>  <key>Disabled</key><false/>  <key>StandardOutPath</key>  <string>/var/log/AdGuardHome.stdout.log</string>  <key>StandardErrorPath</key>  <string>/var/log/AdGuardHome.stderr.log</string>  </dict>  </plist>

對 Launch Daemon 不熟悉的同學可以參考 Mac OS X 的 Launch Daemon / Agent

查看端口號:

$ sudo lsof -iTCP -sTCP:LISTEN -P -n|grep AdGuard  AdGuardHo 9990  root    3u  IPv6 0xb76d091ec878f951      0t0  TCP *:3000 (LISTEN)

打開瀏覽器,輸入網址 http://127.0.0.1:3000/ 即可訪問 AdGuard Home 的管理界面。

點擊「開始配置」,然後設定網頁管理界面和 DNS 服務的端口。

點擊「下一步」設置用戶名和密碼。

最後點擊「下一步」就大功告成了。

在儀錶盤上,我們可以看到 DNS 查詢次數、被過濾器攔截的網站、查詢 DNS 請求的客戶端地址等等信息。

現在再查看端口號,管理界面會變成你剛剛設定的端口,另外還會多出一個 DNS 服務的端口:

$ sudo lsof -iTCP -sTCP:LISTEN -P -n|grep AdGuard  AdGuardHo 10619  root   11u  IPv6 0xb76d091eb6671751      0t0  TCP *:53 (LISTEN)  AdGuardHo 10619  root   12u  IPv6 0xb76d091ebc3c7751      0t0  TCP *:5300 (LISTEN)    $ sudo lsof -iUDP -P -n|grep AdGuard  AdGuardHo 10619           root   10u  IPv6 0xb76d091eb89601c1      0t0  UDP *:53

2. 配置優化

默認的配置比較簡單,為了更強力地攔截廣告,我們可以對配置進行優化。

常規設置

勾選【使用過濾器和 Hosts 文件以攔截指定域名】、【使用 AdGuard 瀏覽安全網頁服務】、【強制安全搜索】。如果你想攔截成人網站,也可以勾選【使用 AdGuard 家長控制服務】。

過濾器

雖然 AdGuard 本身提供了 AdGuardAdAway 的廣告過濾規則,但在中國有點水土不服,如果要想更完美的實現廣告屏蔽還需要自己添加規則,AdGuard 可以兼容 Adblock 的語法。最知名的過濾規則 EasyList 就是由 Adblock Plus 團隊維護,過濾規則往往是一個 txt 文件,在文件的開頭部分會顯示規則的最後更新日期。

推薦廣告過濾規則:

優酷網如果播放無限加載,那在自定義靜態規則里加入一條規則 @@mp4.ts (參考下圖)。

上游 DNS 設置

官方默認使用 Cloudflare 的 DNS over HTTPS 作為上游服務器,在國內可能請求上游 DNS 延遲比較高,可以加上或替換國內的 DNS。我自己另外加了中科大的兩組無污染 DNS,每次查詢的時候會對所有的上游 DNS 同時查詢,加速解析。

查詢日誌

在這個界面里可以看見所有設備的 DNS 查詢日誌,可以下載整個日誌文件,也可以針對某個域名進行快速攔截和放行。

提升 QPS

有兩個參數可以明顯提升 QPS:

  • ratelimit : DDoS 保護,客戶端每秒接收的數據包數。建議禁用該參數(將值改為 0),默認值是 20。
  • blocked_response_ttl : TTL 緩存時間,建議設置為 60

配置文件默認路徑是 /usr/local/bin/AdGuardHome.yaml

3. 使用 Envoy 作為前端代理

其實到這裡已經算是結束了,但本人有強迫症,我可不想將應用的管理界面設置為一些奇奇怪怪的非標準端口。有人或許會說:那你為什麼不將管理界面設置為 80 或 443 端口啊?問得好,因為我的電腦上部署了各種奇奇怪怪的應用,80 端口只有一個,不夠用的,只能考慮加個前端代理了。

作為一名雲原生狂熱信徒,當然是選 Envoy 了,雖然 Envoy 很難編譯,但 Tetrate 的工程師(包括 Envoy 的核心貢獻者和維護者)發起了一個 GetEnvoy 項目,目標是利用一套經過驗證的構建工具來構建 Envoy,並通過常用的軟件包管理器來分發,其中就包括 Homebrew。我們可以直接通過 Homebrew 來安裝:

$ brew tap tetratelabs/getenvoy  ==> Tapping tetratelabs/getenvoy  Cloning into '/usr/local/Homebrew/Library/Taps/tetratelabs/homebrew-getenvoy'...  Tapped 1 formula.    $ brew install envoy  ==> Installing envoy from tetratelabs/getenvoy  ==> Downloading ...  ######################################################################## 100.0%  ?  /usr/local/Cellar/envoy/1.10.0: 3 files, 27.9MB, built in 13 seconds    $ envoy --version  envoy  version: e349fb6139e4b7a59a9a359be0ea45dd61e589c5/1.11.1/clean-getenvoy-930d4a5/RELEASE/BoringSSL

這是我的 envoy 配置文件:

static_resources:    listeners:    - address:        # Tells Envoy to listen on 0.0.0.0:80        socket_address:          address: 0.0.0.0          port_value: 80      filter_chains:      # Any requests received on this address are sent through this chain of filters      - filters:        # If the request is HTTP it will pass through this HTTP filter        - name: envoy.http_connection_manager          typed_config:            "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager            codec_type: auto            stat_prefix: http            access_log:              name: envoy.file_access_log              typed_config:                "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog                path: /dev/stdout            route_config:              name: search_route              virtual_hosts:              - name: backend                domains:                - "*"                routes:                - match:                    prefix: "/"                  route:                    cluster: adguard            http_filters:            - name: envoy.router              typed_config: {}    clusters:    - name: adguard      connect_timeout: 1s      type: strict_dns      dns_lookup_family: V4_ONLY      lb_policy: round_robin      load_assignment:        cluster_name: adguard        endpoints:        - lb_endpoints:          - endpoint:              address:                socket_address:                  address: 127.0.0.1                  port_value: 5300  admin:    access_log_path: "/dev/stdout"    address:      socket_address:        address: 0.0.0.0        port_value: 15001

創建 Launch Agent 的 plist 文件:

$ cat /Library/LaunchAgents/envoy.plist    <?xml version="1.0" encoding="UTF-8"?>  <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  <plist version="1.0">    <dict>      <key>Label</key>      <string>envoy</string>      <key>ProgramArguments</key>      <array>        <string>/usr/local/bin/envoy</string>        <string>--config-path</string>        <string>/Users/freya/bin/front-proxy.yaml</string>      </array>      <key>StandardOutPath</key>      <string>/var/log/envoy.stdout.log</string>      <key>StandardErrorPath</key>      <string>/var/log/envoy.stderr.log</string>      <key>KeepAlive</key>      <true/>      <key>RunAtLoad</key>      <true/>      <key>Disabled</key>      <false/>    </dict>  </plist>

加載 envoy 服務:

$ sudo launchctl load /Library/LaunchAgents/envoy.plist

現在就可以在瀏覽器中通過 url http://127.0.0.1/ 來訪問 AdGuard Home 的管理界面啦~

後續如果還有其他不可描述的應用,它們的管理界面都可以根據不同的 url 路徑加到 envoy 的後端中。更高級的玩法還可以接入 Prometheus 監控,envoy 的 metrics 路徑是 /stats/prometheus

如果你很好奇為什麼我的瀏覽器能夠輸出彩色的 metrics,請在公眾號後台回復◉prometheus◉

最後,別忘了將 MacOS 的 DNS 設為 127.0.0.1,這個就不用我教了吧?

微信公眾號

掃一掃下面的二維碼關注微信公眾號,在公眾號中回復◉加群◉即可加入我們的雲原生交流群,和孫宏亮、張館長、陽明等大佬一起探討雲原生技術