Prevent duplicate accounts from the same IP

I needed a way to prevent users from opening multiple accounts, so the best idea I had was to save their IP when they register and then check against existing IPs during registration.

Here's what I did.

In the start.php init() function of an existing custom plugin I have, I added:

// IP logging
register_elgg_event_handler('create', 'user', 'MYPLUGIN_log_ip');

Then, also in start.php, I had to define this new function:

   // Save IP address of new users
    function MYPLUGIN_log_ip($event, $object_type, $object)
    {
     if (($object) && ($object instanceof ElggUser))
     {
       $ip_address = $_SERVER['REMOTE_ADDR'];
       create_metadata($object->guid, 'ip_address', $ip_address, '', 0, ACCESS_PUBLIC);
     }
    }

Ok, so that's step 1.  Now the IP of every new user is saved as metadata.  The second step is using these saved IPs to prevent new accounts being added with existing IPs.

I'm using the Site Access plugin, so I modified the /MYDOMAIN.com/mod/siteaccess/views/default/account/forms/register.php file and added this near the top:

$ip_address = $_SERVER['REMOTE_ADDR'];
// find_metadata($meta_name="",$meta_value="",$entity_type=""",$entity_subtype="",$limit=10,$offset=0,$order_by="",$site_guid=0)
$ip_metadata = find_metadata("ip_address",$ip_address,"user");
 
if (is_array($ip_metadata))
  $form_body = '<br /><b>Error:</b><br />An account already exists for your IP address.<br /><br />If you feel this shouldn\'t be the case, please contact support</a>.';          
else
{

// normal Site Access logic

}

If you aren't using Site Access then I'd suggest you look at how it overrides the core registration form and mimic that in your own code.

So now I've prevented 99% of users from registering an account with an existing IP.  But I haven't prevented the "smart" haxxors that can spoof a POST or GET of an HTML form.  I've hidden the form but I haven't done anything to prevent someone from still triggering the action.

Rather than trying to override the core actions/register.php file (a hook wouldn't suffice because I need to prevent registration entirely, not just add a function after it happens), I decided to take the easy way out and just modify it.  So near the top I added this code:

// Validate IP already exists
    $ip_address = $_SERVER['REMOTE_ADDR'];
    // find_metadata($meta_name="",$meta_value="",$entity_type=""",$entity_subtype="",$limit=10,$offset=0,$order_by="",$site_guid=0)
    $ip_metadata = find_metadata("ip_address",$ip_address,"user");
 
  if (is_array($ip_metadata))
  {
    register_error("<b>Error:</b><br />An account already exists for your IP address.<br /><br />If you feel this shouldn't be the case, please contact support.");
    forward();
  }
  else
{

// normal action stuff

}

Hopefully that helps someone trying to do the same thing!  If anyone has a better method I'm all ears too.

  • What a nice person LOLZ ;-) posting your hard work coding for free for the rest of us who cannot $pay ;-O

    ( Cheers Kane.HTML^Kane.PHP ;-)

  • @Kane -- Interesting idea, but it raises a few issues.  The problem with IP filters is that 1) IP addreses change, 2) you can use a proxy force a change, and 3) multiple people behind proxies will have the same IP address and all be treated the same.  It unfortunately doesn't take too bright of a script kiddie to figure this out...

    This is what requiring a valid and unique email address attempts to avoid.  If you want, you could restrict email addresses to only those that don't offer free sign-ups, but that might be a pain too.  Depending on your audience, restricting by IP might be enough.  I'm not sure there is any way to be 100% positive that no two accounts are owned by the same person though...

  • @Brett - yup I realize that users behind the same WAN IP may have an issue, which is why I tell them to contact support if they don't believe they have an existing account.  As far as dynamic IPs, well there's no real way around that I'm aware of.

    I'm of the opinion that validating unique emails is almost meaningless with the multitudes of free email services, and also considering people who do web dev that own tons of domains and could create unique "non-free" emails on the fly.

    I agree, I don't think there is a way to be 100% positive, at least not until someone writes a retinal scan plugin ;)

  • @Kane that'd be an interesting one...and I'm being moderately serious.  A biometrics plugin that ties in to the fingerprint scanners on some laptops and other machines...Interesting, yes, but probably not overly practical, alas.

  • @Brett & @ Kane

    I believe that another area of this aspect does cover biometrics and kindred... TPM's.. Maybe someone might want to at least research read and we might have a wishlist PlugIn for Elgg...

  • This is a problem we have dealt with since the beginning of our site. Nasty Kiddy 1 gets banned from the site is then comes back on as Nasty kiddy 2 within 4 minutes.

    Banning ip's is out as mama and sis and little brother may also want an account, and they use the same router.

    Dynamic ips could end up wiping out a 100 potential members. anyone using a roving laptop or mobile (cell) phone, will have a different ip each time they connect.

    What's the answer? There is none (Ban Nasty kiddy 2) When you notice

    P.S. Thanks for the code and the work. I may be able to bend this to something I'm working on :-)

     

  • Hi Jack,

    I hear ya about banning "innocent" people behind the same router as a "guilty" person, as well as the dynamic IP issue.   I'm handling that by displaying this error message:

    Error:  It looks like you may already have an account with us.
    If you feel this isn't the case, please contact support and we'll be glad to look into it.

    Also, I don't expect my site to get much bigger than a few thousand members, and it's global, so the likelyhood of IPs colliding is very small.

    I think it'll be an adequate solution for my needs.

  • I had someone ask me how they could view the IPs of each user after logging them.   My answer is below -

    ------------------

    If you want to see the registered IP of each user, after you're using my code above to log the IPs, you could extend the Profile view so it was visible for each user on their profile page (but only visible to admin).

    Add this to start.php, perhaps in the Site Access plugin:

        // Extend Profile view
        extend_view('profile/status', 'siteaccess/profile');

    Then create a new file /mod/siteaccess/views/default/siteaccess/profile.php

    <?php

    // Only admins should see this
    if (isadminloggedin()
    {
      // Get GUID of the user who owns this profile
      $owner_guid = $vars['entity']->guid;
     
      // Get owner entity
      $owner_ent = get_entity($owner_guid);
     
      // Get IP address
      $ip_address = $owner_ent->ip_address;
     
      // Display IP address
      echo "<br /><br /><b>IP Address:</b> ".$ip_address;
    }                          

    ?>

    Hopefully that helps anyone else that's trying to do this.

  • $_server['remote_addr'] -- can extend this to also detect beyond the proxy.. we've doing some studies with users being banned, re-register, banned, re-register, re-register... so far we lucky and can 'recognize' them lolz *every time they come back. i'm working on an endless redirect loop for these nasty users.

  • "Zaptor" is a-coming.. to manage IP# related issues on security and banned users