passend zur Diskussion über DNS Blacklist Checks habe ich ein kleines Modul geschrieben, was beim Betreten einer Webseite die IP-Adresse des Besuchers mit einer DNS-Blackliste abgleicht und gegebenenfalls den Zugang zur Seite verweigert.
Hier die Modul-Ausgabe:
Code: Alles auswählen
<?php
if (!($edit || $contenido)) {
	cInclude("classes", "contenido/class.client.php");
	cInclude("classes", "class.user.php");
	
	$cApiClient   = new cApiClient($client);
	$clientAdmins = User::getClientAdmins($client);
	
	$cfg["tab"]["spamcache"] = $cfg['sql']['sqlprefix'] . "_spamcache";
	$sql = "CREATE TABLE IF NOT EXISTS `" . $cfg["tab"]["spamcache"] . "` (`ip` VARCHAR(15) NOT NULL, `dnsbl` TINYTEXT NOT NULL DEFAULT '', `lastaccessed` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`ip`))";
	$db->query($sql);
	
	$sql = "DELETE FROM `" . $cfg["tab"]["spamcache"] . "` WHERE ROUND((NOW() - `lastaccessed`) / 60) >= 5";
	$db->query($sql);
	
	$sql = "SELECT * FROM `" . $cfg["tab"]["spamcache"] . "` WHERE `ip`='$_SERVER[REMOTE_ADDR]'";
	$db->query($sql);
	if ($db->next_record()) {
		$dnsbl = $db->f('dnsbl');
		$sql = "UPDATE `" . $cfg["tab"]["spamcache"] . "` SET `lastaccessed`=NOW() WHERE `ip`='$_SERVER[REMOTE_ADDR]'";
		$db->query($sql);
		
		if ($dnsbl)
			dieSpammer($dnsbl);
	} else {
		$dnsbls = explode(",", $cApiClient->getProperty("dnsbls", "servers"));
		if (is_array($dnsbls)) foreach ($dnsbls as $dnsbl) {
			$prefix = $cApiClient->getProperty("dnsbls", $dnsbl);
			if ($prefix) $prefix = ".$prefix";
			
			if ($dnsbl && isSpammer("$_SERVER[REMOTE_ADDR]$prefix", $dnsbl)) {
				$sql = "INSERT INTO `" . $cfg["tab"]["spamcache"] . "`(`ip`, `dnsbl`) VALUES('$_SERVER[REMOTE_ADDR]', '$dnsbl')";
				$db->query($sql);
				dieSpammer($dnsbl);
			}
		}
		
		$sql = "INSERT INTO `" . $cfg["tab"]["spamcache"] . "`(`ip`) VALUES('$_SERVER[REMOTE_ADDR]')";
		$db->query($sql);
	}
}
	
function isSpammer($ip, $dnsbl) {
	if (!function_exists("gethostbyname"))
		return false;
		
	if (!preg_match('/(?:(?:[1-9]|[1-9][0-9]|1[0-9]{2,2}|2[0-4][0-9]|25[0-5])\.){4,4}/', "$ip."))
		return false;
	$hostname = join(".", array_reverse(explode(".", $ip))) . ".$dnsbl";
	
	return gethostbyname($hostname) != $hostname;
}
function dieSpammer($dnsbl) {
	global $clientAdmins;
	header("HTTP/1.0 403 Forbidden");
	header("Content-type: text/plain");
	if (is_array($clientAdmins))
		$admin = array_shift($clientAdmins);
		
	die(sprintf("Sorry!\n\n%s says you are a spammer and we don't want spammers to use our services!\n" . (@$admin["email"] ? sprintf("If you think this is incorrect, please drop us a line via email to: %s.\n", str_replace("@", "(AT)", $admin["email"])) : '') . "\nThanks a lot.", $dnsbl));
}
?>Typ: dnsbls
Name: servers
Wert: <Komma-getrennte Liste von Servern>
Project Honey Pot beispielsweise braucht noch einen Zugangsschlüssel, solche Schlüssel können als
Typ: dnsbls
Name: <Hostname des Servers wie in der Liste>
Wert: Zugangsschlüssel
hinterlegt werden. Das Abfrageergebnis wird in der Datenbank zwischengespeichert und nach 5 minütiger Inaktivität des Besuchers
wieder entfernt.
Nachtrag: Das Modul muss als erstes im Layout der Seite geladen werden, also noch vor der Dokumenttypdeklaration, da die Ausgabe der Seite im Falle eines Spammers abgebrochen - und ein HTTP 403-Header gesendet wird.