LOADING

加载过慢请开启缓存 浏览器默认开启

宝塔告警 IP 溯源级联查询

通过修改宝塔内部的 Python 发信脚本,接入 高德地图腾讯地图 以及太平洋网络、ip-api的 API,实现告警信息的精准溯源。

🛠️ 准备工作

  1. 高德开放平台:注册账号 -> 创建Web服务应用 -> 获取 Key
  2. 腾讯位置服务:微信扫码登录 -> 创建Web服务应用 -> 获取 Key

💻 修改教程

1. 找到文件

以飞书通知为例(钉钉/企业微信同理),在宝塔文件管理中打开:
/www/server/panel/class/feishu_msg.py

2. 注入代码

搜索找到 def send_msg 函数,在函数内部对应位置插入以下代码(记得替换你自己的 Key):

    def send_msg(self,msg,to_user = 'default'):
        """
        飞书发送信息
        @msg 消息正文
        """
# ================== 【开始】四网级联IP查询(高德/腾讯/太平洋/ip-api) ==================
        try:
            import re
            AMAP_KEY = "高德地图API"
            TENCENT_KEY = "腾讯地图API"
 
            def q_amap(ip):
                try:
                    res = requests.get("https://restapi.amap.com/v3/ip?ip={}&key={}".format(ip, AMAP_KEY), timeout=2, verify=False).json()
                    if res.get('status') == '1':
                        p, c = res.get('province', ''), res.get('city', '')
                        if isinstance(p, list) or isinstance(c, list) or not p: return None
                        return "{}{}".format(p, c)
                except: pass
                return None
 
            def q_tencent(ip):
                try:
                    res = requests.get("https://apis.map.qq.com/ws/location/v1/ip?ip={}&key={}".format(ip, TENCENT_KEY), timeout=2, verify=False).json()
                    if res.get('status') == 0:
                        info = res.get('result', {}).get('ad_info', {})
                        p, c = info.get('province', ''), info.get('city', '')
                        if not p: return None
                        return "{}{}".format(p, c)
                except: pass
                return None
 
            def q_pconline(ip):
                try:
                    res = requests.get("http://whois.pconline.com.cn/ipJson.jsp?ip={}&json=true".format(ip), timeout=2, verify=False)
                    if res.encoding == 'ISO-8859-1': res.encoding = 'gbk'
                    addr = res.json().get('addr', '').strip()
                    return addr if addr else None
                except: pass
                return None
 
            def q_ipapi(ip):
                try:
                    res = requests.get("http://ip-api.com/json/{}?lang=zh-CN".format(ip), timeout=3, verify=False).json()
                    if res.get('status') == 'success':
                        return "{} {}".format(res.get('country', ''), res.get('city', '')).strip()
                except: pass
                return None
 
            ip_pattern = r'(?<![0-9])(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})\.){3}(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})(?![0-9])'
            all_ips = re.findall(ip_pattern, msg)
            unique_ips = []
            [unique_ips.append(i) for i in all_ips if i not in unique_ips]
 
            geo_res = []
            for ip in unique_ips[:5]:
                addr = q_amap(ip)
                if not addr: addr = q_tencent(ip)
                if not addr: addr = q_pconline(ip)
                if not addr: addr = q_ipapi(ip)
                
                if addr: geo_res.append("{} ({})".format(ip, addr))
                else: geo_res.append("{} (未知)".format(ip))
 
            if geo_res:
                msg = "📍 来源溯源:\n" + "\n".join(geo_res) + "\n\n----------------\n" + msg
        except: pass
# ================== 【结束】 ==================
        if not self.__feishu_info :
            return public.returnMsg(False,'未正确配置飞书信息。')
        ...

📱 最终效果

保存文件后,在宝塔告警设置里点“测试发送”。

修改后告警样式: 📍 来源溯源: 111.55.xxx.xxx (xx省xx市/国家) 防火墙拦截记录告警: …