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.

  • I know this is an old topic and applies to earlier versions, I also know about all the cons of such a feature, but I really would like to implement such a thing on my elgg 1.8.x site.

    Are there not any plugins that can do what the title suggests?

    I have loads of spammy posts coming from multiple users on a single ip I assume it is because I have the spam throttle plugin activated which suspends a user when they exceed their limit. So I suspect that as soon as they detect that they have been suspended they open a new account.

    The problem is as soon as I delete them all and deny the ip in .htaccess the spammer uses another ip instead and I'm back to square one.

    Can anyone help?

  • @sitemaster: I thnk the Spam Login Filter plugin has an IP blacklist feature (http://community.elgg.org/plugins/774755/1.8.3/spam-login-filter).

  • @iionly yes I'm afraid to say I already have that installed as well.

    As I said the problem is the spammer keeps changing his IP address so that plug-in isn't very helpful in my case.

    The thing is the spammer has discovered the spam throttle on my site and so as soon as he exceeds his limit on that account he opens another account using the same ip address. Therefore overnight I can wake up to 1000 spammy posts under 500 accounts from the one ip address.

    If there was a plug-in available that allowed me to restrict one account per ip address, that might help.

  • Have you also installed the ip-tracker-plugin (http://community.elgg.org/plugins/446342/1.8.1/ip-address-tracker-plugin). I think this plugin might be necessary for the IP blacklisting to work. The option I'm referring to is at the bottom of the setting page of the Spam login filter plugin:

    IP Blacklist

    Blacklisted IPs can navigate into site, but will see the error '403 error - Access denied' in registration page.

    I think this is exactly what you are looking for, i.e. you can't register again using the same IP address when you have formerly being kicked out already. The IP addresses are only cached 1 week though. Maybe this is too short in your case? If in doubt I would suggest you ask directly on the Spam login filter plugin page. Maybe the IP blacklisting fails to work for some reason. Ray J should know best what's going on and in case there really is something not working correctly he might fix it and release an updated version.

  • @iionly yes sorry I have that as well. I should really have listed all the spam plug-in I have installed in my first post, so to catch up I already have the following installed:-

    captcha, honeypot, spam_login_filter, spam_throttle and finally the tracker you suggested

  • Half of the above code is still valid. Create a new elgg plugin with just a start.php and a manifest.xml file. 

    Copy the step1 code to the start.php

    For step 2, use the following code (PS : CODE NOT TESTED)

    elgg_register_plugin_hook_handler("action", 'register', 'register_action_hook',1);

    function register_action_hook($hook, $entity_type, $returnvalue, $params) {
    $ip_address = $_SERVER['REMOTE_ADDR'];
    if($ip_address){
    $user = elgg_get_entities_from_metadata(array('type'=>'user', 'limit'=>1, 'metadata_name'=> 'ip_address', 'metadata_value'=>$ip_address)
    if($user){
    register_error(elgg_echo('duplicate:account:exists'));
    forward(REFERER);
    }
    }
    }

  • @Team Webgalli I assume the code for step two should be placed near the top of mysite.com/actions/register.php is that correct?

    If so I have completed step one and two and tested it, it has prevented me from registering a second account although on submit the browser sends me to mysite.com/actions/register with a blank white screen and no 'duplicate:account:exists' message.

  • adc

    just one thing: are you certain that all your genuine users have the static ip addresses? i only say this in order to remind people that in fact, most computer users (in the uk certainly) have dynamic addresses, and are changeable from session to session, provided by their isp. the isp simply buys a whole bunch of ip addresses between certain ranges and assigns them at random.. on a per session basis. this means that a user could sign up to your site from one ip address, and later be banned under a different ip, but if you only allow one sign up from any ip address, and/or ban by ip, no-one else will be able to sign up if they are assigned that ip. you could therefore be closing your site to thousands of other genuine users. 

  • adc

    you could offer your own email service, then prevent users joining that are with other email providers. if you make them pay for the email service it discourages them from misbehaving.

  • I just want to make sure I have Team Webgalli code in the right place first.

    But yes I have also given alternatives some thought, perhaps if the spam throttle plugin was able to add the ip address to the banned list when a user exceeds their limit that too would prevent them from opening a new account.

    In fact it seems I have overlooked a section of the spam throttle plugin. In settings I have found a section

    spam_login_filter_ip Limit

    with two boxes "Maximum number of spam_login_filter_ip allowed" and "Time interval in minutes" but with no documentation it is difficult to know what this section does exactly.

    Any ideas?