You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails框架下应对机器人恶意请求的最优方案咨询——关于重定向方案安全性及日志优化的疑问

应对Rails应用遭恶意请求轰炸的解决方案探讨

最近我们的Rails应用被大量随机POST和GET请求轰炸,POST请求大多因为无效的authenticity token返回500/422错误,典型日志如下:

Started POST "/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" for 45.146.165.123 at 2021-06-29 04:15:39 -0400
I, [2021-06-29T04:15:39.769996 #2050] INFO -- : [be4241b9-0494-4fb5-b434-2d11038017f1] Processing by HomeController#index as 
I, [2021-06-29T04:15:39.770109 #2050] INFO -- : [be4241b9-0494-4fb5-b434-2d11038017f1] Parameters: {"<?"=>"md5(\"phpunit\")?>", "path"=>"vendor/phpunit/phpunit/src/Util/PHP/eval-stdin"}
W, [2021-06-29T04:15:39.790171 #2050] WARN -- : [be4241b9-0494-4fb5-b434-2d11038017f1] Can't verify CSRF token authenticity.
I, [2021-06-29T04:15:39.833066 #2050] INFO -- : [be4241b9-0494-4fb5-b434-2d11038017f1] Completed 422 Unprocessable Entity in 53ms (MongoDB: 0.0ms)
F, [2021-06-29T04:15:39.916526 #2050] FATAL -- : [be4241b9-0494-4fb5-b434-2d11038017f1]
F, [2021-06-29T04:15:39.916666 #2050] FATAL -- : [be4241b9-0494-4fb5-b434-2d11038017f1] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

我们原本考虑采用「Intermittent Rails 5 ActionController::InvalidAuthenticityToken」方案,但担心机器人会察觉到我们的重定向操作,想问问这种做法有没有风险?有没有更好的方案既能拦截这些机器人,又能避免生产日志被大量错误信息淹没?


先说说「Intermittent InvalidAuthenticityToken」方案的风险

这个方案的核心是间歇性返回重定向而非直接抛出错误,确实存在不小的隐患:

  • 机器人可以通过检测3xx状态码识别出自己被针对性拦截,进而调整攻击策略——比如更换IP池、调整请求频率、伪装请求头,甚至转向其他潜在漏洞尝试。
  • 如果重定向逻辑设计得不够严谨,还可能被利用来进行SSRF(服务器端请求伪造)或者重定向钓鱼攻击(不过后者在你的场景下概率较低)。

更优的拦截&日志优化方案

我建议从基础设施层、应用层、日志层三个维度入手,既能有效拦截恶意请求,又能减少日志污染:

1. 基础设施层拦截(最高效,直接把请求挡在应用外)

  • CDN/WAF规则:用Cloudflare、AWS WAF这类服务,直接拦截带有明显攻击特征的请求:
    • 拦截路径包含phpunit、eval-stdin.php这类常见攻击路径的请求,直接返回403 Forbidden;
    • 设置速率限制,对单一IP的请求频率做阈值限制(比如每分钟最多100次),超过就临时封禁10-15分钟。
  • Web服务器配置:在Nginx/Apache层面添加规则,过滤带有恶意参数(比如<?这种PHP注入特征)的请求,或者拦截无User-Agent、带有攻击工具标识的UA请求。

2. Rails应用层优化(补充防护+减少日志污染)

  • 自定义InvalidAuthenticityToken处理逻辑:不要让框架直接抛出500错误,而是静默返回403,并且不记录冗余的错误日志。你可以在ApplicationController里重写handle_unverified_request方法:
    def handle_unverified_request
      # 针对恶意请求,直接返回403,不触发完整的错误栈日志
      head :forbidden, content_type: 'text/plain'
    end
    
    这样既避免了生产日志被大量错误淹没,也不会给机器人明确的拦截信号(统一返回403,和正常的权限拒绝状态一致)。
  • 集成Rack::Attack做应用层防护:这个中间件可以帮你做速率限制、IP封禁:
    # 先在Gemfile添加
    gem 'rack-attack'
    
    # 然后在config/initializers/rack_attack.rb里配置
    class Rack::Attack
      # 限制单一IP每分钟最多100次非静态资源请求
      throttle('req/ip', limit: 100, period: 1.minute) do |req|
        req.ip unless req.path.start_with?('/assets', '/packs')
      end
    
      # 直接封禁请求恶意路径的IP
      blocklist('malicious_paths') do |req|
        req.path.include?('/vendor/phpunit') || req.path.include?('eval-stdin.php')
      end
    end
    
  • CSRF验证增强:对于敏感接口,可以额外检查X-Requested-With请求头是否为XMLHttpRequest(针对AJAX请求),或者添加自定义的请求头验证规则。

3. 日志层优化

  • 日志分割与过滤:用Logrotate把正常访问日志和错误日志分开,同时在Rails配置里,将ActionController::InvalidAuthenticityToken这类错误的日志级别调低,或者只记录到专门的攻击日志文件中,不要污染主生产日志。
  • 精简错误日志:修改Rails的日志配置,避免记录这类恶意请求的完整栈信息,只保留关键的IP、请求路径、时间戳即可。

总的来说,优先用基础设施层的拦截方案,能最大程度减少应用层的压力;应用层做补充防护和日志优化;尽量保持返回状态码的一致性(比如统一返回403),让机器人难以判断自己是否被识别,避免触发他们的自适应攻击策略。

内容的提问来源于stack exchange,提问作者user1130176

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 21:02:40