FRP内网穿透如何避免SSH暴力破解(二)——指定地区允许访问

news2025/5/16 0:24:34

背景

上篇文章说到,出现了试图反复通过FRP的隧道,建立外网端口到内网服务器TCP链路的机器人,同时试图暴力破解ssh。这些连接造成了流量的浪费和不必要的通信开销。考虑到服务器使用者主要分布在A、B、C地区和国家,我打算对上一篇文章获取的建立连接的ip再过滤一遍,把其他地区的ip加以封禁,确保服务器不被恶意访问骚扰。

思路

在FRP服务端写一个python程序,每个小时查询一次已连接ip的清单,只允许指定区域的ip访问内网的指定端口。本文国家/地区列表我设置为中国大陆、香港、新加坡、马来西亚、美国。

获取地区&检查是否是目标区域

# 设置允许访问地区列表
target_countries = ('China', 'Hong Kong', 'Singapore', 'Malaysia', 'United States')

def get_ip_location(ip_address):
    response = requests.get(f'https://ipapi.co/{ip_address}/json/').json()
    country_name = response.get("country_name")
    # print(country_name)
    return country_name

def check_ip_location(ip_address):
    country_name = get_ip_location(ip_address)
    if country_name in target_countries:
        # print('ok')
        return 'ok'
    else:
        return 'no'

封禁服务区域外的ip

def ban_ip(ip_address):
    # 检查IP是否已经被封禁
    if is_ip_banned(ip_address):
        print(f"IP {ip_address} is already banned.")
        return
    
    try:
        # 封禁IP地址
        subprocess.run(['sudo', 'iptables', '-A', 'INPUT', '-s', ip_address, '-j', 'DROP'], check=True)
        # 记录到文件
        with open('/home/user/ban_ip_no_cn.txt', 'a') as file:
            ban_time = datetime.datetime.now()
            unban_time = ban_time + datetime.timedelta(days=1)
            file.write(f"{ban_time}, {ip_address}, {unban_time}\n")
        print(f"IP {ip_address} has been banned.")
    except Exception as e:
        print(f"Error banning IP {ip_address}: {e}")

封禁时间限制

每天运行一次脚本ban_ip_no_cn.sh,检查是否到了解封时间。

BAN_FILE="/home/user/ban_ip_no_cn.txt"
TEMP_FILE="/tmp/temp_ban_ip_no_cn.txt"

while IFS=, read -r ban_time ip_address unban_time; do
    current_time=$(date +%Y-%m-%d' '%H:%M:%S)
    if [[ "$current_time" > "$unban_time" ]]; then
        sudo iptables -D INPUT -s $ip_address -j DROP
    else
        echo "$line" >> $TEMP_FILE
    fi
done < $BAN_FILE

mv $TEMP_FILE $BAN_FILE

定期清理连接建立记录(ip_ban_delete_old.py)

# 已建立连接ip的清单‘establishment_ip.txt’,每三天释放一次

from datetime import datetime, timedelta
import os

def delete_old_entries(file_path):
    cutoff_date = datetime.now().date() - timedelta(days=1)

    temp_file_path = file_path + ".tmp"

    with open(file_path, 'r') as read_file, open(temp_file_path, 'w') as write_file:
        for line in read_file:
            line_date_str = line.split(' ')[0]  # Extract only the date part
            line_date = datetime.strptime(line_date_str, '%Y-%m-%d').date()

            if line_date >= cutoff_date:
                write_file.write(line)

    os.replace(temp_file_path, file_path)


# Path to the establishment_ip.txt file
file_path = '/home/peter/establishment_ip.txt'
delete_old_entries(file_path)

注意

establishment_ip.txt文件的格式如下,通过ss -anp | grep ":port"(port切换为你的frps开放的port)命令获取。

2024-02-06 07:36:52.541687: Established connection from IP 203.145.18.60 on port 23
2024-02-06 07:36:52.578422: Established connection from IP 203.145.18.60 on port 23
2024-02-06 07:40:01.597133: Established connection from IP 56.101.207.179 on port 24
2024-02-06 07:40:01.597341: Established connection from IP 203.145.18.60 on port 24
2024-02-06 07:40:01.633414: Established connection from IP 203.145.18.60 on port 24
2024-02-06 07:40:36.380221: Established connection from IP 203.145.18.60 on port 24

效果:

  1. ip_ban_no_cn.log输出打印
    ip_ban_no_cn.log输出
  2. ban_ip_no_cn.txt的被封禁ip记录
    在这里插入图片描述

完整Python代码ip_ban_no_cn.py (注意修改路径)

# 每小时运行一次,从已建立连接ip的清单查询,封禁所有不欢迎ip
# 已建立连接ip的清单‘establishment_ip.txt’,每三天释放一次

import re
import requests
import subprocess
import datetime

# 更新国家列表
target_countries = ('China', 'Hong Kong', 'Singapore', 'Malaysia', 'United States')

def get_ip_location(ip_address):
    response = requests.get(f'https://ipapi.co/{ip_address}/json/').json()
    country_name = response.get("country_name")
    # print(country_name)
    return country_name

def check_ip_location(ip_address):
    country_name = get_ip_location(ip_address)
    if country_name in target_countries:
        # print('ok')
        return 'ok'
    else:
        return 'no'

def is_ip_banned(ip_address):
    try:
        with open('/home/{user}/ban_ip_no_cn.txt', 'r') as file:
            for line in file:
                if ip_address in line:
                    return True
    except FileNotFoundError:
        # 如果文件不存在,意味着没有IP被封禁
        return False
    return False

def ban_ip(ip_address):
    # 检查IP是否已经被封禁
    if is_ip_banned(ip_address):
        print(f"IP {ip_address} is already banned.")
        return
    
    try:
        # 封禁IP地址
        subprocess.run(['sudo', 'iptables', '-A', 'INPUT', '-s', ip_address, '-j', 'DROP'], check=True)
        # 记录到文件
        with open('/home/{user}/ban_ip_no_cn.txt', 'a') as file:
            ban_time = datetime.datetime.now()
            unban_time = ban_time + datetime.timedelta(days=1)
            file.write(f"{ban_time}, {ip_address}, {unban_time}\n")
        print(f"IP {ip_address} has been banned.")
    except Exception as e:
        print(f"Error banning IP {ip_address}: {e}")

def main():
    log_file_path = '/home/{user}/establishment_ip.txt'
    ip_pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
    
    current_time = datetime.datetime.now()
    
    try:
        with open(log_file_path, 'r') as file:
            for line in file:
                # 尝试解析每行的时间戳
                parts = line.split(": Established connection from IP ")
                if len(parts) > 1:
                    timestamp_str = parts[0].strip()
                    # print(timestamp_str)
                    try:
                        timestamp = datetime.datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
                        # 检查时间是否在最近2小时内
                        # print(timestamp)
                        if (current_time - timestamp) <= datetime.timedelta(hours=2):
                            search_result = ip_pattern.search(line)
                            # print((current_time - timestamp))
                            if search_result:
                                ip_address = search_result.group(0)
                                if check_ip_location(ip_address) == 'no':
                                    ban_ip(ip_address)
                    except ValueError:
                        # 如果时间戳格式不正确,跳过这一行
                        continue
    except FileNotFoundError:
        print(f"File {log_file_path} not found.")
    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == '__main__':
    main()

Crontab运行的脚本

# Run ban_ip_no_cn.sh every 24 hours and log output
0 0 * * * /home/user/ban_ip_no_cn.sh > /home/user/log_temp/ban_ip_no_cn.log 2>&1

# Run ip_ban_no_cn.py every hour and log output
0 * * * * python3 /home/user/ip_ban_no_cn.py > /home/user/log_temp/ip_ban_no_cn.log 2>&1

# Run ip_ban_delete_old.py every 24 hours and log output
0 0 * * * python3 /home/user/ip_ban_delete_old.py > /home/user/log_temp/ip_ban_delete_old.log 2>&1

总结

  • 代码写完才发现,早就有大神写了个复杂版本。呜呼哀哉,就好像论文idea被抢发了一样:https://github.com/zngw/frptables
  • ip归属地查询返回的是JSON格式,不光能查国家,还能获取到城市、语言、首都等信息。
get_location() function
As per the API documentation of ipapi, we need to make a GET request on https://ipapi.co/{ip}/{format}/ to get location information for a particular IP address. {ip} is replaced by the IP address and {format} can be replaced with any of these – json, jsonp, xml, csv, yaml.

This function internally calls the get_ip() function to get the IP address and then makes a GET request on the URL with the IP address. This API returns a JSON response that looks like this:

{
    "ip": "117.214.109.137",
    "version": "IPv4",
    "city": "Gaya",
    "region": "Bihar",
    "region_code": "BR",
    "country": "IN",
    "country_name": "India",
    "country_code": "IN",
    "country_code_iso3": "IND",
    "country_capital": "New Delhi",
    "country_tld": ".in",
    "continent_code": "AS",
    "in_eu": false,
    "postal": "823002",
    "latitude": 24.7935,
    "longitude": 85.012,
    "timezone": "Asia/Kolkata",
    "utc_offset": "+0530",
    "country_calling_code": "+91",
    "currency": "INR",
    "currency_name": "Rupee",
    "languages": "en-IN,hi,bn,te,mr,ta,ur,gu,kn,ml,or,pa,as,bh,sat,ks,ne,sd,kok,doi,mni,sit,sa,fr,lus,inc",
    "country_area": 3287590,
    "country_population": 1352617328,
    "asn": "AS9829",
    "org": "National Internet Backbone"
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1445996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

万维网的文档

目录 1 万维网的文档 动态万维网文档 CGI CGI 网关程序 活动万维网文档 用 Java 语言创建活动文档 1 万维网的文档 分为&#xff1a; 静态万维网文档。内容不会改变。简单。(html、xml、css) 动态万维网文档。文档的内容由应用程序动态创建。 活动万维网文档。由浏览器端…

npm config set registry https://registry.npm.taobao.org 这个设置了默认的镜像源之后如何恢复默认的镜像源

要恢复npm默认的镜像源&#xff0c;你可以使用以下命令将registry设置回npm的官方源&#xff1a; npm config set registry https://registry.npmjs.org/这个命令会修改你的全局npm配置&#xff0c;将包的下载源改回npm官方的源。这样做之后&#xff0c;任何后续的npm install…

【二叉树】层序遍历

目录 层序遍历概念&结构 层序遍历的实现 整体思路 代码实现 图示理解 BT升级 整体思路 代码实现 图示理解​ 应用 题目 前序&中序&后序遍历&#xff1a;深度优先遍历dfs 层序遍历&#xff1a;广度优先遍历bfs 层序遍历概念&结构 层序遍历&#xf…

【java语言基础⑥】面向对象——面向对象的思想、类与对象

1.学习目标 了解面向对象的思想&#xff0c;能够说出面向对象的三个特性掌握类的定义&#xff0c;能够独立完成类的定义掌握对象的创建和使用&#xff0c;能够完成对象创建&#xff0c;用对象访问对象属性和方法掌握对象的引用传递&#xff0c;能够独立实现对象的引用传递熟悉…

力扣_字符串6—最小覆盖字串

题目 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 “” 。 示例 &#xff1a; 输入&#xff1a;s “ADOBECODEBANC”, t “ABC” 输出&#xff1a;“BANC” 解释&#xff1a;…

Java安全 URLDNS链分析

Java安全 URLDNS链分析 什么是URLDNS链URLDNS链分析调用链路HashMap类分析URL类分析 exp编写思路整理初步expexp改进最终exp 什么是URLDNS链 URLDNS链是Java安全中比较简单的一条利用链&#xff0c;无需使用任何第三方库&#xff0c;全依靠Java内置的一些类实现&#xff0c;但…

mxxWechatBot主动发送消息至微信

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 免责声明&#xff1a;该工具仅供学习使用&#xff0c;禁止使用该工具从事违法活动&#xff0c;否则永久拉黑封禁账号&#xff01;&#xff01;&#xff01;本人不对任何工具的使用负责&am…

【Git版本控制 05】多人协作

目录 一、邀请开发用户 二、新建远程分支 三、拉取远程分支 四、推送远程分支 五、合并远程分支 六、多分支协作 一、邀请开发用户 在windows环境下&#xff0c;再clone同⼀个项⽬仓库&#xff0c;来模拟⼀起协作开发的另⼀名⼩伙伴。 际开发中&#xff0c;每个⽤⼾都有…

【Web】超级详细的Linux权限提升一站式笔记

目录 一、Linux内核提权 提权原理 提权环境 提权复现 二、SUID提权 SUID介绍 设置SUID SUID提权原理 查找SUID文件 提权介绍 find提权 bash提权 vim提权 python提权 三、计划任务提权 提权原理 提权环境 提权步骤 四、环境变量劫持提权 提权原理 提权环境…

【机器学习】卷积和反向传播

一、说明 自从 AlexNet 在 2012 年赢得 ImageNet 竞赛以来&#xff0c;卷积神经网络 (CNN) 就变得无处不在。从不起眼的 LeNet 到 ResNets 再到 DenseNets&#xff0c;CNN 无处不在。 您是否想知道 CNN 的反向传播中会发生什么&#xff0c;特别是反向传播在 CNN 中的工作原理。…

【知识整理】技术新人的培养计划

一、培养计划落地实操 1. 概要 新人入职&#xff0c;要给予适当的指导&#xff0c;目标&#xff1a; 1、熟悉当前环境&#xff1a; 生活环境&#xff1a;吃饭、交通、住宿、娱乐 工作环境&#xff1a;使用的工具&#xff0c;Mac、maven、git、idea 等 2、熟悉并掌握工作技…

Android---Jetpack Compose学习003

Compose 状态。本文将探索如何在使用 Jetpack Compose 时使用和考虑状态&#xff0c;为此&#xff0c;我们需要构建一个 TODO 应用&#xff0c;我们将构建一个有状态界面&#xff0c;其中会显示可修改的互动式 TODO 列表。 状态的定义。在科学技术中&#xff0c;指物质系统所处…

【C深度解剖】前置++与后置++

简介&#xff1a;本系列博客为C深度解剖系列内容&#xff0c;以某个点为中心进行相关详细拓展 适宜人群&#xff1a;已大体了解C语法同学 作者留言&#xff1a;本博客相关内容如需转载请注明出处&#xff0c;本人学疏才浅&#xff0c;难免存在些许错误&#xff0c;望留言指正 作…

相机图像质量研究(12)常见问题总结:光学结构对成像的影响--炫光

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

关于Navicat导入sql文件后er图乱序问题

关于Navicat导入sql文件后er图乱序问题 具体操作如下&#xff1a; 点击左下角刷新旁边的小三角

涤生大数据实战:基于Flink+ODPS历史累计计算项目分析与优化(上)

涤生大数据实战&#xff1a;基于FlinkODPS历史累计计算项目分析与优化&#xff08;一&#xff09; 1.前置知识 ODPS&#xff08;Open Data Platform and Service&#xff09;是阿里云自研的一体化大数据计算平台和数据仓库产品&#xff0c;在集团内部离线作为离线数据处理和存…

数据结构(3) 顺序表存储结构

顺序表存储结构 存储结构顺序结构定义基本操作的实现静态分配问题 动态分配代码功能 顺序表的特点: 顺序表小结顺序表的插入删除插入删除小结 顺序表的查找按位查找按值查找小结 各位小伙伴想要博客相关资料的话关注公众号&#xff1a;chuanyeTry即可领取相关资料&#xff01; …

Codeforces Round 924 E. Modular Sequence

E. Modular Sequence 题意 对于一个长度为 n n n 的数组 a a a&#xff0c;定义它是 g o o d good good 的当且仅当&#xff1a; a 1 x a_1 x a1​x a i a i − 1 y a_{i} a_{i - 1} y ai​ai−1​y 或 a i a i − 1 m o d y i ≥ 2 a_{i} a_{i - 1} mod \hspace{…

【Linux】内核中的链表

&#x1f525;博客主页&#xff1a;PannLZ &#x1f38b;系列专栏&#xff1a;《Linux系统之路》 &#x1f94a;不要让自己再留有遗憾&#xff0c;加油吧&#xff01; 文章目录 链表1.创建和初始化2.创建节点3.添加节点4.删除节点5.遍历 链表 内核开发者只实现了循环双链表&am…

nodejs学习计划--(十)会话控制及https补充

一、会话控制 1.介绍 所谓会话控制就是 对会话进行控制 HTTP 是一种无状态的协议&#xff0c;它没有办法区分多次的请求是否来自于同一个客户端&#xff0c; 无法区分用户 而产品中又大量存在的这样的需求&#xff0c;所以我们需要通过 会话控制 来解决该问题 常见的会话控制…