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

背景

上篇文章说到,出现了试图反复通过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_namedef 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.")returntry:# 封禁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; docurrent_time=$(date +%Y-%m-%d' '%H:%M:%S)if [[ "$current_time" > "$unban_time" ]]; thensudo iptables -D INPUT -s $ip_address -j DROPelseecho "$line" >> $TEMP_FILEfi
done < $BAN_FILEmv $TEMP_FILE $BAN_FILE

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

# 已建立连接ip的清单‘establishment_ip.txt’,每三天释放一次from datetime import datetime, timedelta
import osdef 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 partline_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_namedef 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 Trueexcept FileNotFoundError:# 如果文件不存在,意味着没有IP被封禁return Falsereturn Falsedef ban_ip(ip_address):# 检查IP是否已经被封禁if is_ip_banned(ip_address):print(f"IP {ip_address} is already banned.")returntry:# 封禁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:# 如果时间戳格式不正确,跳过这一行continueexcept 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.mzph.cn/news/670829.shtml

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

相关文章

ELAdmin 前端启动

开发工具 官方指导的是使用WebStorm&#xff0c;但是本人后端开发一枚&#xff0c;最终还是继续使用了 idea&#xff0c;主打一个能用就行。 idea正式版激活方式&#xff1a; 访问这个查找可用链接&#xff1a;https://3.jetbra.in/进入任意一个能用的里面&#xff0c;顶部提…

消息中间件之RocketMQ源码分析(六)

Consumer消费方式 RocketMQ的消费方式包含Pull和Push两种 Pull方式。 用户主动Pull消息&#xff0c;自主管理位点&#xff0c;可以灵活地掌控消费进度和消费速度&#xff0c;适合流计算、消费特别耗时等特殊的消费场景。 缺点也显而易见&#xff0c;需要从代码层面精准地控制…

docker部署自己的网站wordpress

目录 安装 1.创建目录 2.创建并启动mysql 3.创建并启动wordpress 使用 1.设置语言 2.设置基础信息 3.首页 安装 1.创建目录 mkdir -p /opt/wordpress/{db,data} 2.创建并启动mysql docker run -d --name my_mysql --restart always -e MYSQL_ROOT_PASSWORD123456 -e …

flutter使用qr_code_scanner扫描二维码

qr_code_scanner仓库地址&#xff1a;qr_code_scanner | Flutter Package 需要添加android和ios的相机权限和本地相册权限&#xff1a; android中添加权限: 在android\app\build.gradle中修改&#xff1a;minSdkVersion 20 并且在android/app/src/main/AndroidManifest.xml中…

【力扣】Z字形变换,模拟+直接构造

Z字形变换原题地址 方法一&#xff1a;利用二维矩阵模拟 对于特殊情况&#xff0c;z字形变换后只有一行或只有一列&#xff0c;则变换后的字符串和原字符串相同。 对于一般情况&#xff0c;我们可以考虑按照题目要求&#xff0c;把字符串按照Z字形存储到二维数组中&#xff…

【linux】git和gdb调试工具

在linux下提交代码同步到gitee 1.创建一个新的仓库&#xff08;演示步骤&#xff09; 2.init 这两个步骤用于识别提交代码的身份&#xff0c;一个你的名字&#xff0c;一个你的邮箱 开启本地仓库 克隆本地仓库成功 我们将这个仓库拷到了111目录底下. 我们发现少了一个.gitig…

最小覆盖子串[困难]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串&#xff0c;则返回空字符串"" 。 对于t中重复字符&#xff0c;我们寻找的子字符串中该字符数量必须不少于t中该字符数量…

使用Nginx搭建旁路服务器获取客户端真实IP

一、前言 在实际业务开发过程中&#xff0c;很多时候有记录客户端真实IP的需求&#xff0c;但是从客户端发送的请求往往会经过很多代理服务器&#xff0c;导致后端服务获取的IP为代理以后的IP&#xff0c;不具有业务含义。为了解决这个问题&#xff0c;可以搭建一个旁路服务器…

谷歌seo搜索引擎优化方法有什么?

想知道谷歌优化方法有什么&#xff0c;首先要了解谷歌搜索引擎的工作原理&#xff0c;谷歌的工作原理主要是通过“爬虫”来实现的&#xff0c;所谓“爬虫”就是一只能够读取并分析网页内容的程序&#xff0c;或者也能理解成机器人&#xff0c;当你在谷歌上输入关键词进行搜索时…

uniapp小程序实现直播组件live-player全屏问题

实现效果&#xff1a; 代码&#xff1a; <template><view class"player-content"><!-- #ifdef APP-PLUS --><video id"myVideo" :src"srcLink" autoplay controls><!-- 打开全屏 --><image class"img…

速度规划:s形曲线------pencv c++绘图(1)

理论篇 代码篇&#xff1a; opencv环境配置 注意&#xff01;注意&#xff01;注意&#xff01; 配置结束后运行环境切换为如下再运行&#xff1a; #include <iostream> #include <cmath>#include <opencv2/opencv.hpp>using namespace std;double a_max…

github和gitee

github GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持Git作为唯一的版本库格式进行托管&#xff0c;故名GitHub。 github可以给提交的代码打上标签&#xff0c;方便版本的迭代和回退&#xff0c;也是一个存储代码的仓库 github工作区 gitee是gitHub的…

蓝桥杯---分小组

9名运动员参加比赛,需要分3组进行预赛. 有哪些分组的方案呢? 我们标记运动员为 A,B,C .... I 下面的程序列出了所有的分组方法。 该程序的正常输出为:

【CSS】margin塌陷和margin合并及其解决方案

【CSS】margin塌陷和margin合并及其解决方案 一、解决margin塌陷的问题二、避免外边距margin重叠&#xff08;margin合并&#xff09; 一、解决margin塌陷的问题 问题&#xff1a;当父元素包裹着一个子元素且父元素没有边框的时候&#xff0c;当给子元素设置margin-top:100px&…

【精选】java继承进阶——继承的特点 this、super

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

5 款提升 UI 设计效率的软件工具

你知道如何选择正确的UI设计软件吗&#xff1f;你知道设计漂亮的用户界面和带来良好用户体验的应用程序需要什么界面设计软件吗&#xff1f;基于APP界面的不同功能&#xff0c;所选择的APP界面设计软件也会有所不同。然而&#xff0c;并不是说所有的APP界面设计软件都非常精通&…

Leetcode02.05:链表求和

一、题目描述 给定两个用链表表示的整数&#xff0c;每个节点包含一个数位。 这些数位是反向存放的&#xff0c;也就是个位排在链表首部。 编写函数对这两个整数求和&#xff0c;并用链表形式返回结果。 示例&#xff1a; 输入&#xff1a;(7 -> 1 -> 6) (5 -> 9 -…

【C语言】贪吃蛇 详解

该项目需要的技术要点 C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32API等。 由于篇幅限制 和 使知识模块化&#xff0c; 若想了解 使用到的 Win32API 的知识&#xff1a;请点击跳转&#xff1a;【Win32API】贪吃蛇会使用到的 Win32API 目录 1. 贪吃蛇游…

HTTP相关问题

目录 1.从输入URL到页面展示到底发生了什么&#xff1f; 2.HTTP状态码有哪些&#xff1f; 2.1 2XX(成功状态码) 2.2 3XX(重定向状态码) 2.3 4XX(客户端错误状态码) 2.4 5XX(服务端错误状态码) 3.HTTP 请求头中常见的字段有哪些&#xff1f; 4.HTTP和HTTPS有什么区别&…

vue3-内置组件-Transition

基于状态变化的过渡和动画&#xff08;常用&#xff09; 建议多看几遍~~。然后动手去写写&#xff0c;学编程只有多动手才能有感觉。 内置组件: 它在任意别的组件中都可以被使用&#xff0c;无需注册。 Vue 提供了两个内置组件&#xff0c;可以帮助你制作基于状态变化的过渡和动…