目录
一、方案概述
1.1 监控原理
- 通过防火墙策略,让不同域名走不同的出口线路
- Zabbix 定期访问这些域名,获取访问时的出口IP
- 将获取的IP与预设值比较,不一致时通过飞书发送告警
1.2 线路与域名对应关系示例
| 线路编号 | 域名 | 预设IP | 出口接口 |
|---|---|---|---|
| 线路1 | ifconfig.me | 203.0.113.10 | port2 |
| 线路2 | api.ipify.org | 203.0.113.20 | port3 |
| 线路3 | icanhazip.com | 203.0.113.30 | port4 |
| ... | ... | ... | ... |
二、环境准备
2.1 前提条件
- Zabbix Server 7.4 已部署(Docker或物理机)
- 已获取飞书机器人 Webhook 地址
- Zabbix Server 能访问外网(IP查询服务)
2.2 确认Zabbix容器名称
bash
docker ps | grep zabbix
记录Zabbix Server容器名称(如 zabbix-server)
三、部署外部检查脚本
3.1 进入Zabbix Server容器
bash
docker exec -it zabbix-server sh
3.2 创建脚本目录并编写脚本
bash
# 创建目录
mkdir -p /usr/lib/zabbix/externalscripts
# 创建脚本文件
cat > /usr/lib/zabbix/externalscripts/get_ip_by_domain.sh << 'EOF'
#!/bin/bash
# 通过指定的域名获取公网出口IP
# 用法:get_ip_by_domain.sh <域名>
DOMAIN="$1"
TIMEOUT=5
if [ -z "$DOMAIN" ]; then
echo "ERROR: No domain provided"
exit 1
fi
# 使用curl访问域名,提取IPv4地址
IP=$(curl -s -L -m $TIMEOUT "http://$DOMAIN" 2>/dev/null | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1)
if [ -n "$IP" ]; then
echo "$IP"
exit 0
else
echo "ERROR: Failed to get IP from $DOMAIN"
exit 1
fi
EOF
# 赋予执行权限
chmod +x /usr/lib/zabbix/externalscripts/get_ip_by_domain.sh
# 修改属主
chown zabbix:zabbix /usr/lib/zabbix/externalscripts/get_ip_by_domain.sh
# 安装curl(Alpine系统)
apk add curl
3.3 测试脚本
bash
su -s /bin/sh -c "/usr/lib/zabbix/externalscripts/get_ip_by_domain.sh api.ipify.org" zabbix
应返回一个公网IP地址。
3.4 退出容器
bash
exit
四、创建监控项
4.1 登录Zabbix Web
访问 http://你的Zabbix服务器IP:8080,使用 Admin/zabbix 登录。
4.2 创建监控项
- 进入 配置 → 主机 ,选择目标主机(如
hwipmonitor) - 点击 监控项 → 创建监控项
4.3 填写监控项信息
| 字段 | 填写内容 |
|---|---|
| 名称 | WAN01 Exit IP (via api.ipify.org) |
| 类型 | 外部检查 |
| 键值 | get_ip_by_domain.sh["api.ipify.org"] |
| 信息类型 | 文本 |
| 更新间隔 | 60m |
| 历史记录保留期 | 3d |
4.4 保存
点击 添加 完成创建。
4.5 验证监控项
- 进入 监控 → 最新数据
- 筛选主机,查看监控项是否有数据
- 状态应为 已启用,且有IP值
五、创建触发器
5.1 进入触发器创建
- 配置 → 主机 → 选择主机 → 触发器 → 创建触发器
5.2 填写触发器信息
| 字段 | 填写内容 |
|---|---|
| 名称 | WAN01 出口IP异常 (api.ipify.org) |
| 严重性 | 警告 |
| 描述 | 期望IP:103.248.229.101(填写实际预设IP) |
| 表达式 | {hwipmonitor:get_ip_by_domain.sh["api.ipify.org"].last()}<>"103.248.229.101" |
5.3 表达式说明
{主机名:监控项键值.last()}:获取监控项最新值<>"预设IP":不等于预设IP- 如需排除脚本错误,可添加
and {监控项.str(ERROR)}=0
5.4 保存
点击 添加 完成创建。
六、配置飞书媒介
6.1 进入媒介类型配置
管理 → 报警媒介类型 → 创建媒介类型
6.2 填写基本信息
| 字段 | 填写内容 |
|---|---|
| 名称 | feishu |
| 类型 | Webhook |
6.3 添加参数
点击 参数 标签页,添加以下参数:
| 名称 | 值 |
|---|---|
Subject |
{ALERT.SUBJECT} |
Message |
{ALERT.MESSAGE} |
6.4 编写脚本
在 脚本 框中输入以下内容(将Webhook地址替换为实际地址):
javascript
try {
var params = JSON.parse(value),
req = new HttpRequest(),
webhook_url = 'https://open.feishu.cn/open-apis/bot/v2/hook/你的完整Webhook地址',
msg = {
msg_type: "text",
content: {
text: params.Subject + "\n" + params.Message
}
},
resp;
req.addHeader("Content-Type: application/json");
resp = req.post(webhook_url, JSON.stringify(msg));
if (req.getStatus() != 200) {
throw "Response code: " + req.getStatus();
}
resp = JSON.parse(resp);
return JSON.stringify(resp);
} catch (error) {
throw "Failed with error: " + error;
}
6.5 测试媒介
- 点击 测试 按钮
- 填写测试内容:
- Subject :
测试告警 - Message :
这是一条测试消息
- Subject :
- 点击 测试
- 确认飞书群收到测试消息
6.6 保存
点击 添加 完成创建。
七、配置用户媒介
7.1 进入用户配置
管理 → 用户 → 点击 Admin (Zabbix Administrator)
7.2 添加报警媒介
- 点击 报警媒介 标签页
- 点击 添加
- 填写:
- 类型 :选择
feishu - 收件人 :填写
飞书群(任意标识) - 当活动时:默认
- 严重性:全选
- 启用:勾选
- 类型 :选择
- 点击 添加
7.3 保存
点击 更新 保存用户配置。
八、创建动作
8.1 进入动作配置
配置 → 动作 → 触发器动作 → 创建动作
8.2 填写基本信息
| 字段 | 填写内容 |
|---|---|
| 名称 | 出口IP异常飞书告警 |
8.3 配置条件
点击 条件 标签页,添加:
- 类型:触发器名称
- 运算符:包含
- 值 :
出口IP异常
这样所有名称包含"出口IP异常"的触发器都会触发此动作。
8.4 配置操作
点击 操作 标签页 → 新增:
| 字段 | 填写内容 |
|---|---|
| 操作类型 | 发送消息 |
| 默认接收人 | 选择 Admin (Zabbix Administrator) |
| 仅送到 | 选择 feishu |
| 主题 | 告警:{TRIGGER.NAME} |
| 消息 | 主机:{HOST.NAME}\n当前IP:{ITEM.LASTVALUE}\n期望IP:{TRIGGER.DESCRIPTION}\n时间:{EVENT.DATE} {EVENT.TIME} |
| 自定义持续时间 | 0 |
| 仅当问题出现时发送 | ✅ 勾选 |
8.5 配置恢复操作(可选)
点击 新增 添加恢复操作:
| 字段 | 填写内容 |
|---|---|
| 操作类型 | 发送消息 |
| 默认接收人 | 选择 Admin |
| 仅送到 | feishu |
| 主题 | 恢复:{TRIGGER.NAME} |
| 消息 | 主机:{HOST.NAME}\n当前IP:{ITEM.LASTVALUE}\n时间:{EVENT.DATE} {EVENT.TIME} |
| 自定义持续时间 | 0 |
| 仅当问题恢复时发送 | ✅ 勾选 |
8.6 保存
点击 添加 完成动作创建。
九、测试验证
9.1 强制触发测试
临时修改触发器表达式,强制触发告警:
-
配置 → 主机 → 选择主机 → 触发器
-
找到目标触发器,点击编辑
-
将表达式改为:
{hwipmonitor:get_ip_by_domain.sh["api.ipify.org"].last()}<>"1.2.3.4" -
保存
-
等待几秒,进入 监控 → 问题,应看到触发器变为问题状态
-
进入 报表 → 动作日志,查看发送记录
-
检查飞书是否收到告警
9.2 恢复表达式
测试完成后,将表达式改回正确的预设IP。
9.3 验证飞书消息
飞书应收到类似以下内容的消息:
告警:WAN01 出口IP异常 (api.ipify.org)
主机:hwipmonitor
当前IP:103.248.229.101
期望IP:期望IP:103.248.229.101
时间:2026.03.30 17:04:23
十、批量配置其他线路
10.1 方法一:手动创建
为每个域名重复以下操作:
- 创建监控项(修改键值中的域名)
- 创建触发器(修改预设IP和域名)
- 触发器名称格式:
WAN01 出口IP异常 (域名)
10.2 方法二:使用模板
- 创建一个模板,添加所有监控项和触发器
- 将模板链接到主机
10.3 方法三:使用Zabbix API(Python脚本)
python
#!/usr/bin/env python3
import csv
from zabbix_api import ZabbixAPI
# 配置
ZABBIX_URL = "http://localhost/zabbix"
USER = "Admin"
PASSWORD = "zabbix"
HOST_NAME = "hwipmonitor"
# 线路配置列表
configs = [
{"domain": "ifconfig.me", "ip": "203.0.113.10"},
{"domain": "api.ipify.org", "ip": "103.248.229.101"},
{"domain": "icanhazip.com", "ip": "203.0.113.30"},
# ... 添加更多
]
zapi = ZabbixAPI(ZABBIX_URL)
zapi.login(USER, PASSWORD)
# 获取主机ID
hosts = zapi.host.get({"filter": {"host": HOST_NAME}})
host_id = hosts[0]["hostid"]
for config in configs:
domain = config["domain"]
preset_ip = config["ip"]
# 创建监控项
item = zapi.item.create({
"name": f"WAN01 Exit IP (via {domain})",
"key_": f'get_ip_by_domain.sh["{domain}"]',
"hostid": host_id,
"type": 0, # 外部检查
"value_type": 1, # 文本
"delay": "60m",
"history": "3d"
})
# 创建触发器
trigger = zapi.trigger.create({
"description": f"WAN01 出口IP异常 ({domain})",
"expression": f'{{{HOST_NAME}:get_ip_by_domain.sh["{domain}"].last()}}<>"{preset_ip}"',
"priority": 2, # 警告
"comments": f"期望IP:{preset_ip}",
"status": 0
})
print(f"已创建: {domain} -> {preset_ip}")
十一、常见问题排查
11.1 监控项显示"不支持"
可能原因:
- 脚本不存在或路径错误
- 脚本没有执行权限
- 缺少curl命令
解决方法:
bash
# 检查脚本是否存在
ls -l /usr/lib/zabbix/externalscripts/get_ip_by_domain.sh
# 检查curl是否安装
which curl
# 测试脚本
su -s /bin/sh -c "/usr/lib/zabbix/externalscripts/get_ip_by_domain.sh api.ipify.org" zabbix
11.2 飞书收不到消息
可能原因:
- Webhook地址错误
- 飞书机器人安全设置(关键词/IP白名单)
- 脚本中URL为空
解决方法:
- 在媒介类型中点击测试,确认能收到
- 检查飞书机器人安全设置,添加关键词"告警"
- 确认脚本中Webhook地址正确
11.3 动作日志显示"No media defined for user"
解决方法:
- 进入 管理 → 用户,为Admin用户添加feishu媒介
- 确认媒介类型已启用
11.4 触发器表达式语法错误
正确格式:
{主机名:监控项键值.last()}<>"预设IP"
常见错误:
- 缺少花括号
{} - IP未加双引号
- 使用中文括号
11.5 查看Zabbix Server日志
bash
# Docker环境
docker logs zabbix-server --tail 100 | grep -i error
# 物理机
tail -f /var/log/zabbix/zabbix_server.log
十二、总结
12.1 配置文件清单
| 文件/配置 | 位置 |
|---|---|
| 外部脚本 | /usr/lib/zabbix/externalscripts/get_ip_by_domain.sh |
| 监控项 | Zabbix Web → 配置 → 主机 → 监控项 |
| 触发器 | Zabbix Web → 配置 → 主机 → 触发器 |
| 媒介类型 | Zabbix Web → 管理 → 报警媒介类型 |
| 用户媒介 | Zabbix Web → 管理 → 用户 |
| 动作 | Zabbix Web → 配置 → 动作 |
12.2 关键宏说明
| 宏 | 说明 |
|---|---|
{HOST.NAME} |
主机名 |
{TRIGGER.NAME} |
触发器名称 |
{ITEM.LASTVALUE} |
监控项最新值 |
{TRIGGER.DESCRIPTION} |
触发器描述 |
{EVENT.DATE} |
事件日期 |
{EVENT.TIME} |
事件时间 |
{ALERT.SUBJECT} |
告警主题 |
{ALERT.MESSAGE} |
告警内容 |
12.3 后续优化建议
- 调整检查频率:根据线路重要性,可设置为15-30分钟
- 添加期望IP显示:在触发器描述中填写期望IP
- 配置告警重复间隔:如需重复告警,修改自定义持续时间
- 使用模板:将监控项和触发器放入模板,方便批量管理
- 监控脚本健康:添加监控项监控脚本执行状态
至此,您已完成 Zabbix 多线路出口IP监控与飞书告警的全部配置。如有任何问题,欢迎随时交流!