记一次CDN被刷与应对方法 – 晨旭的博客~

admin 6952次浏览

摘要:2024.12.16更新 本站已迁移至海外服务器,本站目前没有继续使用CDN的必要了 上个月初,本站的七牛CDN被刷了不少流量,特此记录一下,极大概率

2024.12.16更新

本站已迁移至海外服务器,本站目前没有继续使用CDN的必要了

上个月初,本站的七牛CDN被刷了不少流量,特此记录一下,极大概率可能是某些PCDN用户刷的,不得不说这个群体是真缺德。

发现CDN被刷

因为主站服务器上行是小水管,所以所有静态文件都走了CDN来加速用户访问

这里为了描述简介,我将主站域名称为主站域名,CDN的域名称为域名A

正常情况下,域名ACDN的流量日志应该是这样的:

但是某天我收到了几条七牛的流量阈值提醒,流量变成了这样,翻了好几倍:

甚至某天夜晚两小时刷了20G:

寻找原因

以开始当然是尝试寻找刷流量的ip来源,于是下载了CDN日志,发现都是同一个ip段,用随机UA,不停访问同一个js文件。这种特征基本可以断定是被刷流量了

在思考是不是得罪人了之后,我感觉这并不是针对性的攻击,毕竟力度太小了

简单搜索,在v2ex上发现不少类似遭遇的帖子:

糟心阿里 CDN,恶意刷流量,域名解析已经切换源,流量依旧

每天晚上 20~23 时准点被山西联通 IP 刷流量现象的分析和猜测

cdn 被盗刷

公司的阿里云 CDN 每晚都在被偷偷刷量

现象基本一致,甚至IP均来自山西联通,可以断定是同一事件。

不得不说搞PCDN的这群人真是缺了大德,为了赚那么点钱,显示刷BT网络,接着刷各大镜像站导致各家无奈限速,最后又来刷各家的个人站点CDN

应对措施

第一时间我停止了域名A的解析,不过没有效果。似乎是直接访问的七牛CDN节点IP并手动提交的http请求信息,我直接在七牛控制台删除了这个CDN,不再产生流量。

屏蔽刷流量访问

如果你觉得自己更新勤快,直接定前屏蔽ip段即可,这里有所有被屏蔽的IP段,这是最快的方法

我启用了之前备用的域名B,这个一直指向的是腾讯CDN,可以随时无缝切换用于备用。不过这样单纯切换也没有用,因为恶意访问的请求是带正确的UA与referer的,很难使用CDN提供商的功能进行筛选。

于是我开启了域名B腾讯CDN的访问鉴权,并将域名A指向改为我的服务器,当用户访问域名A时,会自动走一套验证逻辑,通过验证后会302跳转到带正确鉴权信息的域名B网址,没通过验证的请求直接断开tcp。这样对于主站用户来说是无感的,同时也不影响我机器的小水管上行。

验证逻辑

具体验证逻辑思路如下:

因为正常访问cdn的请求,必定是会先访问我的博客主站的。

所以我的博客主站会先记录下当前访问者的IP,放入访问白名单中,保留30秒。同时页面上也有一个js每20秒会刷新一下,保证访客ip始终在白名单中。

cdn跳转请求处理那边只需要判断当前ip是不是在白名单中即可。

这里我以openresty端来举个例子吧

在nginx全局的配置文件里,先声明一个变量share_ip,用于存储临时的ip数据

//一堆东西...

http

{

//一堆东西...

lua_shared_dict share_ip 10m;

//一堆东西...

然后在真正被访问的网站里,给某个特定路径加上一个心跳记录,用于给某个ip临时加白:

server

{

listen 80;

listen 443 ssl http2;

//一堆东西...

//用来记录合法ip的接口

location /hb {

content_by_lua_block {

local ip = ngx.var.remote_addr

local ttl = 75 --白名单有效期,这里是75秒

local dict = ngx.shared.share_ip

dict:set(ip, true, ttl)

ngx.header["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0";

ngx.header["Pragma"] = "no-cache";

ngx.header["Expires"] = "0";--确保每次请求都不是浏览器缓存

ngx.exit(204)

return

}

}

//一堆东西...

}

这样访问这个网站的/hb路径后,请求ip便会被记录为合法,有效期75秒

在CDN跳转的网站处理代码中加上下面的代码,我这里用腾讯云的鉴权作为例子,大家如果有需求可以改为自己CDN使用的鉴权算法

server

{

listen 80;

listen 443 ssl http2;

//一堆东西...

location / {

content_by_lua_block {

-- Function to encode a character to URL encoding

local function char_to_url(char) return string.format("%%%02X", string.byte(char)) end

-- Function to encode only non-ASCII characters in a string to URL encoding

local function url_encode_non_ascii(str)

local encoded = {}

local i = 1

while i <= #str do

local byte = string.byte(str, i)

if byte > 0x7F then

-- This is the start of a multi-byte character in UTF-8

local multi_byte_char = {}

while byte and byte > 0x7F do

table.insert(multi_byte_char, str:sub(i, i))

i = i + 1

byte = string.byte(str, i)

end

for _, char in ipairs(multi_byte_char) do table.insert(encoded, char_to_url(char)) end

else

table.insert(encoded, str:sub(i, i))

i = i + 1

end

end

return table.concat(encoded)

end

--按需注释

ngx.header.access_control_allow_methods = "*"

ngx.header.access_control_allow_origin = "*"

local ip = ngx.var.remote_addr

local dict = ngx.shared.share_ip

local is_marked = dict:get(ip)

if ip == "127.0.0.1" or ip == "::1" then

is_marked = true

end

if not is_marked then

for i=1,8 do--多等上个8秒,万一加载慢呢

ngx.sleep(1)

is_marked = dict:get(ip)

if is_marked then break end

end

if not is_marked then

ngx.exit(444)--非法访问,直接踢了

return

end

end

local uri = url_encode_non_ascii(ngx.var.uri)

local new_domain = "你的目标CDN域名"

local key = "腾讯云的加密key"

math.randomseed(tonumber(tostring(ngx.now()*1000):reverse():sub(1,9)))--确保真随机

local rand = "abc"..tostring(math.random(10000,99999))

local timestamp = tostring(ngx.time())

local sign = ngx.md5(uri.."-"..timestamp.."-"..rand.."-0-"..key)

local new_url = "https://"..new_domain..uri.."?cdn="..timestamp.."-"..rand.."-0-"..sign

return ngx.redirect(new_url, 302)

}

}

//一堆东西...

}

这样服务端配置就完成了

在网页中,可以手动加上定期刷新白名单请求的js代码,刷新周期比过期时间短就可以了,比如:

效果

部署完这些后,没有再出现异常流量:

附带好处就是可以额外屏蔽某些不道德的爬虫访问cdn,防止流量被爬虫刷

附:部分应屏蔽的ip段

27.221.70.0/24

36.5.81.0/24

36.35.38.0/24

36.151.55.0/24

36.249.150.0/24

39.74.239.0/24

58.220.40.0/24

60.190.128.0/24

60.220.182.0/24

60.221.195.0/24

60.221.231.0/24

61.146.45.0/24

61.147.95.0/24

61.160.233.0/24

61.160.239.0/24

61.179.15.0/24

61.241.177.0/24

111.121.27.0/24

113.231.202.0/24

114.230.220.0/24

116.179.152.0/24

116.246.1.0/24

118.81.184.0/23

122.195.22.0/24

124.132.156.0/24

124.163.207.0/23

124.163.220.0/24

153.101.51.0/24

153.101.64.0/23

153.101.141.0/24

175.42.154.0/23

175.44.72.0/23

183.185.14.0/24

183.224.221.0/24

211.90.146.0/23

211.93.170.0/24

220.248.203.0/24

221.6.171.0/24

221.7.251.0/24

222.189.163.0/24

相关文章:

如何用C#调用RUST的DLL

手动修复时间轴坏掉的视频

简单解析微信、支付宝,付款码的条形码生成原理

Luat系列教程:6、mqtt代码详解

在树莓派上搭建nextcloud私有网盘

相关文章
友情链接