ip banner in php

Stato
Discussione chiusa ad ulteriori risposte.

cyd

Utente Silver
11 Giugno 2007
59
0
1
70
ciao ragazzi, bentrovati!
volevo postare, visto il mortuorio che è questa sezione ultimamente, un piccolo script che ho scritto per un mio progettino..

articolo completo:[QUI]
ESEMPIO: [QUI]

lo script è sostanzialmente un banner che blocca per indirizzo ip.

Cio che fa è bannare un utente se questo commette tot azioni indesiderate in un intervallo di tempo definito (per esempio sbaglia il login x volte in 10 minuti)
e lo banna per un intervallo di tempo a piacere. ogni volta che viene invocato pulisce il file db da vecchi record.

si appoggia su un xml, ma nell'articolo originale sul mio blog è spiegato come usare un file php al posto del xml.

PHP:
<?php

define("XMLFILE","banner.xml");	//nome del file xml database
define("MAX",5);				//numero massimo di tentativi
define("INTERVAL",10);			//intervallo in minuti dopo il quale è possibile fare altri MAX tentativi
define("BANINTERVAL",.25);		//tempo in ore di ban per coloro che esauriscono i tentativi

//funzione che ritorna il numero di tentativi effettuati
function check_status(&$x=false){
  !$x and $x=simplexml_load_file(XMLFILE);
  $r=$x->xpath('//user[@ip="'.$_SERVER['REMOTE_ADDR'].'"]');//xpath, seleziona tutti i nodi con attributo ip=$_...
  return $r?$r[0]->status:false;
}

//funzione per l'indice del nodo xml dell'ip in questione
function get_indexof(&$x=false){
  !$x and $x=simplexml_load_file(XMLFILE);
  for($c=0;$c<count($x->children());$c++) if((string)$x->user[$c]->attributes()->ip==$_SERVER['REMOTE_ADDR']) return $c;
  return false; //se l'ip non e' presente in nessun tag user ritorna false
}

//Funzione che gestisce i tentativi o l'eventuale ban degli utenti
function ban_user(){
  if(!$x=@simplexml_load_file(XMLFILE)) $x=simplexml_load_string('<?xml version="1.0" encoding="utf-8"?><users></users>');
  free_db($x);
  if(check_status($x)>MAX) return false;
  //Se l'ip non e' segnato nel xml allora è il primo tentativo e va inserito un nuovo nodo...
  if(false===$index=get_indexof($x)){
  	  $n=$x->addChild('user');
  	  $n->addAttribute('ip',$_SERVER['REMOTE_ADDR']);
  	  $n->addChild('time',time());
  	  $n->addChild('status',1);
  	  $x->asXML(XMLFILE);
  	  return true; //non ancora bannato
  }

  $status=(int)$x->user[$index]->status;	//prelevo lo stato dell'utente
  
  $status++;
  unset($x->user[$index]->status);
  unset($x->user[$index]->time);
  $x->user[$index]->addChild('status',$status);
  $x->user[$index]->addChild('time',time());

  $x->asXML(XMLFILE);
  return $status>MAX?false:true;
}

function free_db(&$x=false){
  !isset($x) and $x=simplexml_load_file(XMLFILE);
  for($c=0;$c<count($x->children());$c++){
    if((int)$x->user[$c]->status<=MAX && time()>=INTERVAL*60+(int)$x->user[$c]->time) unset($x->user[$c]);
    else if((int)$x->user[$c]->status>MAX && time()>=BANINTERVAL*3600+(int)$x->user[$c]->time) unset($x->user[$c]);
  }
  $x->asXML(XMLFILE);
}

function is_banned(){
$x=simplexml_load_file(XMLFILE);
free_db($x);
if(check_status($x)>MAX)return true;
return false;
}
?>

in ogni pagine su cui si vuole il ban:
PHP:
<?php

include('ipbanner.php');
if(is_banned()) header("Location:error.php"); //qui le azioni da fare se l'utente risulta bannato

?>

per incrementare i tentativi o per bannare:
PHP:
<?php

include('ipbanner.php');
//[...]
if(!ban_user()) header("Location:error.php");

//ban_user ritorna false se l'utente ha superato il numero massimo di tentativi la chiamata corrente.
//dunque la riga sopra lo reindirizza direttamente ad error.php senza dover richiamare is_banned().

?>

accettasi note!
 
Stato
Discussione chiusa ad ulteriori risposte.