我正在使用https://github.com/kickstarter/rack-attack/#throttles来限制对某些网址的请求.
机架攻击文档显示了如何根据请求IP或请求参数进行限制,但我想要做的是每个用户的限制请求.因此,无论IP如何,用户都应该能够在特定时间范围内发出不超过n个请求.
我们使用设计进行身份验证,我想不出根据请求唯一识别用户的简单方法.
我应该在会话/ cookie中存储用户ID吗?也许是uniq哈希?对于这样做的最佳方式,您有什么看法?
我不知道为什么我不能使用机架攻击宝石这里我做了什么
的Gemfile
gem 'rack-attack'
Run Code Online (Sandbox Code Playgroud)
我安装了宝石
配置/ application.rb中
config.middleware.use Rack::Attack
Run Code Online (Sandbox Code Playgroud)
初始化/机架attack.rb
class Rack::Attack
throttle('logins/ip', :limit => 5, :period => 60.seconds) do |req|
if req.path == '/login' && req.post?
Rails.logger.error("Rack::Attack Too many login attempts from IP: #{req.ip}")
req.ip
end
end
end
Run Code Online (Sandbox Code Playgroud)
的routes.rb
post 'login' => 'index#create'
root 'index#new'
get 'login' => 'index#new'
Run Code Online (Sandbox Code Playgroud)
我正在使用Rails 4.2.3和机架攻击宝石4.3.0
我想知道我想念的是什么
我正在开发Reactjs
用作前端和Rails5 api only
应用程序作为后端的Web应用程序
这是我发送到服务器的数据 Request payload
------WebKitFormBoundaryCD1o71UpVNpU4v86
Content-Disposition: form-data; name="user[username]"
oeuoeoaeaoe
------WebKitFormBoundaryCD1o71UpVNpU4v86
Content-Disposition: form-data; name="user[profile_image]"; filename="gggg.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryCD1o71UpVNpU4v86--
Run Code Online (Sandbox Code Playgroud)
这是我的控制器
def update_with_image
user = current_user
if user.update_attributes(user_update_params)
# Handle a successful update.
render json: user, status: 200
else
render json: { errors: user.errors }, status: 422
end
end
private
def user_update_params
params.require(:user).permit(:username,:profile_image)
end
Run Code Online (Sandbox Code Playgroud)
所以当我试图将图像上传到Rails服务器时,我遇到了这个错误
ActionController::BadRequest (Invalid request parameters: invalid %-encoding ("user[username]"
oeuoeoaeaoe
------WebKitFormBoundaryCD1o71UpVNpU4v86
Content-Disposition: form-data; name="user[profile_image]"; filename="gggg.jpg"
Content-Type: image/jpeg
????JFIF????@6"??
??F!1AQ "aq?
#2???B?????$3Rb?%Cr?????? ??A!1A"Qaq?2???BR???#b??3rS?$Cs????
??%)):
rack …
Run Code Online (Sandbox Code Playgroud) Rails app,使用Kickstarter的机架攻击
在我的config/rack-attack.rb文件中,我有:
class Rack::Attack
Rack::Attack.blacklist ('block ip') do |req|
# Request are blocked if the return value is truthy
'68.888.23.22' == req.ip
# req.ip if IPCat.datacenter?(req.ip)
end
end
Run Code Online (Sandbox Code Playgroud)
这一直很好,直到我开始使用CloudFlare.req.ip现在是Cloudflare IP vs实际最终用户的IP
尝试将用户的IP保存到我的服务器日志时,我遇到了类似的问题(正在保存Cloudflare IP).为了解决这个问题,我将以下内容添加到应用程序控制器中:
module ActionDispatch
class Request < Rack::Request
alias :remote_ip_orig :remote_ip
def remote_ip
@remote_ip ||= (@env['HTTP_CF_CONNECTING_IP'] || remote_ip_orig)
end
end
end
Run Code Online (Sandbox Code Playgroud)
是否有一个类似的过程,以便在机架攻击中使用HTTP_CF_CONNECTING_IP作为req.ip?
我有兴趣使用https://github.com/kickstarter/rack-attack来扼杀滥用者和蛮力攻击者.我的应用程序运行在多个dynos上,所以我想Rails默认的FileStore并不完全有效,因为每个dyno都有一个文件系统,而且限制需要是两者的聚合.
如果我要使用memcached插件服务Rails.cache
,如果memcached服务关闭(例如,对FileStore),Rails中是否有"后备"?
如果没有,随着memcached服务的中断,rails应用程序将崩溃或用户无法访问(与优雅地处理错误相比)?
首先,我要说的是,我采取了一些措施来确保SQL注入攻击失败.所有SQL查询值都是通过活动记录预处理语句完成的,所有运算符(如果不是硬编码的)都是通过数字白名单系统完成的.意思是如果有人想通过"ILIKE"进行搜索,他们会传递6,如果他们想通过"="进行搜索,他们会传递1,等等.
我还定期使用Brakeman和Rails SQL Injection指南来查看代码.
因此,我希望阻止尝试的SQL注入器有三个原因.
目前我的想法是针对请求路径和参数运行一个简单的正则表达式匹配,以便标记最明目张胆的SQL注入尝试并将这些ips列入黑名单,所以使用机架攻击.
injection_regex = /SOMEREGEXHERE/
Rack::Attack.blacklist('sql injection blacklist') do |req|
Rack::Attack::Fail2Ban.filter(req.ip, :maxretry => 5, :findtime => 10.minutes, :bantime => 24.hours) do
CGI.unescape(req.query_string).match(injection_regex) || req.path.match(injection_regex)
end
end
Run Code Online (Sandbox Code Playgroud)
我的问题是创建一个正确的标记一个简单的SQL注入尝试的正则表达式,但不会导致常规用户的任何问题.我认为一些误报是可以的,这就是为什么上面的黑名单系统在第一场比赛后没有列入黑名单的原因.
在我的搜索中,我发现了很多关于这个问题的问题,但是它们似乎都是这样的,人们提出使用正则表达式来检测SQL注入的问题,另一个人回答你不应该以这种方式停止SQL注入,问这些问题的人回答他们不会使用正则表达式来停止,而只是为了检测,然后是一堆无用的评论.
那么,这样的正则表达式是否有可能仅仅作为一种检测手段,最小的误报,或者这样的兔子整体是否值得努力?
我正在使用机架攻击。如果有人超过限制,我将使用以下代码:
Rack::Attack.throttled_response = lambda do |env|
[429, {}, [ActionView::Base.new.render(file: 'public/429.html')]]
end
Run Code Online (Sandbox Code Playgroud)
当 sby 超过原始响应的 POST 请求的限制时respond_to :html
,渲染429.html
工作正常。当响应的 POST 请求超过限制respond_to :js
时,屏幕上没有任何反应,但如果我查看日志,一切似乎都很好:
Rendered public/429.html (1.4ms)
Run Code Online (Sandbox Code Playgroud)
429.html
在 的情况下如何显示js response
?是否有可能以error messages
某种方式从这个机架代码传递到 rails 应用程序?如果不是那么复杂,我可能会更改为error messages
from rendering
。
我使用了 Rack::Attack 的示例节流代码。
throttle('req/ip', limit: 100, period: 5.minutes) do |req|
req.ip unless req.path.starts_with?('/assets')
end
Run Code Online (Sandbox Code Playgroud)
这在我们的临时服务器上效果很好,但立即遇到了生产限制,因为 req.ip 返回我们的负载均衡器的 IP 地址,而不是客户端的 remote_ip。
请注意,remote_ip 是 ActionDispatch::Request 中的方法,而不是 Rack::Attack::Request 中的方法。
我们在 Ruby 2.2 上使用 Rails 3.2.2。
我正在使用机架攻击来阻止 IP。
# Block requests from 1.2.3.4
Rack::Attack.blocklist('block 1.2.3.4') do |req|
# Requests are blocked if the return value is truthy
'1.2.3.4' == req.ip
end
Run Code Online (Sandbox Code Playgroud)
成功封堵IP。该人可以查看左上角带有“禁止”字样的白页。有什么方法可以更改字符串“forbidden”吗?
编辑 :
尝试使用这个。我的所有其他错误页面也配置类似。 https://mattbrictson.com/dynamic-rails-error-pages 但它在机架攻击 403 禁止页面上不起作用。
我们一直在阅读基于表单的网站身份验证的权威指南,目的是防止快速登录尝试。
这方面的一个例子可能是:
指南中出现了其他方法,但它们都需要一个能够记录以前失败尝试的存储空间。
作为可能的解决方案,在本期的其中一篇文章中讨论了阻止列表(以旧名称 blacklisting 在文档中更改为阻止列表)。
根据 Rack::Attack 具体而言,一个简单的实现示例可能是:
登录失败的地方:
StorageMechanism.increment("bad-login/#{req.ip")
Run Code Online (Sandbox Code Playgroud)
在 rack-attack.rb 中:
Rack::Attack.blacklist('bad-logins') { |req|
StorageMechanism.get("bad-login/#{req.ip}")
}
Run Code Online (Sandbox Code Playgroud)
这里有两个部分,如果它被列入阻止,则返回响应并检查之前是否发生了失败的尝试(StorageMechanism)。
第一部分,返回响应,可以由 gem 自动处理。但是,我没有看到第二部分那么清楚,至少对于 gem 和 Rails 世界的缓存后端的事实上的选择,Redis。
据我所知,Redis 中过期的键会被自动删除。这将使得无法访问信息(即使已过期),为计数器设置一个新值并相应地增加不应期的超时。
有没有办法用 Redis 和 Rack::Attack 来实现这一点?
我在想,在这种情况下,“存储机制”可能必须保持绝对不可知,并且对 Rack::Attack 及其存储选择一无所知。
rackattack ×10
rack ×3
ruby ×3
heroku ×2
cloudflare ×1
devise ×1
ip-address ×1
memcached ×1
rack-cors ×1
regex ×1
rendering ×1
security ×1
throttling ×1