NGINX+Rails环境下恶意请求IP的记录、封禁及高频请求统计与安全优化咨询
针对你遇到的机器人扫描和攻击问题,结合Rails+Nginx的架构,我整理了一套从日志收集、IP封禁到安全加固的完整方案,具体如下:
一、捕获路由错误并记录关键信息
首先,我们需要在Rails应用中主动捕获ActionController::RoutingError,并记录请求IP、URL及请求次数。推荐用Redis做实时计数,它高效且适配这类统计场景:
配置Redis依赖
在Gemfile中添加:gem 'redis'执行
bundle install完成安装。自定义异常处理逻辑
在app/controllers/application_controller.rb中添加异常捕获代码:rescue_from ActionController::RoutingError do |exception| # 获取请求来源IP client_ip = request.remote_ip # 获取被请求的恶意URL requested_url = request.fullpath # 用Redis统计该IP的攻击次数 Redis.current.incr("attack:ip:#{client_ip}") # 统计恶意URL的被请求频次 Redis.current.incr("attack:url:#{requested_url}") # 将详细攻击日志写入自定义文件 File.open(Rails.root.join('log', 'attack_logs.log'), 'a') do |f| f.puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} | IP: #{client_ip} | URL: #{requested_url} | Error: #{exception.message}" end # 保持原有404返回逻辑 render file: Rails.public_path.join('404.html'), status: :not_found, layout: false end注意:MAC地址无法通过公网HTTP请求获取,因为HTTP是基于IP的应用层协议,MAC属于链路层信息,仅同一局域网内的设备才能获取对方MAC,公网环境下服务器无法拿到攻击者的MAC地址。
二、自动封禁恶意IP
方案1:用Fail2ban监听日志(推荐)
Fail2ban可以自动扫描日志文件、匹配攻击特征,通过iptables自动封禁违规IP,配置步骤如下:
安装Fail2ban
Debian/Ubuntu系统:sudo apt-get install fail2banCentOS/RHEL系统:
sudo yum install fail2ban自定义过滤规则
在/etc/fail2ban/filter.d/rails-routing-error.conf中添加:[Definition] failregex = ^.*IP: <HOST>.*No route matches.*$ ignoreregex =配置封禁规则
在/etc/fail2ban/jail.local中添加:[rails-routing-error] enabled = true filter = rails-routing-error logpath = /path/to/your/rails/app/log/attack_logs.log maxretry = 5 # 累计5次错误请求即封禁 bantime = 3600 # 封禁时长1小时(可按需调整) findtime = 600 # 统计周期为10分钟重启Fail2ban生效
sudo systemctl restart fail2ban
方案2:Nginx内置模块限制请求
如果不想额外部署工具,可以用Nginx的ngx_http_limit_req_module限制单IP请求速率:
在Nginx的http块中添加:
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/m;
然后在你的Rails应用server配置块中添加:
location / { limit_req zone=one burst=5 nodelay; # 保留原有Nginx配置... }
该规则限制单IP每分钟最多10次请求,超出部分直接返回503。
三、统计高频被攻击URL
方式1:Redis实时统计
之前的异常处理逻辑已经用Redis记录了URL请求次数,你可以写一个简单的Rake任务获取Top N恶意URL:
在lib/tasks/attack_stats.rake中添加:
namespace :attack do desc "获取被攻击频次最高的前10个URL" task top_urls: :environment do url_counts = Redis.current.keys("attack:url:*").each_with_object({}) do |key, hash| url = key.gsub("attack:url:", "") hash[url] = Redis.current.get(key).to_i end puts "Top 10 被攻击URL:" url_counts.sort_by { |_, count| -count }.first(10).each do |url, count| puts "#{url}: #{count} 次请求" end end end
执行rake attack:top_urls即可查看结果。
方式2:直接分析日志文件
如果不用Redis,也可以用awk命令直接解析自定义攻击日志:
awk '{print $7}' /path/to/attack_logs.log | sort | uniq -c | sort -nr | head -10
注:命令中的$7需根据你的日志格式调整,确保对应到URL所在的列。
四、额外安全优化建议
- 隐藏Rails版本信息:在
config/application.rb中添加config.action_dispatch.default_headers['X-Rails-Version'] = nil,避免泄露版本给攻击者。 - 启用Nginx安全头:在server块中添加:
add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; - 强制HTTPS访问:配置Nginx将所有HTTP请求重定向到HTTPS,避免明文传输敏感信息。
- 部署Web应用防火墙(WAF):给Nginx安装ModSecurity模块,拦截XSS、SQL注入等常见攻击。
- 定期更新依赖:用
bundle audit检查Gem中的安全漏洞,及时更新补丁。 - 限制后台路径访问:如果有Rails控制台或管理后台,用Nginx配置仅允许特定IP访问。
- 添加CAPTCHA验证:在登录、注册等敏感页面加入CAPTCHA,防止机器人自动化攻击。
内容的提问来源于stack exchange,提问作者CJG

