当我遇到了爬虫
运维同学,线上机器怎么又双叒叕挂了?
对爬虫也是相爱相杀多年,我对线上爬虫的应对出现的几个阶段:
思路:
1、看日志
分析日志,找出异常请求,封ip。
2、看waf
通过waf,针对某个uri ,进行限流(并且人机识别),控制的还是源ip,起初有点成效。
3、nginx限制
遇到大量单ip,触发不到人机识别,通过nginx自带的limit_req_zone进行uri限制,发现有效果,但是会误杀很多无辜。
map $request_uri $xx_limit {
"~*/xxx/" "/xxx/";
default "";
}
limit_req_zone $xx_limit zone=api_limit:10m rate=5r/s;
当请求路径包含/xxx/时,设置$xx_limit 为/xxx/,默认值为空,为空则limit_req_zone 不生效
limit_req zone=api_limit burst=10 delay=5;
每秒标准5个请求,burst可以让突发请求到10个,delay是当有突发请求时前五个直接请求,剩余的rate=5/s=200ms/个,消费1个,等待200ms
4、openresty-lua限制
通过openresty,将请求相关数据发送到请求数据分析接口,分析之后返回结果,再由openresty判断是否放行,到目前为止立竿见影。
数据分析接口大概得思路就是:此时做一些限制已经没有用了(后端代码也无法更改),去推理人的行为,一个正常人要访问网站时会怎么操作,爬虫毕竟只是爬虫,没法跟人一样。
local http = require "resty.http"
local httpc = http.new()
local json = require("cjson")
local uri = ngx.var.noparams_uri
local headers=ngx.req.get_headers()
local ip=headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or ngx.var.remote_addr
local ua=headers["User-Agent"] or ''
local white_ua={"xxxx",} -- ua 白名单
local api_server="xxx:1234"
local topic_id = "xxxxx"
function req_fast_api()
--return false 是异常请求,true是正常请求
local data = {
TopicId = "xxxxxxx",
From = 1710086694000,
To = 1717151565000,
Query = '"remote_addr:\"' .. ip .. '\""',
Limit = 100
}
local jsonStr = json.encode(data)
local resp, err = httpc:request_uri("http://" .. api_server .. "/xxx/xxx/xxxx", {
method = "POST",
body = jsonStr,
headers = {
["Content-Type"] = "application/json",
},
})
if not resp then
ngx.log(ngx.ERR, "cls 日志接口挂了。")
return 500, "true"
end
return resp.status, resp.body
end
function main()
-- 校验ua是否在白名单中
local outer_i
for i, v in ipairs(white_ua) do
if string.find(ua, v) then
break
else
outer_i = i
end
end
if outer_i == #white_ua then
-- ua不在白名单中
ngx.header["Server"] = "xxxxx/xxx"
local status, body = req_fast_api()
ngx.log(ngx.ERR, ip .. "日志接口返回:" .. body .. ",且ua不在白名单中。")
if body == "false" then
ngx.status = ngx.HTTP_BAD_REQUEST
ngx.say("xxxx")
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
end
end
local m = ngx.re.match(uri, "^/xxxxx/.*$", "jo")
if m then
main()
else
ngx.log(ngx.ERR, "非xxxx的忽略" .. uri)
end
本文阅读量 次