dannymcc
dannymcc

Reputation: 3814

Whitelisting list of IPs with some subnets in Rails 3 application

I have been trying to work out the correct way of blocking access to our Rails 3 application except for a small number of IP addresses and a couple of IP subnets.

While looking for ways to do this I found this question/answer. The suggested code is as follows:

Application Controller

before_filter :protect

def protect
  @ips = ['127.0.0.1', '203.123.10.1'] #And so on ...]
  if not @ips.include? request.remote_ip
     # Check for your subnet stuff here, for example
     # if not request.remote_ip.include?('127.0,0')
     render :text => "You are unauthorized"
     return
  end
end

This works, so I've altered it to redirect to a static page rather than just the text message.

What I would like to do though, is allow access from local IP's on the same subnet as the Rails application server. The subnet is simply 192.168.1.0/24.

What is the easiest/cleanest way to add the subnet to the accepted IP's?

Upvotes: 2

Views: 1965

Answers (1)

user1549550
user1549550

Reputation:

To test if a given IP address foo is within a network specified by address net and mask mask, you would apply the mask to both the network address and the tested address, and see if the results are equal: foo & mask == net & mask . You have to first convert the IP address and the mask to integers. A mask of /24 is 24 bits set to 1 followed by 8 bits set to 0 - 0xFFFFFF00 or 255.255.255.0 in dotted quad notation.

before_filter :protect

def protect
  @ips = ['127.0.0.1', '192.168.1.0/24'] #And so on ...]
  allowed = false
  # Convert remote IP to an integer.
  bremote_ip = request.remote_ip.split('.').map(&:to_i).pack('C*').unpack('N').first
  @ips.each do |ipstring|
    ip, mask = ipstring.split '/'
    # Convert tested IP to an integer.
    bip = ip.split('.').map(&:to_i).pack('C*').unpack('N').first
    # Convert mask to an integer, and assume /32 if not specified.
    mask = mask ? mask.to_i : 32
    bmask = ((1 << mask) - 1) << (32 - mask)
    if bip & bmask == bremote_ip & bmask
      allowed = true
      break
    end
  end

  if not allowed
     render :text => "You are unauthorized"
     return
  end
end

Upvotes: 6

Related Questions