LibreNMS 平常是用輪詢(polling)每 5 分鐘去問設備一次狀態,但有些事情等不了 5 分鐘:設備重新開機、介面斷線、UPS 轉電池。這類事件,設備可以主動送 SNMP Trap 通知監控系統。
LibreNMS 本身就能處理 SNMP Trap,但需要另外設定 snmptrapd,收進來之後也不會自動變成告警。這篇依官方文件整理從接收、解析到設定告警規則的完整流程,也修正了一些網路上常見、但其實不正確的寫法。
運作流程
設備 ──SNMP Trap (UDP 162)──> snmptrapd ──> /opt/librenms/snmptrap.php ──> Eventlog ──(告警規則)──> Alert
| 角色 | 說明 |
|---|---|
snmptrapd | Net-SNMP 的 Trap 接收程式,監聽 UDP 162 |
snmptrap.php | LibreNMS 的 Trap 處理入口,依 Trap 的 OID 交給對應的處理程式(handler) |
| Eventlog | Trap 處理的結果寫進裝置的事件記錄 |
| 告警規則 | Eventlog 不會自動告警,要自己寫規則 |
LibreNMS 內建了上百個 Trap 處理程式(GitHub 上 LibreNMS/Snmptrap/Handlers 目錄),常見的開機、介面上下線、各廠牌的硬體事件都有。
安裝與設定 snmptrapd
安裝
apt install snmptrapd
snmptrapd.conf
編輯 /etc/snmp/snmptrapd.conf,依官方文件加入:
disableAuthorization yes
authCommunity log,execute,net your-community
traphandle default /opt/librenms/snmptrap.php
traphandle default:關鍵設定,把所有 Trap 交給 LibreNMS 處理authCommunity:允許使用這個 community 的 Trap 執行 log、execute、net 動作disableAuthorization yes:停用存取控制,任何 community 的 Trap 都會被接受
disableAuthorization yes 方便測試,但正式環境建議拿掉,改由 authCommunity 限制只接受指定的 community,並用防火牆限制只有設備的網段能送 Trap 到 162/UDP。
載入 MIB
snmptrapd 需要 MIB 才能把 OID 解析成名稱。沒設定的話,Eventlog 會出現這樣的訊息:
Misconfigured MIBS or MIBDIRS for snmptrapd, check https://docs.librenms.org/Extensions/SNMP-Trap-Handler/ :
librenms01 UDP: [192.168.1.20]:54630->[192.168.1.20]:162 iso.3.6.1.2.1.1.3.0 7:1:20:31.18 iso.3.6.1.6.3.1.1.4.1.0 iso.3.6.1.6.3.1.1.5.1
意思是 Trap 有收到,但 snmptrapd 沒辦法解析,只能看到一串 OID。這種情況 LibreNMS 的處理程式也對應不到,所以只會留下這筆系統訊息,不會產生對應的事件。
依官方文件,用 systemd 的 override 指定 LibreNMS 內建的 MIB 目錄:
mkdir -p /etc/systemd/system/snmptrapd.service.d
cat > /etc/systemd/system/snmptrapd.service.d/mibs.conf <<'EOF2'
[Service]
Environment=MIBDIRS=+/opt/librenms/mibs:/opt/librenms/mibs/cisco
Environment=MIBS=+IF-MIB
EOF2
systemctl daemon-reload
systemctl enable snmptrapd
systemctl restart snmptrapd
# 確認環境變數有生效
systemctl show snmptrapd --property=Environment
MIBDIRS:MIB 檔案的目錄,不會遞迴,有需要的廠牌目錄要一個一個加,例如/opt/librenms/mibs/ciscoMIBS:要載入的 MIB,只列你需要的,例如介面上下線要IF-MIB,BGP 要再加BGP4-MIB
注意:官方文件特別說明不要用 -m ALL 載入全部 MIB,snmptrapd 通常會因為 MIB 數量太多而載入失敗。網路上有些教學在 snmptrapd.conf 寫 mibs +ALL 或另外安裝 snmp-mibs-downloader,在 LibreNMS 的環境不需要,LibreNMS 本身就附了 MIB。
確認有在監聽
ss -ulpn | grep 162
162 是特權通訊埠,snmptrapd 要以 root 執行。
設備端設定
在交換器、防火牆、UPS 等設備上設定:
- SNMP 版本(v2c 或 v3)與 community/帳號
- Trap 目的地:LibreNMS 主機的 IP,通訊埠 162/UDP
- 要送哪些 Trap(介面上下線、開機、硬體事件等)
注意:設備必須已經加入 LibreNMS 監控,Trap 才會對應到裝置並寫進它的 Eventlog。LibreNMS 是依送出 Trap 的來源 IP 找裝置的。
測試
最直接的方式是讓設備真的產生 Trap,例如拔插一條網路線(介面上下線)。也可以從 LibreNMS 主機自己送一個 coldStart Trap 給自己(前提是 LibreNMS 主機本身也在監控清單裡):
snmptrap -v 2c -c your-community localhost '' 1.3.6.1.6.3.1.1.5.1
'':uptime 留空,自動帶入系統的開機時間1.3.6.1.6.3.1.1.5.1:coldStart,代表設備剛開機
MIB 設定正確的話,Eventlog 會出現:

要看 snmptrapd 收到的原始 Trap,可以依官方文件在 ExecStart 加上 -tLf /var/log/snmptrap/traps.log 記錄到檔案,除錯時很有用。
Trap 寫進 Eventlog 的內容
這部分網路上的說法很多,我直接看了 LibreNMS 的原始碼,常見的幾種如下:
| Trap | eventlog.type | 訊息範例 | 等級 |
|---|---|---|---|
| coldStart | reboot | SNMP Trap: Device xxx cold booted | 警告(4) |
| warmStart | reboot | SNMP Trap: Device xxx warm booted | 警告(4) |
| linkDown | interface | SNMP Trap: linkDown up/down GigabitEthernet1/0/1 | 嚴重(5) |
| linkDown(同時記錄) | interface | Interface went Down : GigabitEthernet1/0/1 (TRAP) | 嚴重(5) |
| linkUp | interface | SNMP Trap: linkUp up/up GigabitEthernet1/0/1 | 正常(1) |
| 沒有處理程式的 Trap | trap | 依設定記錄 Trap OID | 資訊(2) |
| MIB 設定錯誤 | system | Misconfigured MIBS or MIBDIRS... | 資訊(2) |
幾個要特別注意的地方:
- 介面上下線的 type 是
interface,不是link。網路上很多範例寫eventlog.type = 'link',這樣的規則永遠不會觸發 - 不是所有 Trap 訊息都以
SNMP Trap:開頭,例如上表的Interface went Down : ... (TRAP) linkDown訊息裡的up/down是「管理狀態/運作狀態」:up/down是線斷了,down/down是管理者手動關閉- 各廠牌的處理程式 type 各自不同,以自己環境的 Eventlog 實際出現的 type 為準:到「Logs → Eventlog」依 Type 篩選看看
沒有處理程式的 Trap
沒有對應處理程式的 Trap,預設會記錄成 type 為 trap 的事件,可以在「全域設定 → 外部整合 → SNMP Traps Integration」調整,或用指令:
# unhandled:只記錄沒有處理程式的 Trap(預設)/all:全部記錄/none:不記錄
lnms config:set snmptraps.eventlog 'unhandled'
# 記錄 Trap 的完整內容(預設只記錄 Trap OID)
lnms config:set snmptraps.eventlog_detailed true
把 Trap 變成告警
Eventlog 只是記錄,要自己建立告警規則才會通知。到「告警 → 告警規則 → 建立新的告警規則」,可以用規則產生器,也可以直接寫 SQL 條件。
一定要加時間條件
告警規則每次輪詢都會重新判斷。Eventlog 的舊記錄不會消失,規則如果只寫 eventlog.type = "reboot",只要曾經重新開機過一次,這個告警就會一直成立,永遠不會恢復。
官方文件的做法是加上時間的巨集,只看最近一段時間的事件:
eventlog.type = "reboot" AND eventlog.datetime >= macros.past_10m
macros.past_10m 是 10 分鐘前的時間,可用的有 5、10、15、30、60 分鐘。
LibreNMS 收到 Trap 處理完之後,會立刻對這台裝置執行一次告警規則判斷,不用等下一次輪詢,所以告警幾乎是即時的。時間範圍則決定告警要維持多久:我習慣用 10 分鐘,至少會經過一次輪詢再恢復。時間過了之後告警會自動恢復,如果不想收到恢復通知,可以在規則裡關掉。
規則範例
設備重新開機:
eventlog.type = "reboot" AND eventlog.datetime >= macros.past_10m
介面斷線(排除管理者手動關閉):
eventlog.type = "interface" AND eventlog.message REGEXP "linkDown up/down" AND eventlog.datetime >= macros.past_10m
up/down 代表管理狀態是開、運作狀態是斷,也就是線真的斷了;手動關閉的是 down/down,不會被這條規則抓到。只看關鍵的上行介面,可以再加上介面名稱的條件。
依事件等級:
eventlog.severity >= 5 AND eventlog.message REGEXP "TRAP|SNMP Trap" AND eventlog.datetime >= macros.past_10m
等級 5 是嚴重,搭配訊息條件只抓 Trap 來源的事件。
沒有處理程式的 Trap(先觀察用):
eventlog.type = "trap" AND eventlog.datetime >= macros.past_10m
適合導入初期看看設備到底送了哪些 Trap,再決定要不要針對它寫正式的規則。
寫規則的原則
- 優先用
eventlog.type,再用eventlog.message補充條件 - 訊息比對用關鍵字,不要比對整段文字(裝置名稱、介面名稱都會變)
- 規則先套用在一兩台設備測試,確認不會一直誤報,再擴大範圍
常見問題
| 狀況 | 檢查 |
|---|---|
| Eventlog 完全沒有記錄 | ss -ulpn | grep 162 有沒有在聽、防火牆、設備的 Trap 目的地與 community |
只看到 Misconfigured MIBS or MIBDIRS | MIB 沒設定好,檢查 systemd override 與 MIBS 是否包含需要的 MIB |
| 有收到但沒對應到裝置 | 設備沒加入 LibreNMS,或送 Trap 的來源 IP 和監控用的 IP 不同 |
| 告警一直不恢復 | 規則沒有加 eventlog.datetime >= macros.past_Nm |
eventlog.type = 'link' 不會觸發 | 介面的 type 是 interface |
結論
LibreNMS 收 SNMP Trap 的關鍵設定只有三個:traphandle 指到 snmptrap.php、systemd 指定 MIB 目錄、設備加入監控。收進來之後只是 Eventlog,要告警就自己寫規則,而且一定要加時間條件。
網路上流傳的規則範例,很多 type 是猜的,寫之前先到 Eventlog 看看實際的 type 與訊息,比照著寫最準。
參考資料
- LibreNMS 文件:SNMP Trap Handler
https://docs.librenms.org/Extensions/SNMP-Trap-Handler/ - LibreNMS 文件:Alert Rules
https://docs.librenms.org/Alerting/Rules/ - LibreNMS 文件:Alert Macros
https://docs.librenms.org/Alerting/Macros/ - LibreNMS 原始碼:SNMP Trap Handlers
https://github.com/librenms/librenms/tree/master/LibreNMS/Snmptrap/Handlers - LibreNMS 透過 IPMI 監控伺服器 BMC 感測器
https://blog.jason.tools/2025/10/librenms-ipmi-bmc.html

