iluvperl has asked for the wisdom of the Perl Monks concerning the following question:

Need to check all users travelling my web site for their IP address and then see if any other connection via their IP range is seen.

I thought I could do this by s/// the final octet of the IP and then check to see if it exists already, but that logic fails, of course, because it'd fail even if the same IP appeared twice.

I guess I'll need to store the entire IP address and see if an IP with a different last octet is seen. This must be really easy but the logic is just playing with my head.

I think I will be using MYSQL to store all the information (ips, timestamps, etc).

What I really want to do is check to see if the user's IP was seen already using a bot (meaning the same IP range but different numbers at the end) and then block them if two or more users on the same IP range were seen in the past 1 minute.

Any helpful pointers on what data to store to compare with and everything would be great. If this would be easier to do using DB_File, I think I'd rather use that instead.

Replies are listed 'Best First'.
Re: blocking last ip octet
by Anonymous Monk on Feb 22, 2006 at 23:31 UTC
    If your planning on storing the IP addresses in a table, you can use the database to do the work for you.
    If you set up your table with oct1, oct2, oct3, oct4 as four separate fields, the query is fairly straight forward.
    SELECT DISTINCT oct1, oct2, oct3, oct4 INTO #tempCheckIP FROM ipLog WHERE timestamp BETWEEN '2006/01/01' AND '2006/02/01' SELECT oct1, oct2, oct3, count(oct4) AS [Count] FROM #tempCheckIP GROUP BY oct1, oct2, oct3 ORDER BY [Count] DESC DROP TABLE #tempCheckIP
    (NOTE: I tried it on MSDE, not MySQL, but I think the syntax is compatible)

    That being said, I don't think that is going to be an effective way of detecting a bot. Your probably are going to block legitimate users who happen to be accessing the server from behind the same proxy at the same time.
Re: blocking last ip octet
by leighsharpe (Monk) on Feb 23, 2006 at 03:34 UTC
    Let MySQL do all the work:
    An IP address is simply a 32-bit number. It can be converted to it's numerical equivalent a little like this:
    my @octets=split(/\./,$ip_address); my $numerical_address=($octets[3]+(255*$octets[2])+(65535*$octets[1])+ +(16777216*$octets[0]));
    Store this in your database as a 32-bit integer, which is much more eficient than an 18-byte character field for IP address.
    Then, to see if another IP address is in the same class C, do something like this:
    SELECT count(*) from table WHERE (int(ip/256)*256) = (int($ip_address_ +to_be_compared_to/256)*256)
    Any result greater than 0 is a hit.
    Note that the figure of 256 is for a class C subnet. It can be changed to suit any subnet mask you want to use.
    Edit: Oops, that should be 256, not 255.....
Re: blocking last ip octet
by leocharre (Priest) on Feb 22, 2006 at 20:59 UTC

    why don't you log it to STDERR or something.. grep it out.. the logs have timestamp and ip by default

    # cat /var/log/apache/error-log maybe?