Ruby and Rails
Check and report with Net::HTTP, and block in Rails with Rack::Attack.
The standard library is enough to check and report. In Rails, plug the check into Rack::Attack, which most apps already use for throttling.
Check and report
require "net/http"
require "json"
ISIPSAFE = URI("https://isipsafe.com")
def isipsafe_score(ip)
uri = URI.join(ISIPSAFE, "/api/v1/check")
uri.query = URI.encode_www_form(ip: ip)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true, open_timeout: 2, read_timeout: 3) do |http|
http.get(uri.request_uri)
end
res.is_a?(Net::HTTPSuccess) ? JSON.parse(res.body).dig("data", "abuseConfidenceScore").to_i : 0
rescue StandardError
0 # fail open
end
def isipsafe_report(ip, categories, comment = "")
uri = URI.join(ISIPSAFE, "/api/v1/report")
req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer #{ENV.fetch('ISIPSAFE_KEY')}")
req.set_form_data(ip: ip, categories: categories.join(","), comment: comment)
Net::HTTP.start(uri.host, uri.port, use_ssl: true, open_timeout: 2, read_timeout: 5) { |http| http.request(req) }
end
isipsafe_report("203.0.113.50", %w[web-app-attack brute-force], "40 failed logins in 5 minutes")
Block in Rails with Rack::Attack
In config/initializers/rack_attack.rb, block listed addresses on the login and sign-up endpoints, caching each score for an hour:
Rack::Attack.blocklist("isipsafe listed") do |req|
next false unless req.post? && %w[/users/sign_in /users].include?(req.path)
score = Rails.cache.fetch("isipsafe:#{req.ip}", expires_in: 1.hour) { isipsafe_score(req.ip) }
score >= 75
end
Pair it with Rack::Attack's track or your Devise failure hooks to call isipsafe_report for addresses that keep failing.
Need a hand?
If something here does not work with your version of Ruby and Rails, or you have improved it, tell us. We update these pages with what people send.
Ruby and Rails and its logo are trademarks of their respective owners. isipsafe is not affiliated with or endorsed by them.