DNS解析检测与告警脚本
检测多个域名的DNS解析是否正常,对比解析结果是否符合预期,检测DNS污染或解析异常,支持多个DNS服务器对比
详细内容
#!/bin/bash
# ==========================================
# DNS解析检测与告警脚本
# 用途:检测域名DNS解析是否正常,对比预期IP
# 使用方法:bash dns_check.sh
# ==========================================
# ========== 配置 ==========
# 检测列表:域名|预期IP(多个用逗号分隔,留空只检测是否能解析)
DOMAINS=(
"www.baidu.com|180.101.50.242,180.101.50.188"
"www.aliyun.com|"
"github.com|"
# "api.example.com|1.2.3.4"
)
DNS_SERVERS=("223.5.5.5" "114.114.114.114" "8.8.8.8")
RESOLVE_TIMEOUT=5
LOG_FILE="/var/log/dns_check.log"
ALERT_EMAIL=""
WECOM_WEBHOOK=""
# ==========================
mkdir -p "$(dirname "$LOG_FILE")"
log_msg() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
send_alert() {
local title="$1"
local content="$2"
log_msg "【告警】$title: $content"
if [ -n "$ALERT_EMAIL" ]; then
echo -e "$content" | mail -s "【DNS告警】$title" "$ALERT_EMAIL" 2>/dev/null
fi
if [ -n "$WECOM_WEBHOOK" ]; then
curl -s "$WECOM_WEBHOOK" -H "Content-Type: application/json" -d "{
"msgtype": "text",
"text": {"content": "【DNS告警】$title\n$content"}
}" >/dev/null 2>&1
fi
}
resolve_domain() {
local domain="$1"
local dns_server="$2"
if command -v dig >/dev/null 2>&1; then
dig +short +time="$RESOLVE_TIMEOUT" "@$dns_server" "$domain" A 2>/dev/null | grep -E "^[0-9]+\." | sort
elif command -v nslookup >/dev/null 2>&1; then
nslookup -timeout="$RESOLVE_TIMEOUT" "$domain" "$dns_server" 2>/dev/null | grep -A10 "Name:" | grep "Address:" | awk '{print $2}' | sort
else
getent hosts "$domain" 2>/dev/null | awk '{print $1}' | sort
fi
}
log_msg "=========================================="
log_msg " DNS解析检测报告"
log_msg " 检测时间: $(date '+%Y-%m-%d %H:%M:%S')"
log_msg "=========================================="
ALL_OK=true
for item in "${DOMAINS[@]}"; do
domain=$(echo "$item" | cut -d'|' -f1)
expected_ips=$(echo "$item" | cut -d'|' -f2)
log_msg ""
log_msg "【$domain】"
ALL_IPS=""
DNS_RESULTS=""
for dns in "${DNS_SERVERS[@]}"; do
ips=$(resolve_domain "$domain" "$dns")
if [ -z "$ips" ]; then
log_msg " 🔴 DNS $dns: 解析失败"
DNS_RESULTS="$DNS_RESULTS
$dns: 解析失败"
ALL_OK=false
else
ip_list=$(echo "$ips" | tr '\n' ',' | sed 's/,$//')
log_msg " 🟢 DNS $dns: $ip_list"
DNS_RESULTS="$DNS_RESULTS
$dns: $ip_list"
ALL_IPS="$ALL_IPS $ips"
fi
done
# 检查不同DNS解析结果是否一致
UNIQUE_IPS=$(echo "$ALL_IPS" | tr ' ' '\n' | grep -v '^$' | sort -u)
UNIQUE_COUNT=$(echo "$UNIQUE_IPS" | grep -c .)
if [ "$UNIQUE_COUNT" -gt 1 ]; then
log_msg " ⚠️ 不同DNS解析结果不一致: $(echo "$UNIQUE_IPS" | tr '\n' ',')"
send_alert "$domain DNS解析不一致" "不同DNS服务器解析结果不同:\n$DNS_RESULTS"
ALL_OK=false
fi
# 对比预期IP
if [ -n "$expected_ips" ]; then
MATCH=false
for expected in $(echo "$expected_ips" | tr ',' ' '); do
if echo "$UNIQUE_IPS" | grep -q "^${expected}$"; then
MATCH=true
break
fi
done
if [ "$MATCH" = false ]; then
log_msg " 🔴 解析结果与预期不符!预期: $expected_ips 实际: $(echo "$UNIQUE_IPS" | tr '\n' ',')"
send_alert "$domain DNS解析异常" "解析结果与预期不符!\n预期IP: $expected_ips\n实际IP: $(echo "$UNIQUE_IPS" | tr '\n' ',')\n可能存在DNS污染或解析错误"
ALL_OK=false
else
log_msg " ✅ 解析结果与预期一致"
fi
fi
done
log_msg ""
if [ "$ALL_OK" = true ]; then
log_msg "✅ 所有域名DNS解析正常"
else
log_msg "❌ 存在DNS解析异常,请查看上方告警"
fi
log_msg "=========================================="
适配环境
适配系统:CentOS 7+,Ubuntu 18.04+,Debian 10+
依赖环境:bash 4.0+
参数说明
[{"name": "DOMAINS", "label": "\u57df\u540d\u5217\u8868(\u6bcf\u884c\u4e00\u4e2a\uff0c\u683c\u5f0f\uff1a\u57df\u540d|\u9884\u671fIP)", "type": "textarea", "default": "www.baidu.com|\nwww.aliyun.com|"}, {"name": "DNS_SERVERS", "label": "DNS\u670d\u52a1\u5668(\u7a7a\u683c\u5206\u9694)", "default": "223.5.5.5 114.114.114.114 8.8.8.8"}, {"name": "ALERT_EMAIL", "label": "\u544a\u8b66\u90ae\u7bb1(\u53ef\u9009)", "default": ""}]