mirror of
https://github.com/ADD-SP/ngx_waf.git
synced 2026-04-26 14:05:52 +03:00
[GH-ISSUE #13] CC 防护增加验证码访问功能 #6
Labels
No labels
MacOS
Nginx
OpenResty
Tengine
bug
documentation
enhancement
needs-investigation
pull-request
question
stale
stale
stale
timeout
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/ngx_waf#6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @toyops on GitHub (Dec 14, 2020).
Original GitHub issue: https://github.com/ADD-SP/ngx_waf/issues/13
CC 防护是否可以考虑增加一个访问频繁转跳验证码的功能,验证码通过则可以访问,否则锁定一段时间持续要求填写验证码,大部分 toC 的业务层可能都需要这种功能,尤其是业务规模不大的情况下,又遇到刷单的问题。
@ADD-SP commented on GitHub (Dec 14, 2020):
考虑了一下,有下面的几个问题暂时不知如何妥善解决,列出来讨论一下可能的解决方法。并非 WEB 方向,可能会有低级错误。
值得一提的是 nginx 允许自定义错误界面,有没有可能通过通过自定义 503(CC 防护生效时就会返回 503 错误)错误页面来实现?
@toyops commented on GitHub (Dec 14, 2020):
可以考虑调用 Golang ,有合适的库生成 recaptcha 图片,含有图片的页面,及验证功能函数。
https://github.com/dchest/captcha
https://github.com/mojocn/base64Captcha
@ADD-SP commented on GitHub (Dec 14, 2020):
出于下列原因不会考虑调用其它语言:
.so、.dll等,要做各个平台的适配。make之后立刻使用,就算不动态加载.so或dll等文件,也需要提前将其它语言编译成二进制格式。需要额外的编译脚本。@ADD-SP commented on GitHub (Dec 14, 2020):
找到一个 C 语言的库:captcha,先记录在这里。考虑一下实现方式决定是否添加本功能,有了进展我会在这里留言的。
@ADD-SP commented on GitHub (Dec 16, 2020):
想到一种作为项目作者可能可以接受但模块用户不一定可以接受的实现方式,所以贴出来讨论一下,或者改进,或者否决。
实现方式
优点
缺点
@toyops commented on GitHub (Dec 16, 2020):
感觉干脆就外部接入一个程序也挺好。触发 CC 防护时,可能也要加上速率限制,提供验证码页面的次数不能不限制,会成为攻击点。还有现在是分钟,细粒度是不是不够,面对 CC 攻击都是秒级别的多。使用最简单配置测试的时候也发现 CC 防护没到时间就请求到了后端。
nginx 配置
waf on;
waf_mode STD;
waf_cc_deny_limit 5 1;
location / {
index index.html;
}
测试脚本
for i in
seq 1 20;dodate
echo $i
curl http://127.0.0.1
echo
done
发件人: ADD-SP notifications@github.com
发送时间: 2020年12月16日 12:48
收件人: ADD-SP/ngx_waf ngx_waf@noreply.github.com
抄送: toyops volqiu@live.com; Author author@noreply.github.com
主题: Re: [ADD-SP/ngx_waf] CC 防护增加验证码访问功能 (#13)
想到一种作为项目作者可能可以接受实现方式,贴出来讨论一下,或者改进,或者否决。
实现方式
含有若干个验证码图片的目录
waf_captcha_path /path/to/captcha;
指向验证码图片目录的 URL
waf_captcha_url /url/to/captcha;
指向验证码页面的 URL。
waf_captcha_page_url /url/to/captcha/page;
验证码页面发送 GET 请求到这个 URL,使用 GET 参数传递用户输入的验证码的值和验证成功后要跳转到的 URL。
waf_captcha_check_url /url/to/captcha/check;
优点
缺点
―
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHubhttps://github.com/ADD-SP/ngx_waf/issues/13#issuecomment-745761582, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AGEZXHMIJT46Q54GGPCGZN3SVA32LANCNFSM4U2FISQQ.
@ADD-SP commented on GitHub (Dec 16, 2020):
CC 防护并不是每分钟检查一次,而是一分钟内超过指定一次数自动拉黑,并不会等待一分钟过去后再检查。
提供验证码的次数可以限制。
这段话的意思是 CC 拉黑时间还没结束的时候,请求就已经到后端而不是被拦截了?
@toyops commented on GitHub (Dec 16, 2020):
是的,我这边跑出来的结果有些问题。具体日志我发你邮箱吧。
@ADD-SP commented on GitHub (Dec 16, 2020):
请查收邮件。
@ADD-SP commented on GitHub (Dec 17, 2020):
我拍脑袋想到了另外一个实现方式,思考得不多,不过首先需要说明下面几条,这是本功能设计的原则。
实现方式见下文,可以就改进,不行就否决。
实现方式
配置语法
验证过程
假设为字符串形式的验证码。
优点
缺点
@ADD-SP commented on GitHub (Dec 18, 2020):
突然发现不太对,既然验证码的生成都交给业务代码了,为什么不直接在业务代码里实现验证码,把验证工作交给模块是画蛇添足了。
@ADD-SP commented on GitHub (Dec 18, 2020):
本模块设计原则是简单而不是复杂,所以需要将验证码的生成工作交给外部,但是既然验证码的生成已经交给外部了为什么不把验证也一起交给外部呢?把验证过程单独交给模块有些画蛇添足的意思,所以不如不添加这个功能。
所以暂时不考虑添加这个功能,如果有关于这个功能有其它想法可以继续在这里留言讨论。三天后如果没有收到留言我就关掉这个 issue 了。
@toyops commented on GitHub (Dec 18, 2020):
给业务模块生成肯定有一个效率问题,而且会有流量导入到后端,但你 CC 防护已经拒绝用户访问了,不提供验证码就只能等待超时放出了,所以在 CC 防护这里提供验证码放行的功能是可以接受的。
@ADD-SP commented on GitHub (Dec 18, 2020):
其实主要矛盾是实现方式的问题,模块最好不要负责验证码生成,但是交给外部必然带来模块用户的不方便。昨晚提到的实现方式有什么看法么?
@toyops commented on GitHub (Dec 18, 2020):
和外部模块确实只需要一个转跳功能或者反向代理,以及一个放行状态的维护和交互,就可以了。检测到触发 CC 规则,则一直转跳反向代理到 外部模块,外部模块验证通过后,发送通知,通知 waf 解除这个状态,waf 予以放行。
@ADD-SP commented on GitHub (Dec 18, 2020):
看起来我的想法被大致接受了。我确认一下。
同时如果想直接拦截某个 IP 也可以通过直接访问指定的 URL 来实现,只要哈希值计算出来不相同模块就会自动改变 CC 防护的状态。
以上内容有什么意见么?
@toyops commented on GitHub (Dec 18, 2020):
没有,就是外部模块谁来写的问题。
@ADD-SP commented on GitHub (Dec 18, 2020):
不一定需要模块,只要指定的 URL 能跳转到验证码页面就行,并且验证码页面能按照本模块的约定发送请求和接收响应即可。所以 URL 甚至可以直接指向一个静态页面,那个静态页面再通过某些方式获取验证码信息。
@ADD-SP commented on GitHub (Dec 18, 2020):
突然发现我的方式并不安全,提交给模块检查的 URL 最好还是不要暴露,也就是说检查验证码的请求必须由后端代码发出,不过总归方法还不至于被否决。
话说为什么不直接接入成熟的验证码平台呢?
@ADD-SP commented on GitHub (Dec 18, 2020):
否决上次的解决方式,原因是因为 NGINX 的进程模型。
NGINX 启动时会由 master 进程 fork 出多个 worker 进程,然后由 worker 进程负责处理每一个请求。
当一个请求过来的时候会被分配到某一个 worker 进程内,此进程会处理这个请求,本模块也就在此时进行验证操作,并改变 CC 防护的状态。但是多个 worker 进程间模块的上下文不是共享的,所以会导致某个 worker 进程内的模块改变了 CC 防护状态,但是其它 worker 进程内的模块无动于衷的情况。
至于为什么不启用进程间通讯机制来保证模块间同步状态,第一是性能问题,因为多个进程控制同一个信号必然要引入锁。第二是可能会扩大故障范围,一旦某个 worker 进程崩溃,那么它持有的锁可能就永远无法释放,其它的 worker 就会永远无法得到锁从而卡住。第三是不同平台的进程间通讯 API 可能不同,要做多平台适配。
@ADD-SP commented on GitHub (Dec 18, 2020):
说明一下情况,模块不负责验证码生成,但必须知道验证结果,由于多个 worker 进程间模块上下文不共享,所以需要一种合适的方式保证每个模块都能同步知道验证结果,但是现在没找到。因此对于一个请求可能一个 worker 会放行,而另一个会拦截。
至于验证码的需求,我建议在其它地方实现,本模块目前不打算实现此功能。本 issue 将再开启三天,期间如果没有出现合适的实现方式将关闭本 issue。