2022.12.12 更新
Unifi Network Application 新增了 Traffic Management 功能,可以針對特定裝置進行時段封鎖,設定相當簡單易懂,已無須再透過下列方法來達成網路裝置時段控制。網路上相當多教學文章或影片,這裡就不再特別介紹。
在上一篇文章 「用 UniFi Controller 實現小孩的網路使用時段控制」提到可以透過在 UniFi Controller 上設定 config.gateway.json 檔案來控制 UniFi USG 動態用對應的防火牆規則以及對應的 IP 群組控制,藉以達到控制小孩裝置的使用時段限制。
上篇文章使用的是 USG,由於 USG 可以透過承襲自 EdgeOS的參數配置方式,自訂一組 config.gateway.json 進行控制,但 UDM-Pro / UDM-SE 採用的是較新的 UniFiOS,所以無法通用 config.gateway.json 的配置。雖然從 UDM-Pro/UDM-SE 管理介面可以控管透過 WiFi 連線設備的使用時段,不過卻無法控管透過實體有線進行連線設備,所以在 Ubiquiti 還沒釋出新的管理介面前還是得想想其他方法。
UniFiOS 具備更先進對外開放的 REST-API 介面,提供給外部應用程式進行整合。所以國外就有神人寫了用 PHP 來整合 UniFi Network Controller API 的函式庫(Art-of-WiFi),其中 UniFi-API-client 提供了一系列函式,讓 PHP 開發者可以遠端呼叫取得或操作 UniFiOS 裝置。而 UniFi-API-browser 則是另一套 PHP Web 應用程式,可以透過瀏覽器直接取得 UniFiOS 裝置的相關資訊,可以用來觀察或協助開發應用程式時進行除蟲。
這套開源函式庫發表後,接著就有另一位神人,應用了 UniFi-API-client 函式庫,寫了兩支 PHP 程式來對 UniFiOS 的防火牆 IP 群組操作加入/移除,再搭配 Linux 內建的排程工具 crontab 定時啟動來達成時間的控制,最後用 Dockerfile 包裝為 docker 映像檔 (blockips-unifi) 方便我們可以快速佈署,不用自己花大把時間來自己進行整合到作業系統中。
好了,說了這麼多,今天這篇筆記是參考Ubiquiti官方論壇 Time based blocking of IP addresses on the UDM/pro 的這篇文章進行實驗,過程中記錄怎麼在 UDM-Pro / UDM-SE 上一步一步做到小孩的裝置使用時段的控制。
注意:以下操作步驟須具備 Linux crontab 排程及 Docker 容器等相關知識,我無法在這篇文章中鉅細彌遺進行說明,如有說明不足請見諒,網路上自行做功課研究。
UDM-Pro/UDM-SE 新增預計要管控裝置的區網 IP 群組
類似於在上一篇文章 「用 UniFi Controller 實現小孩的網路使用時段控制」提到的,我們也需要建立兩個 IP 群組,一個用於記錄所有小孩使用裝置的 IP (後續要用 blockips-unifi docker 映像檔 來動態新增/移除 IP),另一個則一樣是臨時有需要取消限制時,可以手動將防火牆規則改為套用在這個未設定任何 IP 的群組,藉以取消所有的限制。詳細步驟請參與上一篇文章,不過兩個群組皆無需設定任何 IP,都空著就行,因為 IP 後續會透過 docker 映像檔 (blockips-unifi) 來依據時段動態加入。
直接看圖如何設定。新增群組後,不設定任何 IP。
設定防火牆規則
同樣可以參考上一篇文章「用 UniFi Controller 實現小孩的網路使用時段控制」的步驟來建立防火牆規則,唯一不同的是不需要依照時段建立不同的防火牆規則,只需要在 WAN-OUT 設定單獨一條規則即可,這是因為在前一步驟建立的規則套用的 IP 群組,群組裡面的 IP 清單雖然是空的,但 IP 清單會透過 docker 映像檔 呼叫 UniFiOS 的 REST-API 在需要限制的時段被自動加入,在網路開放的時段又自動從清單中被移除,所以去控制時段即可,這邊不用區分不同的規則。
設定方法一樣請參考上一篇文章,這邊就不再多加贅述,直接看圖照著設定。
規則設定細節
Docker 映像檔安裝與設定
其實這篇筆記的重點現在才開始,這篇文章將以群暉 DSM Docker 套件的形式來介紹如何安裝 blockips-unifi,如果要自行在習慣的作業系統中安裝 docker 就請自行研究。
大致說明一下安裝的步驟
- 從 github 下載 blockips-unifi 專案
下載後在任意目錄(我放在 DSM 共用目錄 docker/blockips-unifi)解開zip後只需要保留 crontab / config.php 這兩個檔案,其他均可以刪除。
- 從 github 下載最新版本的 UniFi-API-client 專案
為何需要更新最新版本的 UniFi-API-client ?
由於 blockips-unifi 目前下載回來 docker 映像檔內嵌的 UniFi-API-client 版本過舊,用內嵌的舊版本搭配我的 UDM-SE + Network Controller v7.1.66 實測結果無法正確進行連線,查看 php 的執行紀錄發現錯誤都是無法登入 UDM-SE,所以需要嘗試將內嵌的 UniFi-API-client 版本更新看看。
一種方法是用 Dockerfile 重新包裝映像檔,把最新的函式庫包進映像檔。但測試的當下我無法確定更新版本是否就可以正常與 UDM-SE 連線,所以我改採比較簡單的方式,由 docker 外部目錄對映的方式將映像檔內部的目錄進行置換,如此就不要再花額外時間重新包裝映像檔。
從 github 下載後在任意目錄(我放在 DSM 共用目錄 docker/blockips-unifi/unifi-api-client)下解開
我更新到目前的最新版本(v1.1.79)後,重新測試連線就一切正常了。
- 安裝 docker 執行神人包裝好的 blockips-unifi 映像檔
在「倉庫伺服器」中搜尋 blockips,應該只會出現一個映像檔,直接按下「下載」即可。
下載下來的映像檔會出現在「映像檔」中
- 佈署 blockips-unifi 映像檔
點選 blockips-unifi 映像檔然後選擇「佈署」,網路選擇預設的 bridge 即可
容器名稱可自訂,另外請點選「進階設定」
新增時區 TZ 環境變數為 Asia/Taipei,設定正確的時區,後面的時間排程才能正確按時執行。設定好後儲存離開。
下一步,連接埠設定可直接跳過,此 docker 映像檔並無需要對映對外監聽埠。
儲存空間一共需要設定四組,兩組檔案,兩組資料夾
兩個檔案 crontab/config.php 請對應至步驟1 github 中 blockips-unifi 解開的檔案
資料夾 unifi-api-client 請對應至步驟2 github 中UniFi-API-client 解開的資料夾
檔案 crontab,docker 中的掛載路徑請設定為 /etc/crontabs/root
檔案 config.php,docker 中的掛載路徑請設定為 /config.php,可以設定為唯讀
資料夾 unifi-api-client,docker 中的掛載路徑請設定為 /vendor/art-of-wifi/unifi-api-client,可以設定為唯讀
新增一個資料夾 log,用來記錄 crontab 排程執行輸出結果,docker 中的掛載路徑請設定為 /var/log,請勿設定為唯讀
- 設定好 config.php 中的對應參數
直接編輯 DSM 資料夾中的 config.php,將 UDM-Pro/UDM-SE 相關參數設定進去,docker 映像檔啟動時由於 config.php 已在前一步驟被置換為外部檔案,所以就會使用我們所配置的參數進行啟動。
$controlleruser,請設定為具有administrator權限的帳號。
$controllerpassword,沒什麼好解釋的,就是密碼。
$controllerurl,請設定為 UDM-Pro/UDM-SE 的網址,例如 https://192.168.60.1。
$controllerversion,設定 UniFi Network Controller 的版本號碼。截至本文撰寫時的最新版本 7.1.66 都可以正常支援。
$site_id,站台代號,可以參考上篇文章「用 UniFi Controller 實現小孩的網路使用時段控制」中的「在 UniFi Controller 主機上設定參數檔」章節說明,預設站台代號是 default。
$group_name,最前面在 UDM-Pro/UDM-SE 防火牆中新增的 IP 群組名稱,在本例中是「小孩的裝置」。
$rule_name,最前面在 UDM-Pro/UDM-SE 防火牆中新增的防火牆規則名稱,在本例中是「小孩裝置停止使用控制」。
$debug,設定為 true 可以輸出更多除錯訊息,後續運作正常後可以修改為 false 來減少 log 輸出檔案大小。
- 調整 crontab 裡的排程時間
直接編輯 DSM 資料夾中的 Linux crontab 排程設定檔(docker 映像檔內的 crontab 也已在前一步驟被置換為外部檔案)。
Linux 的 crontab 的設定語法也不在此篇文章的涵蓋範圍,請自行研究,網路上可以找到很多文章。
我想控制週日~週四每天的 21:00~7:00 之間把六組 IP 限制連線,但週日~週四 7:00~21:00 就打開允許連線。
但週五週六兩天則延長到23:00才開始限制連線,直到隔天早上 7:00 再度打開允許連線
以下貼出我自己的設定
# 週日到週四的 21:00~06:59,每分鐘執行一次把所有小孩使用裝置的 IP 遠端設定到 UDM-Pro/USM-SE # 重複執行沒關係,add_block_firewall.php 會偵測如果 IP 已經在 IP 群組中,則忽略不再執行 * 21-6 * * 0-4 /usr/bin/php /add_block_firewall.php 192.168.60.90 192.168.60.91 192.168.60.92 192.168.60.93 192.168.60.94 192.168.60.95 1>> /var/log/blockfile.txt 2>> /var/log/blockfile.txt # 週五到週六的 23:00~06:59,每分鐘執行一次把所有小孩使用裝置的 IP 遠端設定到 UDM-Pro/USM-SE * 23-6 * * 5-6 /usr/bin/php /add_block_firewall.php 192.168.60.90 192.168.60.91 192.168.60.92 192.168.60.93 192.168.60.94 192.168.60.95 1>> /var/log/blockfile.txt 2>> /var/log/blockfile.txt # 週日到週四的 07:00~20:59,每分鐘執行一次把所有小孩使用裝置的 IP 從 UDM-Pro/USM-SE 中刪除 * 7-20 * * 0-4 /usr/bin/php /del_block_firewall.php 192.168.60.90 192.168.60.91 192.168.60.92 192.168.60.93 192.168.60.94 192.168.60.95 1>> /var/log/blockfile.txt 2>> /var/log/blockfile.txt # 週五到週六的 07:00~22:59,每分鐘執行一次把所有小孩使用裝置的 IP 從 UDM-Pro/USM-SE 中刪除 * 7-22 * * 5-6 /usr/bin/php /del_block_firewall.php 192.168.60.90 192.168.60.91 192.168.60.92 192.168.60.93 192.168.60.94 192.168.60.95 1>> /var/log/blockfile.txt 2>> /var/log/blockfile.txt
啟動 Docker 映像檔
可以從兩個地方來確認是否正常
- Docker blockips-unifi 的日誌中可以確認是否 crontab 是否有依照配置時段來啟動。
從下面日誌可以看到21:00之後每分鐘都啟動執行 /add_block_firewall.php
- 從 UDM-Pro / UDM-SE 的防火牆群組中是否可以看到在 crontab 中設定的小孩裝置IP
接著從 UDM-Pro/UDM-SE Network 管理介面中可以確認六組 IP 已正確被加入「小孩的裝置」IP群組中。
最後從小孩使用的這六組裝置確認無法連線即可。