使用python让你的远程桌面更安全【防火墙自动拉黑多次远程登录失败的ip】

查看 84|回复 9
作者:Light紫星   
朋友最近申请了公网ip,但是发现被人频繁尝试登录,于是我想起来之前另一个朋友弄过自动拉黑ip的,问了他一下是通过python和计划任务的触发器实现的,于是请教gpt,写了个脚本实现了相关操作
代码如下,实现的效果就是在几分钟内尝试登录多少次,就会自动封禁ip,24小时后解除(这个解除是触发器触发的时候进行检测的,所以只有下次登录的时候触发一下才能解除)
然后搜索 计划任务程序
创建一个计划任务,
在触发器里可以手动编辑xml,输入如下内容,可以根据你自己的需求来定义,
然后安装python,在操作里面选择启动程序,启动python如C:\Python39\python.exe ,添加参数如 D:\zixing\safe\secwall.py ,起始于如 D:\zixing\safe
其他配置根据你的需求来,然后就可以测试一下远程连接失败N次后是否会被防火墙屏蔽(当然前提是开了防火墙才可以)
[Asm] 纯文本查看 复制代码
  
    *[System[(Level=1  or Level=2 or Level=3 or Level=4 or Level=0 or Level=5) and (EventID=4625)]]
  
[Python] 纯文本查看 复制代码import subprocess
import re
from datetime import datetime, timedelta
import json
import os
LOG_FILE = "ip_attempts.json"
BLOCK_RULES_FILE = "blocked_ips.json"
MAX_ATTEMPTS = 3
TIME_WINDOW_MINUTES = 3
def load_json(file):
    if os.path.exists(file):
        with open(file, "r") as f:
            return json.load(f)
    return {}
def save_json(data, file):
    with open(file, "w") as f:
        json.dump(data, f)
def get_failed_login_events():
    command = 'wevtutil qe Security "/q:*[System[EventID=4625]]" /rd:true /f:text'
    try:
        output = subprocess.check_output(command, shell=True).decode(
            "gbk", errors="ignore"
        )
    except subprocess.CalledProcessError as e:
        print(f"Error reading event log: {e}")
        return []
    return output.split("\n\n")
def parse_event(event):
    ip_pattern = re.compile(r"源网络地址:\s+(?P\d+\.\d+\.\d+\.\d+)")
    time_pattern = re.compile(r"Date:\s+(?P[\d\-T:.]+)\d*Z")
    ip_match = ip_pattern.search(event)
    time_match = time_pattern.search(event)
    if ip_match and time_match:
        ip = ip_match.group("ip")
        event_time = time_match.group("datetime")
        event_time = event_time[:23]  # 截取前23个字符(YYYY-MM-DDTHH:MM:SS.sss)
        event_time = datetime.fromisoformat(event_time)
        return ip, event_time
    return None, None
def block_ip(ip, blocked_ips):
    rule_name = f"Block {ip} for 24 hours"
    command = f'netsh advfirewall firewall add rule name="{rule_name}" dir=in action=block remoteip={ip} enable=yes'
    try:
        subprocess.check_call(command, shell=True)
        expire_time = (datetime.now() + timedelta(hours=24)).isoformat()
        blocked_ips[ip] = expire_time
        print(f"IP {ip} 被阻止到 {expire_time}")
    except subprocess.CalledProcessError as e:
        print(f"Error blocking IP {ip}: {e}")
def remove_expired_blocks(blocked_ips):
    now = datetime.now()
    for ip, expire_time in list(blocked_ips.items()):
        if datetime.fromisoformat(expire_time)  cutoff_time
        ]
        if not ip_attempts[ip]:
            del ip_attempts[ip]
def main():
    ip_attempts = load_json(LOG_FILE)
    blocked_ips = load_json(BLOCK_RULES_FILE)
    events = get_failed_login_events()
    for event in events:
        ip, event_time = parse_event(event)
        if ip and event_time:
            if ip not in ip_attempts:
                ip_attempts[ip] = []
            if(event_time.isoformat() not in ip_attempts[ip]):
                ip_attempts[ip].append(event_time.isoformat())
    remove_old_attempts(ip_attempts)
    remove_expired_blocks(blocked_ips)
    to_block = []
    for ip, attempts in ip_attempts.items():
        if len(attempts) >= MAX_ATTEMPTS:
            to_block.append(ip)
        else:
            print(f"IP {ip} 尝试次数: {len(attempts)}")
    for ip in to_block:
        if ip not in blocked_ips:
            block_ip(ip, blocked_ips)
        del ip_attempts[ip]
    save_json(ip_attempts, LOG_FILE)
    save_json(blocked_ips, BLOCK_RULES_FILE)
if __name__ == "__main__":
    main()

secwall.zip
(1.49 KB, 下载次数: 27)
2024-10-10 14:20 上传
点击文件名下载附件
下载积分: 吾爱币 -1 CB

防火墙, 触发器

zunmx   

实际上也是通过读取windows日志的,我以前写过一个类似的脚本,只是没有添加防火墙,部分代码附上。
[Python] 纯文本查看 复制代码import win32evtlog
import win32evtlogutil
import re
mapping = {4648: "试图使用显式凭据登录。", 4624: "已成功登录帐户。", 4625: "帐户登录失败。"}
def extract_info(msg, event_time, eventid):
    ip_pattern = r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b'
    ips = re.findall(ip_pattern, msg)
    if len(ips) > 0:
        if eventid in mapping:
            print(event_time, ips, mapping[eventid])
        else:
            print(event_time, ips, eventid)
def ReadLog(logType="Application"):
    py_handle = win32evtlog.OpenEventLog(None, logType)  # 打开日志文件
    numRecords = win32evtlog.GetNumberOfEventLogRecords(py_handle)  # 日志记录的数量
    while True:
        data_list = win32evtlog.ReadEventLog(py_handle,
                                             win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ,
                                             0)
        if not data_list:
            break
        for i in data_list:
            eventid = i.EventID & 0xFFFF  # 事件ID
            if eventid not in mapping.keys(): continue
            msg = win32evtlogutil.SafeFormatMessage(i, logType)  # 日志内容
            win32evtlogutil.FormatMessage(i, logType)
            event_time = i.TimeWritten  # 日志事件事件
            extract_info(msg.strip(), event_time, eventid)
            # print(eventid, msg.strip(), event_time)
    print("TOTAL", numRecords)
    win32evtlog.CloseEventLog(py_handle)  # 关闭句柄
ReadLog("Security")
input()
可以稍微改造一下添加防火墙规则方法。
wasm2023   

感谢分享,学到了
Xiaosesi   

感谢分享,省下买厂商增值服务的预算
TOM小刚   

感谢分享,学到了
次森非彼森   

有没有linux 的脚本
zunmx   


次森非彼森 发表于 2024-10-10 16:58
有没有linux 的脚本

linux的话, 你要说的应该是SSH或者是vnc吧,你可以试试fail2ban, 配置好规则,根据日志banip
ABCDWWWc123   

感谢楼主分享的脚步,拉黑ip方便
yunhang   

感觉可以直接白名单机制,最方便了 或者改个登陆端口
a147888123   

何必搞的这么复杂呢,你不如改成更好的方案,就是任何人都是黑名单,只有你自己的IP访问的时候提前把你的IP写到防火墙白名单,让你远程连接,用完后删除你刚才用过的IP,保证谁也连不上,怎么让服务器知道你自己许可的IP去连接了服务器呢,脑洞大开点,可以解决的
这个方案我用了很久了,真好用,我用在自己一个系统上,可惜我们单位天天说要搞网络安全,对我这个方案不敢兴趣
您需要登录后才可以回帖 登录 | 立即注册

返回顶部