-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit aee7bd4
Showing
18 changed files
with
1,521 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# TPU: Detect and Block Spam Registrations | ||
|
||
This XenForo addon uses custom detection methods to identify automated and manual registrations that are trying to spam your forum. | ||
|
||
You may score based on: | ||
|
||
Visitor's country | ||
E-Mail address | ||
E-Mail length | ||
Username | ||
IP hostname | ||
Internet Provider name | ||
Open TCP port (requires PHP-sockets extension) | ||
StopForum Spam API | ||
Project Honeyport API | ||
TOR client detection | ||
|
||
Visit the addon's page: https://xenforo.com/community/resources/tpu-detect-and-block-spam-registrations.2973/ |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<?php | ||
|
||
class TPUDetectSpamReg_AS | ||
{ | ||
static function reverseIP($ip) | ||
{ | ||
$parts=explode('.', trim($ip)); | ||
if (count($parts)!=4) | ||
return false; | ||
|
||
$parts=array_map('intval', $parts); | ||
$parts=array_reverse($parts); | ||
|
||
return implode('.', $parts); | ||
} | ||
|
||
static function reverseIPv6($ip) | ||
{ | ||
$addr = inet_pton($ip); | ||
$unpack = unpack('H*hex', $addr); | ||
$hex = $unpack['hex']; | ||
return implode('.', array_reverse(str_split($hex))); | ||
} | ||
|
||
static function isIPv6($ip) | ||
{ | ||
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); | ||
} | ||
|
||
static function getASNameAndNumber($ip, &$asNumber, &$asName) | ||
{ | ||
if (self::isIPv6($ip)) | ||
$dns=dns_get_record(self::reverseIPv6($ip).'.origin6.asn.cymru.com', DNS_TXT); | ||
else | ||
$dns=dns_get_record(self::reverseIP($ip).'.origin.asn.cymru.com', DNS_TXT); | ||
|
||
if ((is_array($dns)) && (isset($dns[0]))) | ||
{ | ||
$items=explode('|', $dns[0]['txt'], 2); | ||
$items=array_shift($items); | ||
$asNumber=intval($items); | ||
if ($asNumber>0) | ||
{ | ||
$dns=dns_get_record('AS'.$asNumber.'.asn.cymru.com', DNS_TXT); | ||
if ((is_array($dns)) && (isset($dns[0]))) | ||
{ | ||
$tokens=explode('|', $dns[0]['txt']); | ||
$asName=trim($tokens[4]); | ||
|
||
return TRUE; | ||
} | ||
} | ||
} | ||
|
||
return FALSE; | ||
|
||
// Old slow code | ||
try { | ||
$networkinfo=json_decode(file_get_contents('https://stat.ripe.net/data/network-info/data.json?resource='.$ip)); | ||
$asNumber=$networkinfo->data->asns[0]; | ||
$asInfo=json_decode(file_get_contents('https://stat.ripe.net/data/as-overview/data.json?resource=AS'.$asNumber)); | ||
$asName=$asInfo->data->holder; | ||
|
||
return TRUE; | ||
} catch (Exception $e) {}; | ||
|
||
return FALSE; | ||
} | ||
|
||
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model) | ||
{ | ||
$o=XenForo_Application::getOptions(); | ||
|
||
if (trim($o->TPUDetectSpamRegAS)!='') | ||
{ | ||
if (self::getASNameAndNumber($user['ip'], $asNumber, $asName)) | ||
{ | ||
if ($verbose) | ||
$model->logScore('tpu_detectspamreg_as_detected', 0, array('number'=>$asNumber, 'name'=>$asName)); | ||
|
||
foreach (explode("\n", $o->TPUDetectSpamRegAS) as $entry) | ||
{ | ||
$entry=explode('|', trim($entry)); | ||
if (count($entry)!=2) | ||
continue; | ||
|
||
list($points, $match)=$entry; | ||
|
||
if ((is_numeric($match)) && ($match>0)) | ||
{ | ||
if ((int)$match==(int)$asNumber) | ||
{ | ||
$model->logScore('tpu_detectspamreg_as_fail', $points, array('number'=>$asNumber, 'name'=>$asName)); | ||
if (is_numeric($points)) | ||
$score['points']+=$points; | ||
else | ||
$score[$points]=true; | ||
} | ||
} else | ||
{ | ||
$asName=strtok($asName, ' '); | ||
$regex=$model->buildWildcardRegex($match); | ||
|
||
if (preg_match('/^'.$regex.'$/iU', $asName)) | ||
{ | ||
$model->logScore('tpu_detectspamreg_as_fail', $points, array('number'=>$asNumber, 'name'=>$asName)); | ||
if (is_numeric($points)) | ||
$score['points']+=$points; | ||
else | ||
$score[$points]=true; | ||
} else | ||
if ($debug) | ||
$model->logScore('tpu_detectspamreg_as_ok', 0, array('number'=>$asNumber, 'name'=>$match)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
|
||
class TPUDetectSpamReg_Cleanup | ||
{ | ||
public static function cleanup() | ||
{ | ||
$o=XenForo_Application::getOptions(); | ||
|
||
// Remove permanently banned users from user-permissions to improve performance | ||
$userIds=XenForo_Application::getDb()->fetchAll('SELECT xf_permission_entry.user_id FROM xf_permission_entry LEFT JOIN xf_user ON xf_permission_entry.user_id=xf_user.user_id LEFT JOIN xf_user_ban ON xf_permission_entry.user_id=xf_user_ban.user_id WHERE permission_id="TPUSpamRegModAllPosts" AND xf_permission_entry.user_id!=0 AND end_date=0'); | ||
foreach($userIds as $row) | ||
{ | ||
$permissions=array('general'=>array('TPUSpamRegModAllPosts'=>'unset')); | ||
XenForo_Model::create('XenForo_Model_Permission')->updateGlobalPermissionsForUserCollection($permissions, 0, $row['user_id']); | ||
} | ||
|
||
// Permanently delete users who have made no posts and haven't logged on for x days | ||
if ($o->TPUDetectSpamRegScoreModPosts['purgedays']>0) | ||
{ | ||
$userIds=XenForo_Application::getDb()->fetchAll('SELECT xf_permission_entry.user_id FROM xf_permission_entry LEFT JOIN xf_user ON xf_permission_entry.user_id=xf_user.user_id WHERE permission_id="TPUSpamRegModAllPosts" AND xf_permission_entry.user_id!=0 AND message_count=0 AND last_activity<UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL ? DAY))', array($o->TPUDetectSpamRegScoreModPosts['purgedays'])); | ||
|
||
foreach($userIds as $row) | ||
{ | ||
// Let's make sure the user has no deleted posts | ||
$hasPosts=XenForo_Application::getDb()->fetchOne('SELECT user_id FROM xf_post WHERE user_id=?', $row['user_id']); | ||
if ($hasPosts!==FALSE) | ||
continue; | ||
|
||
$writer = XenForo_DataWriter::create('XenForo_DataWriter_User', XenForo_DataWriter::ERROR_EXCEPTION); | ||
$writer->setExistingData($row); | ||
$writer->delete(); | ||
} | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
upload/library/TPUDetectSpamReg/ControllerPublicRegister.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
class TPUDetectSpamReg_ControllerPublicRegister extends XFCP_TPUDetectSpamReg_ControllerPublicRegister | ||
{ | ||
protected function _completeRegistration(array $user, array $extraParams = array()) | ||
{ | ||
$result=parent::_completeRegistration($user, $extraParams); | ||
|
||
if (class_exists('TPUDetectSpamReg_ModelSpamPrevention', false)) | ||
{ | ||
if (TPUDetectSpamReg_ModelSpamPrevention::$moderateAllPosts) | ||
{ | ||
$permissions=array('general'=>array('TPUSpamRegModAllPosts'=>'allow')); | ||
$this->getModelFromCache('XenForo_Model_Permission')->updateGlobalPermissionsForUserCollection($permissions, 0, $user['user_id']); | ||
} | ||
} | ||
|
||
return $result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
|
||
class TPUDetectSpamReg_Email | ||
{ | ||
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model) | ||
{ | ||
$o=XenForo_Application::getOptions(); | ||
|
||
if (trim($o->TPUDetectSpamRegEmail)!='') | ||
{ | ||
$email=$user['email']; | ||
|
||
foreach (explode("\n", $o->TPUDetectSpamRegEmail) as $entry) | ||
{ | ||
$entry=explode('|', trim($entry)); | ||
if (count($entry)!=2) | ||
continue; | ||
|
||
list($points, $match)=$entry; | ||
|
||
$regex=$model->buildWildcardRegex($match); | ||
|
||
if (preg_match('/^'.$regex.'$/iU', $email)) | ||
{ | ||
$model->logScore('tpu_detectspamreg_email_fail', $points, array('email'=>$match)); | ||
if (is_numeric($points)) | ||
$score['points']+=$points; | ||
else | ||
$score[$points]=true; | ||
} else | ||
if ($debug) | ||
$model->logScore('tpu_detectspamreg_email_ok', 0, array('email'=>$match)); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
|
||
class TPUDetectSpamReg_EmailLength | ||
{ | ||
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model) | ||
{ | ||
$o=XenForo_Application::getOptions(); | ||
|
||
$items=explode('@', $user['email']); | ||
$email=array_shift($items); | ||
|
||
if (trim($o->TPUDetectSpamRegEmailLen20)!=0) | ||
{ | ||
if (strlen($email)>=20) | ||
{ | ||
$model->logScore('tpu_detectspamreg_emaillen_fail', $o->TPUDetectSpamRegEmailLen20, array('length'=>20, 'email'=>$email)); | ||
$score['points']+=$o->TPUDetectSpamRegEmailLen20; | ||
return; | ||
} else | ||
if ($debug) | ||
$model->logScore('tpu_detectspamreg_emaillen_ok', 0, array('length'=>20, 'email'=>$email)); | ||
} | ||
|
||
if (trim($o->TPUDetectSpamRegEmailLen15)!=0) | ||
{ | ||
if (strlen($email)>=15) | ||
{ | ||
$model->logScore('tpu_detectspamreg_emaillen_fail', $o->TPUDetectSpamRegEmailLen15, array('length'=>15, 'email'=>$email)); | ||
$score['points']+=$o->TPUDetectSpamRegEmailLen15; | ||
return; | ||
} else | ||
if ($debug) | ||
$model->logScore('tpu_detectspamreg_emaillen_ok', 0, array('length'=>15, 'email'=>$email)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
class TPUDetectSpamReg_HoneyPot | ||
{ | ||
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model) | ||
{ | ||
$o=XenForo_Application::getOptions(); | ||
|
||
if ($o->TPUDetectSpamRegHoneyPotEnabled) | ||
{ | ||
// Only IPv4 supported | ||
if (filter_var($user['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)==FALSE) | ||
return; | ||
|
||
$dnsBl=new XenForo_DnsBl($o->TPUDetectSpamRegHoneyPotAPIKey.'.%s.dnsbl.httpbl.org'); | ||
$res=$dnsBl->checkIp($user['ip']); | ||
if (is_array($res)) | ||
{ | ||
if ($res[0]=='127') | ||
{ | ||
$lastSeen=intval($res[1]); | ||
$threatLevel=intval($res[2]); | ||
|
||
if ($lastSeen<$o->TPUDetectSpamRegHoneyPotCutoff) | ||
{ | ||
$scoreToGive=0; | ||
|
||
if (($threatLevel>=10) && ($threatLevel<20)) | ||
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore10; | ||
elseif (($threatLevel>=20) && ($threatLevel<40)) | ||
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore20; | ||
elseif (($threatLevel>=40) && ($threatLevel<60)) | ||
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore40; | ||
elseif (($threatLevel>=60) && ($threatLevel<80)) | ||
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore60; | ||
elseif (($threatLevel>=80) && ($threatLevel<100)) | ||
$scoreToGive=$o->TPUDetectSpamRegHoneyPotScore80; | ||
|
||
if ($scoreToGive!=0) | ||
{ | ||
$model->logScore('tpu_detectspamreg_honeypot_fail', $scoreToGive, array('lastseen'=>$lastSeen, 'threatlevel'=>$threatLevel)); | ||
$score['points']+=$scoreToGive; | ||
} else | ||
$model->logScore('tpu_detectspamreg_honeypot_pass', 0, array('lastseen'=>$lastSeen, 'threatlevel'=>$threatLevel)); | ||
} else | ||
$model->logScore('tpu_detectspamreg_honeypot_ok', 0); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
class TPUDetectSpamReg_Hostname | ||
{ | ||
static function getRegSpamScore(&$score, array $user, $verbose, $debug, $model) | ||
{ | ||
$o=XenForo_Application::getOptions(); | ||
|
||
if (trim($o->TPUDetectSpamRegHostname)!='') | ||
{ | ||
$hostname=gethostbyaddr($user['ip']); | ||
|
||
if ($verbose) | ||
$model->logScore('tpu_detectspamreg_hostname_detected', 0, array('hostname'=>$hostname)); | ||
|
||
foreach (explode("\n", $o->TPUDetectSpamRegHostname) as $entry) | ||
{ | ||
$entry=explode('|', trim($entry)); | ||
if (count($entry)!=2) | ||
continue; | ||
|
||
list($points, $match)=$entry; | ||
|
||
$regex=$model->buildWildcardRegex($match); | ||
|
||
if (preg_match('/^'.$regex.'$/iU', $hostname)) | ||
{ | ||
$model->logScore('tpu_detectspamreg_hostname_fail', $points, array('hostname'=>$match)); | ||
if (is_numeric($points)) | ||
$score['points']+=$points; | ||
else | ||
$score[$points]=true; | ||
} else | ||
if ($debug) | ||
$model->logScore('tpu_detectspamreg_hostname_ok', 0, array('hostname'=>$match)); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.