因为一些原因需要搞一个类似于 Cloudflare 的五秒盾,不是给公司用的,给个人站点用的。大伙看看有没有什么问题,比如绕过的方法,或者一些漏洞可以被用来攻击。
下面是流程图。
注意:流程图中提到的服务器是类似 Apache 和 Nginx 这样的服务器软件。
1 HenryGe 2021-04-30 18:00:49 +08:00 挂一个 proxy ip 池,每隔一秒换一个 ip, 只需要 5 个 ip 轮换,就轻松破功。 |
![]() | 2 c137rick OP @HenryGe #1 code 计算时是有 IP 的,IP 变化了服务端计算 code 时就对不上了,会重新计算三个 cookie 然后重定向到五秒盾。 |
![]() | 4 chairuosen 2021-04-30 18:11:12 +08:00 ![]() 防的是什么? 5 秒后这个正常请求如果被重放,似乎并不会被拦? |
![]() | 6 woodensail 2021-04-30 18:13:41 +08:00 我看你似乎在无 cookie 状态下没做任何判断就直接生成 cookie 了? 如果对方针对这个来打爆你的数据库能撑得住吗,还是说在数据库层面做了 ip 去重。 |
![]() | 7 c137rick OP @HenryGe #3 我的五秒盾的目的是对于每个用户首次访问需要延迟五秒,我不是专业的,能否把具体的攻击方式描述一下?所谓攻击就是绕过首次的五秒延迟。 |
![]() | 8 clf 2021-04-30 18:15:57 +08:00 5S 盾的机制应该是像 1 分钟请求超过 100 次或者是 1s 超过 5 次之类时后端做个接口熔断。 然后前端路由切换过快时,做个前端拦截。 你现在单纯的判断上次请求的时间,意思就是每个接口请求间隔必须 5s,那么用户使用体验极差,还有就是像现在的前后端分离的页面,你进入页面后基本都要请求 N 个接口,那么这些接口请求还要间隔 5s 么。如果不需要,怎么判断是正常访问你的页面还是脚本爆破你的服务器呢。 |
![]() | 9 c137rick OP @chairuosen #4 目标就是每个用户首次访问时延迟五秒,延迟五秒后正常访问。重放是可以重放,但是没有意义吧?比如换一个 IP 重放会导致服务端计算的 code 对不上。 |
![]() | 10 c137rick OP @woodensail 服务端不存储任何信息,服务端完全依靠客户端的 cookie 验证。 |
12 superrichman 2021-04-30 18:18:30 +08:00 via iPhone ![]() 恭喜你重新发明了 jwt |
![]() | 13 chairuosen 2021-04-30 18:19:11 +08:00 ![]() @c137rick #9 CF 做延迟 5 秒是为了放 D 。。。你是为了给用户添堵?。。。。。不能只照着皮毛抄呀。。 不换 IP 重放,code 是一样的 |
![]() | 14 c137rick OP @chairuosen #14 延迟五秒后五秒盾就不会再起作用了,后续会有专门的机制限制 IP 的访问频率。想使用这两个机制稍微抵抗一下代理池。 |
![]() | 15 suomy 2021-04-30 18:24:33 +08:00 那我首次访问伪造一下 time cookie 不就破了吗? |
![]() | 16 c137rick OP @suomy #15 只有在客户端提供的 code 和服务器计算的 code 相同时才会判断时间,如果 code 对不上是不会走到判断时间这一步的。 |
![]() | 17 woodensail 2021-04-30 18:33:39 +08:00 @c137rick 服务端不存储的话,对方岂不是很容易就伪造 hash 了。还是说你寄希望于对方摸不透你 cookie 的生成算法? |
![]() | 18 woodensail 2021-04-30 18:35:25 +08:00 哦,等下,你有个 salt 是吧,也就是靠 salt 保密那倒是基本上没问题了,除了不防重放以外。 |
![]() | 19 c137rick OP @woodensail #17 Cookie 生成算法是可以公开的,因为生成 code 时用到了服务端的一个长度为 128 的随机字符串。对方知道算法也没办法伪造吧?攻击者可以伪造 uid 和 time,但是 code 生成时不仅使用了客户端 IP 和 uid,还使用了一个仅存储在服务端的随机字符串,所以 code 应该时不能伪造的。大概没问题吧? |
![]() | 20 c137rick OP @woodensail #18 重放确实不防,不过五秒盾的后面还有一个限制 IP 访问频率的机制,应该可以缓解一下。我是希望使用这两种机制来缓解一下来自代理池的攻击。 |
![]() | 22 c137rick OP @woodensail #18 好像有一个问题,首次访问时只需要修改一下 time 就能绕过了,这应该是一个漏洞。我打算用让 time 参加到 code 的生成过程中,这样应该就没问题了。 |
![]() | 23 rrfeng 2021-04-30 19:15:57 +08:00 首先指定一个用户标记:ip 、uid 、cookie 都行,识别用户。 然后存一个用户的 『首次访问时间』就行了,哪有这么麻烦?用户识别和时间都是以服务器为准,怎么都伪造不了。 |
![]() | 24 clf 2021-04-30 19:32:46 +08:00 @c137rick #11 看下来后,其实你只要服务器上缓存用户的首次访问时间就行了,以服务端为准,对客户端应该是无感的。过了 5s 限制后服务端把这个缓存记录清除就可以了。(其实和 jwt 的场景很像,二次加密一下 jwt 就是你的 code 计算了。 另外,首次访问延迟 5s 这个需求就有点奇怪(干脆登录接口调用后延迟 5s 下发数据得了。 |
![]() | 25 woodensail 2021-04-30 20:20:27 +08:00 @lychs1998 我感觉楼主就是想实现一个不依赖数据库的鉴权,有些类似于 jwt 。 |
![]() | 26 zjsxwc 2021-04-30 21:32:06 +08:00 via Android http2 协议一次请求代替 n 次原先 http 1 协议的请求, 楼主是开倒车吗 |
![]() | 27 yujiang 2021-04-30 22:50:43 +08:00 via Android 你这个也不防 d 啊,流量照样全打上。 个人网站直接套 cf 就好,做这个东西没啥意义,挡不住的。而且这样做就意味着你全站没法用现成的大厂 CDN,回源会出问题。cf5 秒盾后面还有一整套的风控,不是咱几行代码就能抄过来的 |
![]() | 28 ysc3839 2021-05-01 10:42:17 +08:00 via Android 没仔细看,但感觉没学到精髓。 印象中 Cloudflare 那个主要是要客户端脚本跑一个比较复杂的算法,防止那些非浏览器的流量进来。算法会故意混淆,防止有人直接用其他语言实现,而且可能几天就换一下,使得只有用 Javascript 引擎才能算出。 而你这个方案,感觉简单研究一下就能用别的语言实现了。 |
![]() | 29 c137rick OP |
![]() | 30 discrete 2021-05-01 14:58:21 +08:00 可以写个 JS 让客户端帮你算 Proof of Work,然后你服务端交到矿池上去。如果被 D 你也是赚了,不被 D 最好 |
![]() | 32 no1xsyzy 2021-05-01 15:42:05 +08:00 |
![]() | 33 c137rick OP |
35 firefox12 2021-05-03 23:08:26 +08:00 我每次都用你 10 秒以前的 key 不久好了,你设置了 cookie 我不需要用啊 1 个 key 无限使用。 |