Change Value of Request.Remote_Ip in Ruby on Rails

Change value of request.remote_ip in Ruby on Rails

If you want this functionality in your whole application, it might be better/easier to override the remote_ip method in your app/helpers/application_helper.rb:

class ActionDispatch::Request #rails 2: ActionController::Request
def remote_ip
'1.2.3.4'
end
end

And the 1.2.3.4 address is available everywhere

how can I redefine the ruby and rails request.ip and request.remote_ip methods?

I believe request is an instance. But you are defining class methods. Remove the class << self nonsense and you instead be redefining instance methods.

Just a note though, this sounds kind of crazy. Be careful in there. Frameworks dont always like having their guts rearranged.


Your error message when using instance methods means something else is going on. super calls the superclass implementation. But when you reopen a class and override things, you are literally overwriting the original implementation. Since the method doesn't exist in the superclass, super doesn't work.

Instead you can use alias to save the original implementation before you declare the new method that would replace it.

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

Devise get remote_ip in model validator

Finally figured it out. The before_filter needed to be uncommented and the param added to the permit list.

class Users::RegistrationsController < Devise::RegistrationsController

before_filter :configure_sign_up_params, only: [:create]

def create
params[:user][:current_sign_in_ip] = request.remote_ip
super
end

protected

def configure_sign_up_params
devise_parameter_sanitizer.for(:sign_up) << :current_sign_in_ip
end

end

How to mock out remote_ip in a Rspec helper?

Answer

You can set the remote_ip in the helper with controller.request.remote_addr = '1.2.3.4'.

Example

Helper file:

module ApplicationHelper
def ip
request.remote_ip
end
end

Spec file:

require 'rails_helper'

RSpec.describe ApplicationHelper, type: :helper do
describe '#ip' do
it 'returns the IP' do
controller.request.remote_addr = '1.2.3.4'

expect(helper.ip).to eql '1.2.3.4'
end
end
end

Explanation

Helper specs mix in ActionView::TestCase::Behavior. This provides a helper object which mixes in the helper module being spec'd, along with ApplicationHelper. (In this case the module being spec'd is the ApplicationHelper).

When the helper spec is executed is sets the controller object to an ActionView::TestCase::TestController. The request object on this test controller is an ActionController::TestRequest.

Using the #remote_addr= setter on the test request, sets the "REMOTE_ADDR" key in the @env instance variable. The remote_ip uses the same "REMOTE_ADDR" key in the @env instance variable to retrieve the IP.

Rails ActionController: Difference between request.remote_ip and request.remote_addr

I'm the author of the current implementation of remote_ip, and the other things that it does include checking for IP spoofing attacks, and correctly handling multiple X-Forwarded-For headers. There's a big caveat, though: only some Ruby web servers support multiple headers, so the value still might be wrong.

I wrote up the results from testing the most popular Ruby app servers on my blog, which you might want to check out if repeated headers matter for your application.

How to log real client ip in rails log when behind proxy like nginx

In my opinion, your current approach is the only sane one. The only step that is missing is overwriting the IP address in env.

The typical REMOTE_ADDR seldom holds the correct IP if you've any amount of layers of proxies and load balancers and what not -- you're not unique in this respect. Each potentially adds or changes remote IP-related headers. And you cannot assume that each of those fields necessarily correspond to a single IP address, at that. Some will push or unshift an IP to a list instead.

There is only one way to know for sure which field holds the correct value and how, and that is to dive in there and look. You've evidently done that already. Now, just overwrite env['REMOTE_ADDR'] with its correct value using your Rack middleware. There's little point in letting any piece of code you didn't write log or process the wrong IP address, as is happening now.

(This being Ruby, you could also monkey patch Rack::Request, of course...)

For colorful reading that illustrate the varying degrees of which exotic setups can mess up attempts at finding a client's real IP address, see for instance the unending discussions that occurred about this for WordPress:

  • https://core.trac.wordpress.org/ticket/9235
  • https://core.trac.wordpress.org/ticket/4198
  • https://core.trac.wordpress.org/ticket/4602

It's PHP but the gist of the points raised apply equally well to Ruby. (Note that they're unresolved as I write this, too, and that they've been around for aeons.)

Get real IP address in local Rails development environment

As far as I can see there is no standard method for getting the remote address of your local machine. If you need the remote address for (testing) your geocoding, I suggest adding 127.0.0.1 to your database table that matches IP addresses with locations.

As a last resort you could also hard code your remote address. E.g. like this:

class ApplicationController < ActionController::Base
def remote_ip
if request.remote_ip == '127.0.0.1'
# Hard coded remote address
'123.45.67.89'
else
request.remote_ip
end
end
end

class MyController < ApplicationController
def index
@client_ip = remote_ip()
end
end


Related Topics



Leave a reply



Submit