使用 LibreNMS 實現 HTTP Health check 健康度檢查,網站監控

監控,是一個很老牙卻也很樸實的問題。網站的健康度已成為維持業務連續性的必要條件。
本文將探討如何使用 LibreNMS 這一強大的網路監控工具來實現網站HTTP 的 Health check 健康度檢查。LibreNMS 不僅在 SNMP 提供豐富的功能,還支援廣泛的設備,但在 HTTP 健康度卻比較少著墨,故整理一個較完整的筆記分享給大家。

背後的實現原理

先說結論,LibreNMS 是使用 Nagios plugins 來實現健康度監控的。
Nagios plugins 是一個很老牌的開源監控服務的程式, 2002 年首次發佈,GPLv2 授權釋出,
它提供了很多的監控服務,例如 HTTP, FTP, SSH, SMTP, POP3, SNMP, DNS, Disk, CPU, Memory…等等,而
LibreNMS 就是使用這些服務來實現健康度監控的。
所以你要先了解 Nagios plugins 的使用方法,才能在 LibreNMS 上面設定,
很剛好的,我們拉取的 jarischaefer/docker-librenms docker image 直接把 Nagios plugins 給包進去了,
我們可以直接拿它來做健康度監控。

我們就舉一些例子來看看怎麼實現 Health check 吧!

建立健康度監控的操作步驟

Step1. 先建立 Device

LibreNMS 的健康度測試是一個一個 Services 要掛在 Device 上面
所以我們要先建立 Device

Devices > Add Devices

  • Hostname or IP: 打入一個監控的網址或 IP
  • SNMP: OFF

如果 SNMP 設定是 OFF,會改用 ping 來做測試
如果 SNMP 設定 ON,需要提供 SNMP Version, Community 等資訊

SNMP (Simple Network Management Protocol) 可以視你的情況打開,它會依照協定規範發送 CPU, RAM…等資訊,這部分就不細講了

如果你只需要一個 Device,然後把所有 HTTP 健康度測試,你甚至 IP 用 localhost 都可以。

再建立 Service

這邊就是 Nagios plugins 的重頭戲

Services > Add Services

  • Name: 取一個名字
  • Device: 選擇剛剛加入的裝置
  • Check Type: http
  • Description: (可留空)
  • Remote Host: 打入要檢測的網址
  • Parameters: 參數說明,後詳

這邊我覺得就是 LibreNMS 設計不好的地方,出現了一個謎樣的 Parameters 欄位
這個參數格式還要參照另外一個文件知道怎麼使用,很不直覺
(有看到一個討論串,其中之一的作者說要重寫這個部分,可以參與實作

我把文件先放上來
https://nagios-plugins.org/doc/man/check_http.html

列一些比較常用或重要的參數:

  • -p 8080 :設定 連接埠 (port) 號,例如 8080
  • -S :使用 SSL 加密協定 (https) ,若只是 http 不用加此參數
  • --sni:使用 Server Name Indication (SNI) 伺服器名稱指示
    開啟後它才可以正確辨別第二階層的 DNS 位址,例如主域名是 example.com 底下有二個子域名 blogmyhome
    沒有開啟 sni 的時候,blog.example.commyhome.example.com 都會被視為一個 example.com
    而造成不如預期的結果,如果第二層域名,要打開這個選項,個人建議不管有沒有第二層域名,直接打開該選項
  • -u /example/path :如果你有參數需要寫這裡
  • -s "testString" :設定 Response 的關鍵字檢測,有出現該關鍵字才算正確,例如有出現 testString 關鍵字才算正確
  • -f follow :跟隨轉址 (Follow redirect),假設有一個首頁直接呼叫它,會回應 302 Redirect,它會繼續轉址直到停止控制時才會做前者的關鍵字檢測
  • -e 403 :原始 HTTP 封包的關鍵字檢測,例如有個 Endpoint 永遠不會回 200 OK,
    而是回應 403 forbidden,你就可以加 -e 403 設定檢測規則
  • -v:使用 verbose 模式,可以看到更多的訊息,可以看到原始的 HTTP 封包

手動測試步驟

剛剛有提過, LibreNMS 是透過 Nagios plugins 來實現 HTTP 健康度監控的
它安裝在 container 裡面的 /usr/lib/nagios/plugins (可能會依版本不同而路徑不同)
如果你要手動測試,你可以參照以下步驟

  1. 用 docker ps 或者 docker-compose ps 找到你該容器 ID
# docker ps
% docker ps
CONTAINER ID   IMAGE                              COMMAND                  CREATED        STATUS                PORTS                                                                                                                             NAMES
b6064b0ae371   jarischaefer/docker-librenms       "/sbin/my_init"          34 hours ago   Up 34 hours           443/tcp, 0.0.0.0:9001->80/tcp, :::9001->80/tcp                                                                                    librenms-web-1
f7e81da94af5   mariadb:10.5                       "docker-entrypoint.s…"   34 hours ago   Up 34 hours           3306/tcp                                                                                                                          librenms_database

以這個範例來說就是,該 container ID 為 b6064b0ae371

  1. 進入該容器
# docker exec -it b6064b0ae371 /bin/bash

進入容器後,切到 /usr/lib/nagios/plugins 目錄

# cd /usr/lib/nagios/plugins

然後你就會找到 ./check_http 你可以對他做測試
例如以下的幾個實例可以快速進入狀況

附註:在容器內找不到 ./check_http 程式?

如果在容器內找不到 ./check_http 程式
可以找尋看看 /opt/librenms/config.php 這個設定檔

可能會找到這段

$config['nagios_plugins'] = "/usr/lib/nagios/plugins";

這邊就有記載著 nagios_plugins 它的路徑

或者你的 nagios_plugins 沒有安裝,可能要參考文件手動安裝

舉一些範例

我把 LibreNMS 設定參數與測試指令放在一起做對照

檢測 http 連結

檢測 http 連結,例如 http://192.168.1.1:8080/hello ,其中須包含 Hello 字樣

  • Remote Host: 192.168.1.1
  • Parameters: -p 8080 -f follow -s "Hello" -u "/hello"
測試指令

這裡列出前述方法的測試指令與執行結果,供大家參考

./check_http -H 192.168.1.1 -p 8080 -s "Hello" -u "/hello" -f follow
HTTP OK: HTTP/1.1 200 OK - 235 bytes in 0.025 second response time |time=0.024936s;;;0.000000;10.000000 size=235B;;;0
參數說明
  • -H 192.168.1.1:指定 Host name 為 192.168.1.1
  • -p 8080 :設定 連接埠 (port) 號,為 8080
  • -u /hello :指定 Path 為 /hello
  • -f follow :跟隨轉址 (Follow redirect)
  • -s "hello" :有出現 hello 關鍵字才算成功

檢測 https 連結

檢測 https 連結,例如 https://google.com/ ,其中須包含 Google 字樣

  • Remote Host: google.com
  • Parameters: -S --sni -f follow -u "/" -s "Google"
測試指令

這裡列出前述方法的測試指令與執行結果,供大家參考

./check_http -H google.com -S --sni -f follow -u "/" -s "Google"
HTTP OK: HTTP/1.1 200 OK - 21613 bytes in 0.555 second response time |time=0.555301s;;;0.000000;10.000000 size=21613B;;;0
參數說明
  • -H google.com:指定 Host name 為 google.com
  • -S :使用 SSL 加密協定 (https)
  • --sni:使用 Server Name Indication (SNI) 伺服器名稱指示
  • -f follow :跟隨轉址 (Follow redirect)
  • -u / :指定 Path 為 / (在這個範例可省略)
  • -s "Google" :有出現 Google 關鍵字才算成功

檢查 POST API (x-www-form-urlencoded)

這個範例可能比較少用,但還是附上來

檢查 POST API,例如 POST 到 https://httpbin.org/post ,參數為 aaa=bbb (x-www-form-urlencoded) ,其中須包含 origin 字樣

  • Remote Host: httpbin.org
  • Parameters: -S --sni -f follow -u "/post" -P "aaa=bbb" -s "origin"
測試指令
./check_http -H httpbin.org -S --sni -f follow -u "/post" -P "aaa=bbb" -s "origin"
HTTP OK: HTTP/1.1 200 OK - 662 bytes in 3.446 second response time |time=3.446157s;;;0.000000;10.000000 size=662B;;;0
參數說明
  • -H httpbin.org:指定 Host name 為 httpbin.org
  • -S :使用 SSL 加密協定 (https)
  • --sni:使用 Server Name Indication (SNI) 伺服器名稱指示
  • -f follow :跟隨轉址 (Follow redirect)
  • -u /post :指定 Path 為 /post
  • -P "aaa=bbb" :設定 POST 參數,aaa=bbb (x-www-form-urlencoded)
  • -s "origin" :有出現 origin 關鍵字才算成功

檢查 POST API (json)

檢查 POST API,例如 POST 到 https://httpbin.org/post ,參數為 {"aaa":"bbb"} (application/json) ,其中須包含 origin 字樣

  • Remote Host: httpbin.org
  • Parameters: -S --sni -f follow -u "/post" -T "Content-Type:application/json" -P "{\"aaa\": \"bbb\"}" -s "origin"
測試指令
./check_http -H httpbin.org -S --sni -f follow -u "/post" -T "Content-Type:application/json" -P "{\"aaa\": \"bbb\"}" -s "origin"
HTTP OK: HTTP/1.1 200 OK - 676 bytes in 1.333 second response time |time=1.332586s;;;0.000000;10.000000 size=676B;;;0
參數說明
  • -H httpbin.org:指定 Host name 為 httpbin.org
  • -S :使用 SSL 加密協定 (https)
  • --sni:使用 Server Name Indication (SNI) 伺服器名稱指示
  • -f follow :跟隨轉址 (Follow redirect)
  • -u /post :指定 Path 為 /post
  • -T "Content-Type:application/json" :設定 POST 參數的 Content-Type 為 application/json
  • -P "{\"aaa\": \"bbb\"}" :設定 POST 參數,{"aaa": "bbb"} (application/json)
  • -s "origin" :有出現 origin 關鍵字才算成功

檢查 HTTP 狀態碼

在有些時候,別的團隊沒有特別做出 health check API,但我們還是可以做檢查
例如我們可以找一個 API 可能會回應 404 not found
我們就拿這個方式來檢查

註: 404 不等於網路接不上,404 是網路「有接上」,但是沒有這個頁面
如果是網路接不上,會是 timeout,而這就是我們要檢查的

檢查 HTTP 狀態碼,例如 https://httpbin.org/status/404 ,狀態碼為 404

  • Remote Host: httpbin.org
  • Parameters: -S --sni -f follow -u "/status/404" -e 404
測試指令

這裡列出前述方法的測試指令與執行結果,供大家參考

./check_http -H httpbin.org -S --sni -f follow -u "/status/404" -e 404
HTTP OK: Status line output matched "404" - 238 bytes in 2.494 second response time |time=2.493861s;;;0.000000;10.000000 size=238B;;;0
參數說明
  • -H httpbin.org:指定 Host name 為 httpbin.org
  • -S :使用 SSL 加密協定 (https)
  • --sni:使用 Server Name Indication (SNI) 伺服器名稱指示
  • -f follow :跟隨轉址 (Follow redirect)
  • -u /status/404 :指定 Path 為 /status/404
  • -e 404 :狀態碼有出現 404 關鍵字才算成功

檢查 SSL 憑證期限

檢查 SSL 憑證是否有到期,例如 https://example.com/ 的憑證期限

  • Remote Host: example.com
  • Parameters: --sni -S -C 30,10
測試指令

這裡列出前述方法的測試指令與執行結果,供大家參考

./check_http -H example.com --sni -S -C 30,10
OK - Certificate 'www.example.org' will expire on Sat Mar  1 23:59:59 2025 +0000.
參數說明
  • -H example.com:指定 Host name 為 example.com
  • --sni:使用 Server Name Indication (SNI) 伺服器名稱指示
  • -S :使用 SSL 加密協定 (https) 
  • -C 30,10 :設定過期時限通知,30 天標黃色,10 天標紅色

個人小結

這邊做一個小總結與加上一點個人建議
關於 HTTP 健康度測量這部分,我覺得 LibreNMS 設定上比較沒那麼直覺,
可能等待有緣人來修改這段的程式碼

個人可以給出一些設定上的小建議

  • 測試指令原本寫 -H 的地方,在 LibreNMS 中就寫在 Remote Host 的地方
  • 使用 -u 參數指令後續的路徑
  • 建議不管有沒有第二層子網域都加上 --sni 參數,避免網域被合併而測不到的情境
  • 建議可以加上 -f follow 參數,自動做頁面轉導,避免頁面需要轉導跳出 301 moved permanently 造成不預期的情境
  • 有 https 請加上 -S 參數
  • 如果回應不是 200 OK,使用 -e 參數指定 Response 應看到的 http status code
    例如 -e 404 代表瀏覽該頁面應該要看到 404 not found
    (網路不通等待到 timeout 跟看到 404 有所不同,前者網路不通,後者網路有通但無此頁面)
  • 如果有特定的關鍵字,可以使用 -s 參數指定,例如 -s "Hello" 代表要看到 Hello 字樣才算成功
  • 如果要測試語法,可以用 ./check_http -v 使用 verbose 模式,可以看到更多的訊息,還可以看到原始的 HTTP 封包

希望這篇文章能有所幫助,祝大家設定愉快!

參考資料