views:

69

answers:

2

I'm looking at implementing IP Address filtering for my Rails SaaS app. In a nutshell I want administrators to be able to specify one or more IP Addresses (or a range of IP Addresses) and then my app only accept requests on their instance from the specified addresses.

I'm looking at using IPAddress (http://github.com/bluemonk/ipaddress) for the parsing/validating of each address/range of addresses. Is this a good fit or are there better/more appropriate libraries?

Has anyone implemented this kind of filtering who could describe an approach that has worked for them or are there any gotchas I need to worry about?

Alternatively, is there an existing Ruby library that handles all of this automatically that has managed to elude my Googling?

Many Thanks, Ash

+3  A: 

ipaddress is an awesome library (I know the author), but you won't probably need it unless you are planning to perform some advanced manipulation of IP Addresses.

In fact, the most simple way is to

  1. store the array of IP addresses to filter somewhere. You can use the string representation (192.168.1.1) or the long int representation. With the string version, you can even allow wildcards (192.168.1.*)

  2. then configure a before_filter in the controller that will load the list of banned IPs and perform a simple string match to check whether current request.ip_address matches a banned IP. If true, redirect to the error page.

As you can see, you don't even need to convert the IPs into IP objects, unless you need to perform other kind of manipulations.

Simone Carletti
What about cached pages?
Brian Maltzan
You can't use cached pages unless you implement a filtering system at server level.
Simone Carletti
Thanks for the answer Simone. I was considering using ipaddress mainly for the parsing of the ip addresses - they will be user supplied so I wanted to be able to validate them. As far as I can tell, IP Addresses look to be a bit more complicated than I realised so I didn't want to get in to parsing them! Have I read something that has worried me unnecessarily - is it sufficient to just use a regexp to match the standard pattern?
Ash
IPAddress provides a `valid?` method you can use to validate the input.
Simone Carletti
+1  A: 

I think you can achieve what you want using Rails 3 built-in routing features. Gregg Pollack introduces Rails 3 Action Dispatch and mentions (from the screencast) :constraints => {:ip => /192\.168\.1\.\d{1,3}}/} option where you can supply a regular expression matching the IP address range you want to allow.

Extending that a bit more, looking at the Advanced constraints and their example demonstrates pulling a list of blacklisted IPs out from the database and checking if the request.remote_ip is in the list of blacklisted IPs. It looks like you want a list of accepted (aka whitelist IPs) but the code would be nearly identical to the example in Rails guides.

So I would build your admin view to be able to input approved IP addresses, then the application routing can pull this list for incoming requests.

Andy Atkinson
In this way you can't implement a user-based filtering system. In other words, you can't supply a different blacklist for different users because the condition is a routing level and applies to any request regardless the user account.
Simone Carletti
Oh, ok, now I see that lower down in his follow-up post. Reading his original post, I thought the IP's were entered by an admin on the back-end.
Andy Atkinson