Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/52.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何重新定义ruby和rails request.ip和request.remote_ip方法?_Ruby On Rails_Ruby_Rack - Fatal编程技术网

Ruby on rails 如何重新定义ruby和rails request.ip和request.remote_ip方法?

Ruby on rails 如何重新定义ruby和rails request.ip和request.remote_ip方法?,ruby-on-rails,ruby,rack,Ruby On Rails,Ruby,Rack,我有一个rails应用程序,我正在尝试重载request.remote_ip和request.ip,以便使用cloudflare头文件(HTTP_CF_CONNECTING_ip),如果它存在的话。。。 我试过这些,但都不管用: module Rack class Request class << self def ip @ip ||= (@env['HTTP_CF_CONNECTING_IP'] || super) end

我有一个rails应用程序,我正在尝试重载request.remote_ip和request.ip,以便使用cloudflare头文件(HTTP_CF_CONNECTING_ip),如果它存在的话。。。 我试过这些,但都不管用:

module Rack
  class Request
    class << self
      def ip
        @ip ||= (@env['HTTP_CF_CONNECTING_IP'] || super)
      end
    end
  end
end

module ActionDispatch
  class Request < Rack::Request
    class << self
      def remote_ip
        @remote_ip ||= (@env['HTTP_CF_CONNECTING_IP'] || super)
      end
    end
  end
end
在应用程序中,因为我有一些其他的gem(比如designe)使用request.ip


谢谢大家!

我相信
请求
就是一个例子。但是您正在定义类方法。删除
类如果您想使用CloudFlare并检测真正的IP,就像我在没有KingX或Apache模块的情况下所做的那样,这种猴子补丁方法是一个非常糟糕的主意,这将在将来导致意外的结果。您最好使用应该使用的中间件。这是我提出并实施的一个方案

模块机架
类CloudFlareFixup
def初始化(应用程序)
@app=app
结束
def呼叫(环境)
if env['HTTP\u CF\u CONNECTING\u IP']
env['HTTP_X_FORWARDED_FOR']=env['HTTP_CF_CONNECTING_IP']
env['REMOTE\u ADDR']=env['HTTP\u CF\u CONNECTING\u IP']
结束
@应用程序调用(环境)
结束
结束
结束
只需将其添加到application.rb中即可

config.middleware.insert_before(0, Rack::CloudFlareFixup)

你可以在

上看到这个问题的完整要点。我尝试了许多解决这个问题的方法。以下是我的发现:

  • cloudflare rails
    gem=>这将ip和远程ip设置为原始ip。我希望ip代表它来自的cloudflare ip,远程ip代表用户的原始ip,所以这对我来说不起作用。它每12小时查找一次Cloudflare IP范围列表,并将其添加到受信任的\u代理中。然后用cloudflare trusted proxy对:-
    ActionDispatch::Request.ip
    ActionDispatch::Request.remote\u ip
    Rack::Attack::Request.trusted\u proxy?
    进行修补,以便ip和remote\u ip忽略它们,并使用发起请求的用户的原始ip
  • actionpackcloudflare
    gem=>这要简单得多。它所做的只是直接设置
    ActionDispatch.remote_ip=@env['HTTP\u CF\u CONNECTING_ip']
    ,这符合Cloudflare最佳推荐的最佳实践,但似乎不值得为一行代码使用gem
  • 手卷
最后,我想阻止非代理请求

# config/initializers/rack_attack.rb
class Rack::Attack
  class Request < ::Rack::Request
    # Create a remote_ip method for rack request by setting it equal to the cloudflare connecting ip header
    # To restore original visitor IP addresses at your origin web server, Cloudflare recommends your logs or applications
    # look at CF-Connecting-IP instead of X-Forwarded-For since CF-Connecting-IP has a consistent format containing only one IP.
    # https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-CloudFlare-handle-HTTP-Request-headers-
    def remote_ip
      @remote_ip ||= (env['HTTP_CF_CONNECTING_IP'] || ip).to_s
    end

    # This checks the request IP against Cloudflare IP ranges and the action dispatch default trusted proxies.
    # These include various local IPs like 127.0.0.1 so that local requests won't be blocked.
    def proxied?
      Rails.application.config.action_dispatch.trusted_proxies.any? { |range| range === ip }
    end
  end

  # Block all requests coming from non-Cloudflare IPs
  blocklist("block non-proxied requests in production") do |req|
    if req.proxied?
      false
    else
      req.log :warn
      true
    end
  end
end
#config/initializers/rack#u attack.rb
类Rack::攻击
类请求<::机架::请求
#通过将其设置为cloudflare连接ip标头,为机架请求创建远程ip方法
#要恢复原始web服务器上的原始访问者IP地址,Cloudflare建议您使用日志或应用程序
#请看CF连接IP,而不是X-Forwarded-For,因为CF连接IP的格式是一致的,只包含一个IP。
# https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-CloudFlare-handle-HTTP-Request-headers-
def远程_ip
@远程| ip |=(env['HTTP_CF_CONNECTING_ip']| ip)。到
结束
#这将根据Cloudflare IP范围和操作分派默认受信任代理检查请求IP。
#其中包括各种本地IP,如127.0.0.1,这样本地请求就不会被阻止。
def代理?
Rails.application.config.action\u dispatch.trusted\u proxies.any?{|范围|范围===ip}
结束
结束
#阻止来自非Cloudflare IP的所有请求
区块列表(“在生产中阻止非代理请求”)do | req|
如果需要代理?
假的
其他的
请求日志:警告
真的
结束
结束
结束

为什么要重新定义这些方法以指向通常不包含IP地址信息的标头?对不起,我的错误(我复制并粘贴了代码,试图查看它是否加载了某些值)。。。正确的头值是HTTP\u CF\u CONNECTING\u IP,它是在cloudflare下根据请求设置的。我也尝试过删除类,我也尝试过,问题是头值不存在时。由于“super”,它会抛出一个错误:!!处理请求时出现意外错误:super:no superclass method'ip'for#别名之间不应该有逗号:
alias:remote\u ip\u orig:remote\u ip
我应该将该模块放在哪个目录中?您的中间件应该放在
ActionDispatch::RemoteIp
中间件的正前方,而不是机架顶部堆叠
使用config.middleware.insert_before(ActionDispatch::RemoteIp,Rack::CloudFlareFixup)
这样
使用ActionDispatch::ShowExceptions
ActionDispatch::DebugExceptions
可以在中间件处理请求之前捕获应用程序路由异常。您可以在rails api上阅读更多关于
ActionDispatch::RemoteIp
的信息:这个答案应该通过一个链接更新到他的更新要点:
config.middleware.insert_before(0, Rack::CloudFlareFixup)
# config/initializers/cloudflare.rb

# These values should rarely or never change and Cloudflare should alert us before that happens.
# The list of Cloudflare proxy server ip ranges comes from https://www.cloudflare.com/ips/
CLOUDFLARE_IP_RANGES = [IPAddr.new("103.21.244.0/22"),IPAddr.new("103.22.200.0/22"),IPAddr.new("103.31.4.0/22"),IPAddr.new("104.16.0.0/12"),IPAddr.new("108.162.192.0/18"),IPAddr.new("131.0.72.0/22"),IPAddr.new("141.101.64.0/18"),IPAddr.new("162.158.0.0/15"),IPAddr.new("172.64.0.0/13"),IPAddr.new("173.245.48.0/20"),IPAddr.new("188.114.96.0/20"),IPAddr.new("190.93.240.0/20"),IPAddr.new("197.234.240.0/22"),IPAddr.new("2405:8100::/32"),IPAddr.new("2405:b500::/32"),IPAddr.new("2606:4700::/32"),IPAddr.new("2803:f800::/32"),IPAddr.new("2a06:98c0::/29"),IPAddr.new("2c0f:f248::/32")
]

# By adding the cloudflare IP ranges as trusted_proxies, rails ignores those IPs when setting remote_ip and correctly sets it to the originating IP
Rails.application.config.action_dispatch.trusted_proxies = CLOUDFLARE_IP_RANGES + ActionDispatch::RemoteIp::TRUSTED_PROXIES
# config/initializers/rack_attack.rb
class Rack::Attack
  class Request < ::Rack::Request
    # Create a remote_ip method for rack request by setting it equal to the cloudflare connecting ip header
    # To restore original visitor IP addresses at your origin web server, Cloudflare recommends your logs or applications
    # look at CF-Connecting-IP instead of X-Forwarded-For since CF-Connecting-IP has a consistent format containing only one IP.
    # https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-CloudFlare-handle-HTTP-Request-headers-
    def remote_ip
      @remote_ip ||= (env['HTTP_CF_CONNECTING_IP'] || ip).to_s
    end

    # This checks the request IP against Cloudflare IP ranges and the action dispatch default trusted proxies.
    # These include various local IPs like 127.0.0.1 so that local requests won't be blocked.
    def proxied?
      Rails.application.config.action_dispatch.trusted_proxies.any? { |range| range === ip }
    end
  end

  # Block all requests coming from non-Cloudflare IPs
  blocklist("block non-proxied requests in production") do |req|
    if req.proxied?
      false
    else
      req.log :warn
      true
    end
  end
end