PearAdmin二次开发之防火墙封禁工具——IP地理位置归属

目录

一、需求描述

二、设计实现

2.1 geoip2 模块

2.2 数据库

2.3 前端页面

2.4 后端接口

三、效果展示


一、需求描述

        基础封禁数据概览

        以卡片形式呈现多维度封禁统计值,涵盖今日、本周、本月的封禁数量,累计封禁总数,涉及攻击来源国家数,以及资产统计数,快速展示防护成果与规模 。

        近期封禁趋势分析

        通过柱状图呈现最近一周(08 - 05 至 08 - 11)每日封禁 IP 动态,不同颜色柱体叠加展示当日不同攻击来源(对应图例国家 / 地区)的封禁情况,辅助分析攻击波峰波谷与来源变化 。
地理分布可视化

        借助环形饼图,呈现最近一周被封禁 IP 的地理来源占比,不同颜色区块对应不同国家 / 地区,直观展现攻击源的地域集中性 。

        攻击源排名洞察

        以柱状图展示 “TOP 30 国家攻击 IP 统计”,按攻击贡献排序,清晰呈现攻击最频繁的前 30 个国家 / 地区及对应封禁量,为重点防护方向提供数据支撑 。

二、设计实现

2.1 geoip2 模块

import geoip2.database
from IPy import IP
import re
from datetime import datetime
from applications.extensions import db
from applications.models import Hwip


def get_ip_location(ip_address, db_path='./GeoLite2-City.mmdb'):
    """查询 IP 地址的地理位置信息(优化版)"""
    try:
        cidr_pattern = r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/([0-2]?[0-9]|3[0-2])$'
        if re.match(cidr_pattern, ip_address):
            ips = IP(ip_address)
            for ip in ips:
                with geoip2.database.Reader(db_path) as reader:
                    # 优先使用中文查询,失败时回退到英文
                    try:
                        response = reader.city(str(ip), locale='zh-CN')
                    except Exception:
                        response = reader.city(str(ip))
                    # 提取地理位置信息
                    country = response.country.names.get('zh-CN') or response.country.name
                    city = response.city.names.get('zh-CN') or response.city.name
                    province = response.subdivisions.most_specific.names.get('zh-CN') or response.subdivisions.most_specific.name
                    timestamp = datetime.now()
                    print(country,city,province)
                    if country == '中华民国' or country == '香港':
                        country == '中国'
                    if country == '大韩民国':
                        country == '韩国'
                    rule = Hwip(timestamp=timestamp, ip=str(ip), country=country, city=city, province=province)
                    db.session.add(rule)
            db.session.commit()
    except geoip2.errors.AddressNotFoundError:
        print(f"错误:未找到 IP {ip} 的地理位置信息")
        return None

    except Exception as e:
        print(f"查询失败:{str(e)}")
        return None

2.2 数据库

from applications.extensions import db

class Hwip(db.Model):
    __tablename__ = 'admin_hwip'
    id = db.Column(db.Integer, autoincrement=True,  primary_key=True)
    timestamp = db.Column(db.String(20), nullable=False, comment='创建时间')
    ip = db.Column(db.String(20), nullable=False, comment='封禁|解封的IP')
    country = db.Column(db.String(20), nullable=False)
    city = db.Column(db.String(80), comment='城市')
    province = db.Column(db.String(80), comment='省份')

2.3 前端页面

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>分析页</title>
    {% include 'system/common/header.html' %}
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="{
  
  { url_for('static', filename='system/admin/css/other/analysis.css') }}"/>
</head>

<body>
    <div class="pear-container">
        <div class="layui-row layui-col-space12">
            <div class="layui-col-xs6 layui-col-md2">
                <div class="layui-card top-panel">
                    <div class="layui-card-header">今日封禁</div>
                    <div class="layui-card-body">
                        <div class="layui-row layui-col-space5">
                            <div class="layui-col-xs8 layui-col-md8 top-panel-number" style="color: #28333E;"
                                id="value1">
                                0
                            </div>
                            <div class="layui-col-xs4 layui-col-md4 top-panel-tips">
                                <svg t="1688201011061" class="icon" viewBox="0 0 1024 1024" version="1.1"
                                    xmlns="http://www.w3.org/2000/svg" p-id="1411" width="200" height="200">
                                    <path
                                        d="M716.8 0H307.2C137.5488 0 0 137.5488 0 307.2v409.6c0 169.6512 137.5488 307.2 307.2 307.2h409.6c169.6512 0 307.2-137.5488 307.2-307.2V307.2c0-169.6512-137.5488-307.2-307.2-307.2z"
                                        fill="#D8F4EE" p-id="1412"></path>
                                    <path
                                        d="M691.8656 639.1296a257.4592 257.4592 0 0 1-52.736 52.736l60.928 60.928a37.2992 37.2992 0 0 0 52.736-52.736l-60.928-60.928z"
                                        fill="#75E8CD" p-id="1413"></path>
                                    <path
                                        d="M486.4 716.8a230.4 230.4 0 1 0 0-460.8 230.4 230.4 0 0 0 0 460.8z m130.9696-302.5152a16.64 16.64 0 0 1 0.3584 23.5008l-115.84 119.296a16.5376 16.5376 0 0 1-3.84 3.3792 16.64 16.64 0 0 1-22.144-3.5072l-67.328-60.5184-47.232 48.64a16.64 16.64 0 0 1-23.8336-23.168l56.32-57.984a16.6912 16.6912 0 0 1 24.8832-3.072l69.5552 62.5152 105.6-108.7232a16.6144 16.6144 0 0 1 23.5008-0.3584z"
                                        fill="#01C3A3" p-id="1414"></path>
                                    <path
                                        d="M341.257236 436.535528m-7.948259-21.87091l0 0q-7.948258-21.87091-29.819168-13.922652l0 0q-21.87091 7.948258-13.922652 29.819169l0 0q7.948258 21.87091 29.819168 13.922651l0 0q21.87091-7.948258 13.922652-29.819168Z"
                                        fill="#FFFFFF" p-id="1415"></path>
                                    <path
                                        d="M331.4432 370.7392a17.2544 17.2544 0 0 0 29.3888-3.584l5.9648-13.5168a26.112 26.112 0 0 1 14.9504-13.9264l30.1056-10.9312a15.2576 15.2576 0 0 0 8.8832-20.224 15.0272 15.0272 0 0 0-18.4576-8.6016c-47.7696 15.4368-67.0976 29.3888-73.9584 57.5232a15.6672 15.6672 0 0 0 3.1488 13.2608z"
                                        fill="#FFFFFF" p-id="1416"></path>
                                </svg>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="layui-col-xs6 layui-col-md2">
                <div class="layui-card top-panel">
                    <div class="layui-card-header">本周封禁</div>
                    <div class="layui-card-body">
                        <div class="layui-row layui-col-space5">
                            <div class="layui-col-xs8 layui-col-md8 top-panel-number" style="color: #28333E;"
                                id="value2">
                                0
                            </div>
                            <div class="layui-col-xs4 layui-col-md4 top-panel-tips">
                                <svg t="1688201051691
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

候鸟-南飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值