Location: PHPKode > scripts > Firewall > firewall/firewall.class.php
<?php
/****************************************************************************************
*   Class   :   firewall
*   Ver.    :   1.0
*   Author  :   Temperini Mirko  <hide@address.com>
*   Date    :   03-29-2010
*   License :   GPL License
*
*   IMPORTANT!!!
*
*    The firewall must be EVER started at the top of  the script ( think to session_start() as condition rules)  
*
*   ONLY ONE ISTANCE IS ALLOWED IN A PAGE!!! 
*   
* 
*   calling costructor, you can pass directly the rules table to parse
*   es: $myFirewall = new firewall(fielname.ext);
*   and the table is directly loaded
*
*
*
*   you can set 2 different types of output on deny ip:
*   default:     send an header with 403 Status (Forbidden)
*   redirect:    it redirect by a single javascript line to a link specified.
*               why javascript? because when a server is not propelry setted or the page have already sended the header, it not fail.  
*               $myFirewall->setAction('redirect','http://www.google.com');
*
*   show:       simply output the code you pass in 
*               $myFirewall->setAction( 'show',file_get_contents('forbidden.tpl') );
*
*
*   if no action is specified, the default is a blank page whit 403 Status Header (Forbidden)
*
*
*   ok, we turn On our firewall
*   $myFirewall->start();
*   
*   ----------------------------------------
*   |CAUTION!                               |
*   ----------------------------------------------------------------------------------------------------
*   the forceHostname() method try to resolve an IP from ah hipotetic hostname, when it isn't a valid   |
*   this feature can make your firewall slow! Depends from the necessary time to resolve the IP!        |
*   ----------------------------------------------------------------------------------------------------   
*   
*this class is successfull tested on PHP 5.3 
*
*   please report bugs at : <hide@address.com>
*   
****************************************************************************************/

class firewall{
    private $rules_table    =""; //path to rules table
    private $code_rules     =array('allow'=>array(),'deny'=>array());
    private $action         ="";
    private $source         ="";
    private $ipClient       =null;
    private $force_hostname =false  ;
    private $onDenied       ='';
    private $onAllowed      ='';
    
    final public function __construct($rules_table=""){
        $this->rules_table=$rules_table;
        $this->loadTable($this->rules_table);
        }
    
    final public function start(){
        $this->ipClient     =$this->clientIp();
        $this->onDenied     =trim((string)$this->onDenied);
        $this->onAllowed    =trim((string)$this->onAllowed);        
        //var_dump($this->onAllowed);
        if( !$this->isAllowed($this->ipClient) ){
            switch($this->action){
                case 'redirect':
                    echo '<script type="text/javascript">location.href="'.$this->source.'"</script>';
                break;
                case 'show':
                    echo $this->source;
                break;
                default:
                    header('HTTP/1.1 403 Forbidden');
                break;
                }
            if($this->onDenied != '')
                call_user_func($this->onDenied,$this->ipClient);
            exit();
            }
        else{
            if(trim($this->onAllowed) != '')
                call_user_func($this->onAllowed,$this->ipClient);
            }
        }
    
    final private function storeRule($type,$values){
        $clientIp=$this->ip2int($this->clientIp());
        switch($type){
            case 'range':
                $action =$values[1];

                $from   =( str_replace('.','',$values[3]) > str_replace('.','',$values[2]) )?$values[2]:$values[3];
                $from   =$this->ip2int($from);

                $to     =( str_replace('.','',$values[3]) > str_replace('.','',$values[2]) )?$values[3]:$values[2];
                $to     =$this->ip2int($to);
                
                $this->code_rules[$action][]="if($clientIp >= $from  && $clientIp <= $to) \$result=true;";
            break;
            case 'simple':
                $action =$values[1];
                $ip=$this->ip2int($values[2]);
                $this->code_rules[$action][]="if ($clientIp == $ip) \$result = true;";
            break;
            }
        }
    

    
    final public function isAllowed($ip){
        // first check allowed arrays. if not results, check denied array. if not results return true;
        $rules=$this->code_rules;

        if(!empty($rules['allow'])){
            foreach($rules['allow'] as $allow){
                @eval($allow);
                if(isset($result)) return true;
                }
            }
 

        if(!empty($rules['deny'])){
            foreach($rules['deny'] as $deny){
                @eval($deny);
                if(isset($result)) return false;
                }
            }

        return true;
        }
    
    
    final private function ip2int($ip){
        $tmp=explode('.',$ip);
        foreach($tmp as $t_key=>$t_val) $tmp[$t_key]=str_pad($t_val,3, "0", STR_PAD_LEFT); 
        return implode('',$tmp);
        }
    
    final private function isValidIp($ip){
        return preg_match("^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}^", $ip);
        }
    
    final private function clientIp(){
            if  (!empty($_SERVER['HTTP_CLIENT_IP']))        $ip=$_SERVER['HTTP_CLIENT_IP'];
        elseif  (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))  $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
        else                                                $ip=$_SERVER['REMOTE_ADDR'];
        
        return $ip;
        }    
    
    final public function loadTable($rule_table=''){
        $this->rules_table=$rule_table;
        $rulesFile=$this->rules_table;
        
        if(is_file($rulesFile) && is_readable($rulesFile)){
            $rules=file($rulesFile,FILE_IGNORE_NEW_LINES);
            if(!$rules) $rules=array();
            
            if(!empty($rules)){                
                foreach($rules as $ruleLine){
                    $ruleLine=trim($ruleLine);
                    if($ruleLine !=""){
                        // check syntax allow/deny n.n.n.n to n.n.n.n
                        preg_match('/^(deny|allow)[\s](.*)[\s]to[\s](.*)$/i',$ruleLine,$values);
                        if(!empty($values) && $this->isValidIp($values[2]) && $this->isValidIp($values[3])){
                            $this->storeRule('range',$values);
                            continue;
                            }
                        //check syntax allow/deny simple n.n.n.n
                        preg_match('/^(deny|allow)[\s](.*)$/i',$ruleLine,$values);
                        
                        if(!empty($values) && !empty($values[2])){
                            $checkIp=$this->isValidIp($values[2]);
                            if( !(bool)$checkIp ){
                                //try to resolve ip by the given string...
                                if($this->force_hostname) 
                                    $checkRemoteIp=gethostbyname($checkIp);
                                
                                $values[2]=(isset($checkRemoteIp) && (bool)$checkRemoteIp !== false )?$checkRemoteIp:$values[2];
                                }
                            $this->storeRule('simple',$values);
                            continue;
                            }
                        }
                    }
                }
            }
        }

    final public function onAllow($callback=''){
        $this->onAllowed=(string)$callback;
        }    

    final public function onDeny($callback=''){
        $this->onDenied=(string)$callback;
        }    


    //CAUTION! 
    //this feature can make your firewall slow! Depends from the necessary time to resolve the IP!
    final public function forceHostname($value=true){
        $this->force_hostname=(bool)$value;
        }
    
    final public function setAction($type,$source){
        $this->action=$type;
        $this->source=$source;
        }
    
    }
Return current item: Firewall