rack_attack.rb 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. THROTTLE_PUBLIC_ENDPOINTS = [
  3. {
  4. url: '/api/v1/users/password_reset'.freeze,
  5. field: 'username',
  6. },
  7. {
  8. url: '/api/v1/users/email_verify_send'.freeze,
  9. field: 'email',
  10. },
  11. {
  12. url: '/api/v1/users/admin_password_auth'.freeze,
  13. field: 'username',
  14. },
  15. ].freeze
  16. THROTTLE_PUBLIC_ENDPOINTS.each do |config|
  17. Rack::Attack.throttle("limit #{config[:url]} requests per #{config[:field]}", limit: 3, period: 1.minute.to_i) do |req|
  18. if req.path.start_with?(config[:url]) && req.post?
  19. # Normalize to protect against rate limit bypasses.
  20. req.params[config[:field]].to_s.downcase.gsub(%r{\s+}, '')
  21. end
  22. end
  23. Rack::Attack.throttle("limit #{config[:url]} requests per source IP address", limit: 3, period: 1.minute.to_i) do |req|
  24. if req.path.start_with?(config[:url]) && req.post?
  25. req.ip
  26. end
  27. end
  28. end
  29. #
  30. # Throttle form submit requests
  31. #
  32. API_V1_FORM_SUBMIT_PATH = '/api/v1/form_submit'.freeze
  33. form_limit_by_ip_per_hour_proc = proc { Setting.get('form_ticket_create_by_ip_per_hour') || 20 }
  34. Rack::Attack.throttle('form submits per IP and hour', limit: form_limit_by_ip_per_hour_proc, period: 1.hour.to_i) do |req|
  35. if req.path.start_with?(API_V1_FORM_SUBMIT_PATH)
  36. req.ip
  37. end
  38. end
  39. form_limit_by_ip_per_day_proc = proc { Setting.get('form_ticket_create_by_ip_per_day') || 240 }
  40. Rack::Attack.throttle('form submits per IP and day', limit: form_limit_by_ip_per_day_proc, period: 1.day.to_i) do |req|
  41. if req.path.start_with?(API_V1_FORM_SUBMIT_PATH)
  42. req.ip
  43. end
  44. end
  45. form_limit_per_day_proc = proc { Setting.get('form_ticket_create_per_day') || 5000 }
  46. Rack::Attack.throttle('form submits per day', limit: form_limit_per_day_proc, period: 1.day.to_i) do |req|
  47. if req.path.start_with?(API_V1_FORM_SUBMIT_PATH)
  48. req.path
  49. end
  50. end