hfish告警脚本

基于Python3写的hfish告警

由于原告警是excel文件不方便阅读,故写了个比较直观的脚本,并且当时环境是部署在gcp上的,故联动gcp接口调用防火墙黑名单 需要调用到基础接口脚本里的数据库读写和google.cloud库

from requests.packages import urllib3
import time,re,json,logging
from google.cloud import compute _v1
from google. oauth2 import service_account
from BasicInterfaces import executeMysqlData
from datetime import datetime,timedelta
def listFirewallRule(credentials,projectId):
    client = compute _v1.FirewallsClient(credentials= credentials)
    firewallRuleList = client.list(project=projectId)
    query = "blocklist"
    dataJson = {}
    ipList = []
    for firewallName in firewallRuleList:
        if query in firewallName.name:
            dataJson[firewallName.name] = len(firewallName.source_ranges)
            ipList. extend(firewallName.source_ranges)
            return dataJson,ipList
            
def addSourceIPToFirewallRule(credentials,projectId, firewallRuleName,ipaddressForAdd):
    client = compute_v1.FirewallsClient(credentials=credentials)
    firewall = client.get(project=projectId, firewall=firewallRuleName)
    firewall.source_ranges.append(ipaddressForAdd)
    try:
        operation = client.update(project=projectId, firewall=firewallRuleName,firewall_resource=firewall)
        operation.result()
    except Exception as e:
        return str(e).split()[-1]
def removeSourceIPToFirewallRule(credentials,projectId, firewallRuleName,ipaddressForAdd):
    client = compute _v1.FirewallsClient(credentials= credentials)
    firewall = client.get(project=projectId, firewall=firewallRuleName)
    firewall.source_ranges.remove(ipaddressForAdd)
    operation = client.update(project=projectId, firewall=firewallRuleName, firewall_resource= firewall)
    operation.result()
def newFirewallPolicy(credentials,projectId, firewallRuleName):
    client = compute_v1.FirewallsClient(credentials= credentials)
    firewall = {
        "denied": [{"I_p_protocol": "all"}],
        "direction": "INGRESS",
        "name": firewallRuleName,
        "network": "global/networks/ default",
        "priority": 999,
        "source_ranges": ["224.1.1.132/32"]
        }
    try:
        client.insert(project=projectId, firewall_resource = firewall)
        return True
    except Exception as e:
        return (str(e).split()[-2] + " " + str(e).split()[-1])
def isPublicIpv4(ip):
    pattern = r'^(?:(?:(?:[1-9]?\d|1\d\d|2[θ-4]\d|25[θ-5])\.){3}(?:[1-9]?\d|1\d\d|2[θ-4]\d|25[θ-5]))$'
    private_pattern = r'^(?:(?:10|127)\.\d{1,3}\.\d{1,3}\.\d{1,3}|(?:172\.(?:1[6-9]|2\d|3[01]))\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\
    return re.match(pattern, ip) is not None and re.match(private_pattern,ip) is None
def makeMaiLContext(data):
    table _ html = """
    <table style="border-collapse: collapse;">
        <tr bgcolor="aqua">
            <th style=" border: 1px solid black; padding: 8px;">扫描类型</th>
            <th style=" border: 1px solid black; padding: 8px;">来源IP</th>
            <th style=" border: 1px solid black; padding: 8px;">来源MAC</th>
            <th style=" border: 1px solid black; padding: 8px;">来源区域</th>
            <th style=" border: 1px solid black; padding: 8px;">目标IP</th>
            <th style=" border: 1px solid black; padding: 8px;">目标端口</th>
            <th style=" border: 1px solid black; padding: 8px;">扫描次数</th>
            <th style=" border: 1px solid black; padding: 8px;">开始时间</th>
            <th style=" border: 1px solid black; padding: 8px;">持续时间</th>
            <th style=" border: 1px solid black; padding: 8px;">攻击详情</th>
        </tr>
    """
    ports = ",".join(filter(None, data[3].split(",")))
    table _ html += f"""
    <tr>
        <td style=" border: 1px solid black; padding: 8px;">{data[6]}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[θ]}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[8]}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[1]}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[2]}</td>
        <td style=" border: 1px solid black; padding: 8px;">{ports}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[4]}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[7]}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[5].total_seconds()}</td>
        <td style=" border: 1px solid black; padding: 8px;">{data[9]}</td>
    </tr>
    """
    table_html += "</table>"
    return (table_html)
def beijing(sec, what):
    beijing_time = datetime.now()+ timedelta(hours=8)
    return beijing_time.timetuple()
"""蜜罐收集黑名单"""
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
logger = logging.getLogger()
logging.Formatter.converter = beijingprojectCSTId = "xxxx"
# Google Cloud项目ID
credentialsCST = service_account.Credentials.from_service_account_file('dddd.json')projectIdList = [{'projectId':projectCSTId,' credentials':credentialsCST}]
#遍历 project列表
while 1:
    logger.info('开始新一轮扫描')
    for projectInfo in projectIdList:
        firewallInfo,sourceRange = listFirewallRule(project Info['credentials'],projectInfo['projectId'])[θ],listFirewallRule(projectInfo['credentials'],projectInfo['projectId'])[1]
        for firewallName in firewallInfo:
            if firewallInfo[firewallName] < 5000:
                break
            queryScanData = "SELECT source_ip,source_ip_country,dest_ip,GROUP_CONCAT(DISTINCT dest_port),count(*) AS ipCount,TIMEDIFF(MAX(update_time),MIN(create_time)),GROUP_CONCAT(DISTINCT scan_type),create_time,source_mac,detail FROM scanners WHERE ifAlreadysent=0 GROUP BY source_ip"
            scanpata = executeMysqivata(1,' read', queryscanData)
            logger.info  ("开始扫描数据库,看是否有新的ip")
            if len(scanData) == 0:
                logger.info  ('本次扫描没有发现新的ip')
            else:
                for j in scanData:
                    logger.info (j[0])
                    if isPublicIpv4(j[0]) == True:
                        ###这边判断是否是自己的ip
                        if j[0] != 'x.x.x.x':
                            dataQuery = f"""select * from sync_ip_info where ip={"'" + j[0] + "'"}"""
                            queryDupIp = executeMysqlData(1,'read',dataQuery)
                            if len(queryDupIp) == 0:
                                resultAddIP = addSourceIPToFirewallRule(projectInfo['credentials'],projectInfo['projectId'],firewallName,j[0])
                                if resultAddIP == '5001.':
                                    logger.info  (f'防火墙规则已满,尝试创建新的规则')
                                    for i in range (1,1000):
                                        firewallRuleName = "blocklist" + str(i)
                                        resultAddPolicy = newFirewallPolicy(credentialsCST,projectCSTId,firewallRuleName)
                                        if resultAddPolicy == 'already exists':
                                            logger.info(f'防火墙{firewallRuleName}已经存在,尝试下一个。。。')
                                            i += 1
                                            else:logger.info  (f'防火墙{firewallRuleName}创建成功!')
                                            addSourceIPToFirewallRule(projectInfo['credentials'],projectInfo['projectId'],firewallName,j[0])
                                            break
                                        else:
                                            logger.info('防火墙规则写入成功')
                                            dataInsert = f"""insert into sync_ip_info(ip, sync) VALUES ({"'"+ j[0] + "'"},'honeypotserver')"""
                                            executeMysqlData(1,'write',dataInsert)
                                            logger.info("数据写入成功")
                                else:
                                    logger.info(f'该ip{j[0]}已经写入数据库!')
                            else:logger.info  (f'ip{j[0]}是公司IP,请注意检查!')
        time.sleep(60)