Last active
October 29, 2020 21:41
-
-
Save sbassett29/2b1140de338d586a1d2e079e42f08685 to your computer and use it in GitHub Desktop.
Quick and Dirty StopForumSpam bulk IP search and stats
This file contains hidden or 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
<?php | |
/** | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License along | |
* with this program; if not, write to the Free Software Foundation, Inc., | |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
* https://www.gnu.org/copyleft/gpl.html | |
* | |
* @file | |
*/ | |
namespace SFSIPCheck; | |
// helper classes | |
class SFSFileManager { | |
public $fileMap; | |
public $fileName; | |
const cache_dir = './cache'; | |
const cache_expire = 43200; | |
public function __construct( string $fileId ) { | |
$this->fileMap = [ | |
'24h' => 'https://www.stopforumspam.com/downloads/listed_ip_1_ipv46_all.gz', | |
'7d' => 'https://www.stopforumspam.com/downloads/listed_ip_7_ipv46_all.gz', | |
'30d' => 'https://www.stopforumspam.com/downloads/listed_ip_30_ipv46_all.gz', | |
'90d' => 'https://www.stopforumspam.com/downloads/listed_ip_90_ipv46_all.gz', | |
'180d' => 'https://www.stopforumspam.com/downloads/listed_ip_180_ipv46_all.gz', | |
'1y' => 'https://www.stopforumspam.com/downloads/listed_ip_365_ipv46_all.gz', | |
]; | |
if( ! array_key_exists( $fileId, $this->fileMap ) ) | |
throw new Exception( 'Bad file ID specified!' ); | |
$this->fileName = $this->fileMap[ $fileId ]; | |
} | |
public function getRemoteFile( string $fileName ) { | |
return file_get_contents( $fileName ); | |
} | |
public function writeCacheFile() { | |
$fileNameLocal = self::cache_dir . '/' . basename( $this->fileName ); | |
if( is_file( $fileNameLocal ) && | |
abs( time() - filemtime( $fileNameLocal ) ) < self::cache_expire ) { | |
return false; | |
} | |
$data = $this->getRemoteFile( $this->fileName ); | |
$MD5data = $this->getRemoteMD5File(); | |
if( md5( $data ) != $MD5data ) | |
throw new Exception( 'MD5 checksum mismatch!' ); | |
if( (bool)file_put_contents ( $fileNameLocal, $data ) ) | |
return true; | |
else | |
throw new Exception( 'Unable to write cache file!' ); | |
} | |
public function getCacheFile() { | |
$fileNameLocal = self::cache_dir . '/' . basename( $this->fileName ); | |
if( ! is_file( $fileNameLocal ) && | |
abs( time() - filemtime( $fileNameLocal ) ) > self::cache_expire ) { | |
$this->writeCacheFile( $fileNameLocal ); | |
} | |
return file_get_contents( $fileNameLocal ); | |
} | |
public function getRemoteMD5File() { | |
$md5File = $this->fileName . '.md5'; | |
return $this->getRemoteFile( $md5File ); | |
} | |
} | |
class SFSCreateIPsReport { | |
public $fileData; | |
public $rawRequestVar; | |
public $processedIPData; | |
public function __construct( string $rawRequestVar, string $SFSFileData ) { | |
$this->fileData = preg_split( '/(\r\n|\n|\r)/', $SFSFileData ); | |
$this->rawRequestVar = $rawRequestVar; | |
$this->processedIPData = $this->parseIPsFromRequestData(); | |
} | |
public function parseIPsFromRequestData() { | |
$regExpPat = '/^(((?=.*(::))(?!.*\3.+\3))\3?|([\dA-F]{1,4}(\3|:\b|$)|\2))(?4){5}((?4){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})\z|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/i'; | |
$search = preg_split( '/(\r\n|\n|\r)/', $this->rawRequestVar ); | |
array_walk( $search, function( &$v ) use ( $regExpPat ) { | |
$v = trim( basename( $v ) ); | |
if( ! preg_match( $regExpPat, $v ) ) { | |
$v = null; | |
} | |
} ); | |
return array_filter( $search ); | |
} | |
public function generateBasicStatsArray() { | |
$found = []; | |
foreach( $this->fileData as $v ) { | |
$ip = trim( str_getcsv( $v )[0] ); | |
if( in_array( $ip, $this->processedIPData ) ) | |
$found[] = $ip; | |
} | |
return [ 'found' => count( $found ), 'total' => count( $this->processedIPData ) ]; | |
} | |
public function generateFullIPStatsArray() { | |
$found = []; | |
foreach( $this->fileData as $v ) { | |
$data = str_getcsv( $v ); | |
if( in_array( $data[0], $this->processedIPData ) ) { | |
$found[] = [ | |
htmlspecialchars( $data[0] ), | |
htmlspecialchars( $data[1] ), | |
htmlspecialchars( $data[2] ) | |
]; | |
} | |
} | |
return $found; | |
} | |
} | |
class Form { | |
public static function display() { | |
echo <<<EOF | |
<html> | |
<head><title>SFS IP Check</title></head> | |
<body> | |
<h1>Check IPs within stopforumspam.com deny lists</h1> | |
<h4>(<a href='https://www.stopforumspam.com/downloads' target='_blank'> | |
https://www.stopforumspam.com/downloads</a>)</h4> | |
<h4>Enter a newline-separated list of IPs below<br />...or a list of urls like: https://en.wikipedia.org/wiki/Special:Contributions/11.22.33.44</h4> | |
<form name='sfs-form' method='get' action='/sfsipcheck/'> | |
<textarea name='IPs' rows='12' cols='70'> | |
</textarea><br /><br /> | |
<select name='fileId'> | |
<option value='24h'>IPv4 & IPv6 - Last 24 hours</option> | |
<option value='7d'>IPv4 & IPv6 - Last 7 days</option> | |
<option value='30d'>IPv4 & IPv6 - Last 30 days</option> | |
<option value='90d' selected='true'>IPv4 & IPv6 - Last 90 days</option> | |
<option value='180d'>IPv4 & IPv6 - Last 180 days</option> | |
<option value='1y'>IPv4 & IPv6 - Last year</option> | |
</select><br /> | |
<br /><input type='submit' name='form-submit' value='Check IPs' /> | |
</form> | |
</body> | |
</html> | |
EOF; | |
} | |
} | |
class Report { | |
public static function display( string $requestVar, string $data ) { | |
$oStats = new SFSCreateIPsReport( $requestVar, $data ); | |
$basic = $oStats->generateBasicStatsArray(); | |
$full = $oStats->generateFullIPStatsArray(); | |
echo <<<EOF0 | |
<html> | |
<head><title>SFS IP Check</title></head> | |
<body> | |
<h1>Report of IPs within stopforumspam.org deny lists</h1> | |
<table border='1' cellpadding='4'> | |
<tr> | |
<td>Number of IPs checked:</td> | |
<td><strong>{$basic['total']}</strong></td> | |
</tr> | |
<tr> | |
<td>Number of IPs found in deny list:</td> | |
<td><strong>{$basic['found']}</strong></td> | |
</tr> | |
</table> | |
EOF0; | |
if( (int)$basic['found'] > 0 ) { | |
echo <<<EOF1 | |
<h2>Full IP data</h2> | |
<table border='1' cellpadding='4'> | |
<tr><th>IP Address</th><th>Threshold</th><th>Last seen</th></tr> | |
EOF1; | |
foreach( $full as $v ) { | |
if( is_array( $v ) && count( $v ) == 3 ) | |
echo "<tr><td>{$v[0]}</td><td>{$v[1]}</td><td>{$v[2]}</td></tr>\n"; | |
} | |
echo <<<EOF2 | |
</table> | |
EOF2; | |
} | |
echo <<<EOF3 | |
<div><br /><a href="/sfsipcheck/">Back</a></div> | |
</body> | |
</html> | |
EOF3; | |
} | |
} | |
// controller class | |
class Controller { | |
public function run() { | |
if( count( $_GET ) > 0 ) { | |
$oFM = new SFSFileManager( $_GET['fileId'] ); | |
$data = gzdecode( $oFM->getCacheFile() ); | |
Report::display( $_GET['IPs'], $data ); | |
} | |
else | |
Form::display(); | |
} | |
} | |
// run controller | |
$oCont = new Controller(); | |
$oCont->run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment