小伙伴们都知道宝塔Nginx免费防火墙挺好用的哈。唯一的就是IP地址没有归属地,总感觉有些不舒服。幸运的小编做AI即时通讯聊天室有提供这个IP物理地址的接口的哈,废话不多说下面进入主题。找到(/www/server/panel/plugin/free_waf/free_waf_main.py)这个文件
给这个类增加一个IP归属地显示的方法。代码如下(17行下面):
def getIpLocation(self, ip):
url = f"https://www.wenyunfang.com/e/extend/chat/info.php?enews=ipcha&ip={ip}"
try:
response = requests.get(url)
if response.status_code == 200:
data = response.json()
if data["code"] == 1:
location = data["ip2"]
return location
else:
return "查询失败,错误代码: " + str(data["code"])
else:
return f"请求失败,状态码: {response.status_code}"
那我们在日志获取方法的类新增IP归属地显示。仍然是这个文件。(get_safe_logs)为方法,直接贴方法了哈
def get_safe_logs(self, get):
try:
import cgi
pythonV = sys.version_info[0]
if 'drop_ip' in get:
path = '/www/server/free_waf/drop_ip.log'
num = 14
else:
path = '/www/wwwlogs/free_waf_log/' + get.siteName + '_' + get.toDate + '.log'
num = 10
if not os.path.exists(path): return []
p = 1
if 'p' in get:
p = int(get.p)
start_line = (p - 1) * num
count = start_line + num
fp = open(path, 'rb')
buf = ""
try:
fp.seek(-1, 2)
except:
return []
if fp.read(1) == "\n": fp.seek(-1, 2)
data = []
b = True
n = 0
c = 0
while c < count:
while True:
newline_pos = str.rfind(buf, "\n")
pos = fp.tell()
if newline_pos != -1:
if n >= start_line:
line = buf[newline_pos + 1:]
if line:
try:
tmp_data = json.loads(cgi.escape(line))
for i in range(len(tmp_data)):
if i == 7:
tmp_data[i] = str(tmp_data[i]).replace('&', '&').replace('<',
'<').replace(
'>', '>')
else:
tmp_data[i] = cgi.escape(str(tmp_data[i]), True)
ip = tmp_data[1]
ip_location = self.getIpLocation(ip)
tmp_data.append(ip_location)
data.append(tmp_data)
except:
c -= 1
n -= 1
pass
else:
c -= 1
n -= 1
buf = buf[:newline_pos]
n += 1
c += 1
break
else:
if pos == 0:
b = False
break
to_read = min(4096, pos)
fp.seek(-to_read, 1)
t_buf = fp.read(to_read)
if pythonV == 3: t_buf = t_buf.decode('utf-8', errors="ignore")
buf = t_buf + buf
fp.seek(-to_read, 1)
if pos - to_read == 0:
buf = "\n" + buf
if not b: break
fp.close()
if 'drop_ip' in get:
drop_iplist = self.get_waf_drop_ip(None)
stime = time.time()
setss = []
for i in range(len(data)):
if (float(stime) - float(data[i][0])) < float(data[i][4]) and not data[i][1] in setss:
setss.append(data[i][1])
data[i].append(data[i][1] in drop_iplist)
else:
data[i].append(False)
except:
return public.get_error_info()
data = []
return data
全部修改完成,因为小编没有办法访问下载City.mmdb,所以也只能用文韵坊阅读网IP归属地接口。能下载的改下那个IP归属地的方法即可。效果图如下:
看到了吧。是不是日志输出的JSON里面有IP归属地物理地址了。至于怎么渲染出来,自行修改/www/server/panel/plugin/free_waf/index.html 里面那段render_site_logs,比如小编的
// 渲染站点日志
render_site_logs: function (obj, callback) {
var _this = this;
this.get_safe_logs({ siteName: obj.siteName, toDate: obj.toDate, p: obj.p }, async function (res) {
_this.refresh_table_view({
el: '#site_logs_table',
form_id: 'site_logs_table', // 用于重置
config: [
{ fid: '0', width: '150px', title: '时间' },
{ fid: '1', title: '用户 IP', tips: true, width: '120px', type: 'link',
templet: function (row, index) {
var ip = row[1];
var ipLocation = row[8];
return '<a class="btlink add_log_ip_black" title="' + _this.escapeHTML(ipLocation) + '" data-cityip="' + _this.escapeHTML(ipLocation) + '" data-ip="' + _this.escapeHTML(ip) + '" >' + _this.escapeHTML(ip) + '</a>';
}
},
{ fid: '2', title: '类型' },
{ fid: '3', title: 'URL 地址', templet: function (row, index) { return '<span title="' + _this.escapeHTML(row[3]) + '">' + _this.escapeHTML(row[3]) + '</span>' } },
{ title: '状态', templet: function (row, index) { return '已拦截'; } },
{ fid: '5', title: '过滤器', tips: true, width: '80px' },
{ fid: 'tools', title: '操作', width: '125px', style: 'text-align: right;', group: [
{
title: '误报',
event: function (row, index) {
layer.confirm('是否确定提交误报反馈?', { title: '误报反馈', closeBtn: 2, icon: 3 }, function () {
var rule_arry = row[6].split(" >> ");
_this.add_url_white({ url_rule: row[3] }, function (res) {
layer.msg(res.msg, { icon: 1 });
if (rule_arry[1] != undefined) { $.get('https://www.bt.cn/Api/add_waf_logs?data='; + rule_arry[1], function (rdata) { }, 'jsonp') }
});
});
}
},
{
title: '详细',
event: function (row, index) {
var filter_rule = '', rule_arry = row[6].split(" &gt;&gt; "), incoming_value = '', risk_value = '';
if (rule_arry.length == 0) filter_rule = rule_arry[0]
incoming_value = rule_arry[1] == undefined? '空' : rule_arry[1];
risk_value = incoming_value.match(new RegExp(rule_arry[0].replace(/\//g, '\\/'), 'i'));
risk_value = risk_value? risk_value[0] : '空';
layer.open({
type: 1,
title: "【" + row[0] + "】详情",
area: '600px',
closeBtn: 2,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
<tbody><tr><th>时间</th><td>' + _this.escapeHTML(row[0]) + '</td><th>用户 IP</th><td><a class="btlink add_log_ip_black" title="加入黑名单">' + _this.escapeHTML(row[1]) + '</a></td><th>类型</th><td>' + _this.escapeHTML(row[2]) + '</td></tr><tr><th>过滤器</th><td>' + _this.escapeHTML(row[5]) + '</td><th>IP归属地</th><td>' + _this.escapeHTML(row[8]) + '</td><th></th><td></td></tr></tbody></table>\
<div><b style="margin-left:10px">URI 地址</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">' + _this.escapeHTML(row[3]) + '</div></div>\
<div><b style="margin-left:10px">User-Agent</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">' + _this.escapeHTML(row[4]) + '</div></div>\
<div><b style="margin-left:10px">过滤规则</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">' + _this.escapeHTML(rule_arry[0]) + '</div></div>\
<div><b style="margin-left:10px">传入值</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">' + _this.escapeHTML(incoming_value) + '</div></div>\
<div><b style="margin-left:10px">风险值</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">' + _this.escapeHTML(risk_value) + '</div></div>\
</div>',
success: function () {
$('.add_log_ip_black').click(function () {
layer.confirm('是否将 <span style="color:red">' + row[1] + '</span> 添加到 IP 黑名单?', { title: '加入 IP 黑名单', closeBtn: 2 }, function () {
_this.add_ip_black({ start_ip: row[1], end_ip: row[1] }, function (res) {
layer.msg(res.msg, { icon: res.status? 1 : 2 });
});
});
});
}
})
}
},
{
title: 'HTTP',
event: function (row, index) {
var _http_info = row[7];
if (_http_info) {
layer.open({
type: 1,
title: "【" + row[0] + "】HTTP 详情",
area: ['800px', '500px'],
closeBtn: 1,
shadeClose: false,
maxmin: true,
content: '<div class="pd15 lib-box" style="height:100%">\
<pre id="http_info_data" style="height:100%"></pre></div>',
success: function (layers) {
$('#http_info_data').text(_http_info);
$(layers).css('top', ($(window).height() - $(layers).height()) / 2);
}
})
} else {
layer.msg('暂无 HTTP 详情信息', { icon: 6 })
}
}
}
] }
],
data: res,
done: function (res) {
$('.site_logs_page').html(_this.render_logs_pages(9, obj.p, res.length));
$('.site_logs_page a').unbind().click(function (e) {
var _page = parseInt($(this).attr('data-page'));
_this.render_site_logs({ siteName: obj.siteName, toDate: obj.toDate, p: _page });
});
// 使用事件委托绑定点击事件
$('#site_logs_table').on('click', '.add_log_ip_black', function () {
var ip = $(this).data('ip');var cityip = $(this).data('cityip');
layer.confirm('是否将 <span style="color:red">' + ip + '</span> 添加到 IP 黑名单?<br>来自:' + cityip + '', { title: '加入 IP 黑名单', closeBtn: 2, icon: 0 }, function () {
_this.add_ip_black({ start_ip: ip, end_ip: ip }, function (res) {
layer.msg(res.msg, { icon: res.status? 1 : 2 });
});
});
});
}
});
});
},
// 渲染封锁历史列表
render_history_data:function(obj,callback){
var _this = this;
if(obj == undefined) obj={p:1}
this.get_safe_logs_ip({p:obj.p},function(res){
_this.refresh_table_view({
el:'#history_table',
form_id:'history_table', //用于重置
config:[
{fid:'0',title:'开始时间',type:'link',templet:function(res){return bt.format_data(res[0])}},
{fid:'1',title:'IP',templet:function(row,index){
return row[7]?'<a href="javascript:;" class="btlink uncover_ip" title="解封当前IP('+row[1]+':'+ row[6] +')" data-ip="'+ row[1] +'">'+ row[1] +'</a>':'<span title="' + row[6] + '">' + row[1] + '</span>';
}},
{fid:'2',title:'站点'},
{fid:'3',title:'封锁原因',templet:function(row,index){
return row[5] === 'cc'?'CC攻击':'多次恶意请求';
}},
{fid:'4',title:'封锁时长',templet:function(row,index){
return row[4] + '秒';
}},
{fid:'5',title:'状态',style:'text-align: right;',templet:function(row,index){
return row[7]?'<span style="color:red">封锁中</span>':'已解封';
}}
],
data:res,
done:function(res){
// 解封所有封锁
$('.uncover_ip').click(function(){
var _ip = $(this).attr('data-ip');
var _cityip = $(this).attr('data-cityip');
layer.confirm('是否要从防火墙解封IP【'+ _ip +':'+ _cityip +'】', { title: '解封IP地址',closeBtn:2,icon:0}, function () {
_this.remove_waf_drop_ip({ip:_ip},function(res){
_this.render_history_data();
layer.msg(res.msg,{icon:res.status?1:2});
});
});
});
$('.history_uncover_page').html(_this.render_logs_pages(10,obj.p,res.length));
$('.history_uncover_page a').unbind().click(function(e){
var _page = parseInt($(this).attr('data-page'));
_this.render_history_data({p:_page});
});
if(callback) callback(res)
}
})
});
},
既然小编都提到宝塔Nginx免费防火墙了,那就把小编屏蔽的垃圾爬虫规则也说下吧。User-Agent过滤(通常用于过滤浏览器、蜘蛛及一些自动扫描器)
(Amazonbot|GPTBot|CheckMarkNetwork|Synapse|Nimbostratus-Bot|Dark|scraper|LMAO|Hakai|Gemini|Wappalyzer|masscan|crawler4j|Mappy|Center|eright|aiohttp|MauiBot|Crawler|researchscan|Dispatch|AlphaBot|Census|ips-agent|NetcraftSurveyAgent|ToutiaoSpider|EasyHttp|Iframely|sysscan|fasthttp|muhstik|DeuSu|mstshash|HTTP_Request|ExtLink***ot|package|SafeDN***ot|CPython|SiteExplorer|SSH|MegaIndex|BUbiNG|CCBot|NetTrack|Digincore|aiHitBot|SurdotlyBot|null|SemrushBot|Test|Copied|ltx71|Nmap|DotBot|Ad***ot|InetURL|Pcore-HTTP|PocketParser|Wotbox|newspaper|DnyzBot|redback|PiplBot|SMTBot|WinHTTP|Auto Spider 1.0|GrabNet|TurnitinBot|Go-Ahead-Got-It|Download Demon|Go!Zilla|GetWeb!|GetRight|libwww-perl|Cliqzbot|MailChimp|SMTBot|Dataprovider|XoviBot|linkdexbot|SeznamBot|Qwantify|spbot|evc-batch|zgrab|Go-http-client|FeedDemon|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|Ahref***ot|CrawlDaddy|CoolpadWebkit|Java|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|YisouSpider|HttpClient|MJ12bot|EasouSpider|LinkpadBot|Ezooms|ClaudeBot)
《让宝塔Nginx免费防火墙显示IP归属地城市名》首发文韵坊阅读网,推荐你来看看,原文地址: https://www.wenyunfang.com/zazhi/zhongwangjiaocheng/1273.html