FRP穿透后利用脚本封禁爆破ssh的IP

发布于 2024-03-17  3 次阅读


前言

通过frp进行穿透后,ssh客户机无法感知真实的ip地址,只显示部署frpc的本地ip。所以当有人爆破我们的服务器时,无法通过客户机进行ip封禁操作。此脚本部署在frps服务器端。

1. 环境说明

系统:Debian11
防火墙:iptables
脚本环境:python3.9
frps版本:frp_0.53.2_linux_amd64

2.原理

根据frps生成的日志文件,检测连接ssh服务的ip。利用python脚本读取每一行,匹配ssh关键字。同一个IP在一段时间内多次连接ssh服务则封禁。同时将ip写进blocked_ips.txt。每次执行脚本时会读取txt检测该ip是否早已添加,防止重复添加。然后清除防火墙INPUT规则,将txt里的ip记录重新添加到防火墙进行拦截。

2024.07.15更新--IP属地检测,因爆破用的肉鸡多为国外机器,所以只封禁国外IP。

3.实现步骤

1.frps开启日志

在frps.toml配置文件里添加:


# console or real logFile path like ./frps.log
log.to = "/root/frp/frp_0.53.2_linux_amd64/frps.log"
# trace, debug, info, warn, error
log.level = "info"
#log.level = "debug"
log.maxDays = 3
# disable log colors when log.to is console, default is false
#log.disablePrintColor = false


2.编写python脚本

参数说明:
/root/frp/frp_0.53.2_linux_amd64/blocked_ips.log 为脚本的操作日志
/root/frp/frp_0.53.2_linux_amd64/frps.log 为frps的日志
/root/frp/frp_0.53.2_linux_amd64/blocked_ips.txt 为封禁ip的合集
这两行代表10分钟内5次爆破即满足封禁条件
time_interval = timedelta(minutes=10)
if info['count'] >= 5:
请按需修改。

import subprocess
from datetime import datetime, timedelta
import re
import logging
import requests

# 配置日志
logging.basicConfig(filename='/root/frp/frp_0.53.2_linux_amd64/blocked_ips.log', level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s')

# 定义时间间隔为20分钟
time_interval = timedelta(minutes=20)

# 创建一个字典用于存储IP地址和其出现次数
ip_counts = {}

# 定义一个函数获取 IP 属地信息
def get_ip_location(ip):
    try:
        response = requests.get(f'https://ipinfo.io/widget/demo/{ip}')
        if response.status_code == 200:
            data = response.json().get('data', {})
            nation = data.get('country', '')
            return nation
        else:
            logging.warning(f"Failed to get location for IP {ip}. Status code: {response.status_code}")
            return ''
    except Exception as e:
        logging.error(f"Error occurred while getting location for IP {ip}: {str(e)}")
        return ''


# 读取日志文件
with open('/root/frp/frp_0.53.2_linux_amd64/frps.log', 'r') as file:
    for line in file:
        # 使用正则表达式匹配时间戳和IP地址
        match = re.search(
            r'(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}) .* \[.*ssh.*\] get a user connection \[([\d.]+):\d+\]', line)
        if match:
            timestamp_str, ip = match.group(1), match.group(2)
            timestamp = datetime.strptime(timestamp_str, '%Y/%m/%d %H:%M:%S')

            # 检查当前行的IP地址是否已经在字典中
            if ip in ip_counts:
                # 检查时间间隔是否在20分钟内
                if timestamp - ip_counts[ip]['timestamp'] <= time_interval:
                    ip_counts[ip]['count'] += 1
                else:
                    ip_counts[ip] = {'timestamp': timestamp, 'count': 1}
            else:
                ip_counts[ip] = {'timestamp': timestamp, 'count': 1}

# 输出IP地址和其出现次数到txt文本,并封禁IP地址并记录到日志
blocked_ips_set = set()
with open('/root/frp/frp_0.53.2_linux_amd64/blocked_ips.txt', 'a+') as output_file:
    output_file.seek(0)  # 移动到文件开头
    existing_ips = output_file.read().splitlines()
    blocked_ips_set.update(existing_ips)  # 将已存在的 IP 加入集合中,避免重复写入

    for ip, info in ip_counts.items():
        if info['count'] >= 5 and ip not in blocked_ips_set:
            # 获取 IP 属地信息
            nation = get_ip_location(ip)
            if nation != 'CN' and nation != '':
                message = f'IP: {ip}, Count: {info["count"]}, Timestamp: {info["timestamp"]}, Nation: {nation}, has been recorded in blocked_ips.txt.'
                print(message)
                logging.info(message)
                # 将符合条件的 IP 写入文本
                output_file.write(ip + '\n')
                blocked_ips_set.add(ip)

# 读取txt文本内的IP并利用iptables封禁
with open('/root/frp/frp_0.53.2_linux_amd64/blocked_ips.txt', 'r') as input_file:
    blocked_ips = input_file.read().splitlines()
    for ip in blocked_ips:
        subprocess.run(['/usr/sbin/iptables', '-I', 'INPUT', '-s', ip, '-j', 'DROP'])
    message = 'All IPs in blocked_ips.txt have been blocked with iptables.'
    print(message)
    logging.info(message)

3.定时执行脚本

利用cron定时执行脚本:例如10min


crontab -e


*/10 * * * * /usr/bin/python3 /root/frp/frp_0.53.2_linux_amd64/ban_frps_ip.py

注意python路径,以及脚本路径。

4.日志分割

可以参考这篇文章进行日志分割,将blocked_ips.log按天分割

4.注意事项

frp客户端在进行配置时需要把name = ""添加上ssh关键字。例如:


[[proxies]]
name = "Ubuntu-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 122

并且重启后封禁将失效。如需永久生效需要添加额外的iptables命令。

效果截图:

希望赤诚善良的人,能被世界温柔以待
最后更新于 2025-01-17