Location: PHPKode > scripts > phphilter > phphilter/class.phphilter.php
<?php 
/*
 * @(#) $Header: /var/cvsroot/phphilter/class.phphilter.php,v 1.7 2009/06/11 12:30:00 cvs Exp $
 */
/*
    A simple class to allow access via iptables

    Copyright (C) 2009- Giuseppe Lucarelli <hide@address.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of version 2 of the GNU General Public License as
    published by the Free Software Foundation.

    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

define('_IPTABLES', '/usr/bin/sudo /usr/sbin/iptables');
define('_CHAIN', 'INPUT');
define('_PROTOCOL', 'tcp');
define('_PORT', '9521');
define('_ACCEPT', 'ACCEPT');
define('_DROP', 'DROP');
define('_DENY', 'REJECT');

define('_HOST_ALLOW', '127.0.0.1');	// '123.456.789.012' or '11.22.333.444/24' or 'ALL'

define('_HOST_DENY', '');		// '123.456.789.012' or '11.22.333.444/24' or 'ALL'

$passwd = array(
	'nopasswd'	=> '',
	'someuser'	=> 'passthru',
	);

class PhPhilter
{
/* public */
/* private */
	var $hostallow = '';
	var $hostdeny = '';
	var $filter = '';
	var $debug = false;

	private function Init() {
		$this->hostallow = explode(',',_HOST_ALLOW);
		$this->hostdeny = explode(',',_HOST_DENY);
		$this->remoteip = $_SERVER['REMOTE_ADDR'];
		$this->remotebinip = $this->GetBinaryValue($this->remoteip);
	}
	
	private function ToggleAccess($ip,$action) {
		$pattern='/^([0-9])+[ \t]+('.$action.')[ \t]+'._PROTOCOL.'[ \t]+[-A-Za-z0-9]+[ \t]+'.
			str_replace("/","\\/",$ip).'/im';
		if($this->debug) {
			echo "[DEBUG] ToggleAccess:\n-----------------\n$pattern\n-----------------\n";
		}
		if(!preg_match($pattern, $this->filter, $matches, PREG_OFFSET_CAPTURE)) {
			return;
		}
		$cmd = sprintf("%s -D %s %s 2>&1",
			_IPTABLES, _CHAIN, $matches[1][0]);
		$handle = popen($cmd, 'r');
		if($this->debug) {
			echo "[DEBUG] ToggleAccess [$cmd]:\n----------------\n".
				fread($handle, 2096).
				"\n------------------------\n";
		}
	}

	private function CheckAccess() {
		global $passwd;
		$state = -1;

		foreach($this->hostallow as $token) {
			if(strlen($token) <= 0)
				continue;
			if(!strcasecmp($token,'all'))	// allow access to all
				return true;
			$this->ToggleAccess($token,_DENY.'|'._DROP);
			$ipchain = $this->GetBinaryValue($token,$mask);
			if(!strcmp(substr($ipchain,0,$mask),substr($this->remotebinip,0,$mask))) {
				$state=true;
			}
		}
		foreach($this->hostdeny as $token) {
			if(strlen($token) <= 0)
				continue;
			if(!strcasecmp($token,'all'))	// deny access to all
				return false;
			$this->ToggleAccess($token,_ACCEPT);
			$ipchain = $this->GetBinaryValue($token,$mask);
			if(!strcmp(substr($ipchain,0,$mask),substr($this->remotebinip,0,$mask))) {
				$state=false;
			}
		}
		if($state != -1)
			return $state;
        	if (!$_SERVER['PHP_AUTH_USER']) {
                	header("WWW-Authenticate: Basic realm=\"PhPhilter\"");
                	header("HTTP/1.0 401 Unauthorized");
                	exit;
        	} else {
                	if (!isset($passwd[$_SERVER['PHP_AUTH_USER']]) ||
                	$_SERVER['PHP_AUTH_PW'] != $passwd[$_SERVER['PHP_AUTH_USER']]) {
                        	exit;
                	}
        	}
		return true;
	}

	private function InitChain() {
		$state = false;

		foreach($this->hostallow as $token) {
			if(strlen($token) <= 0)
				continue;
			$cmd = sprintf("%s -A %s -p %s -s %s --dport %s -j %s 2>&1",
				_IPTABLES, _CHAIN, _PROTOCOL, $token, _PORT, _ACCEPT);
			if($this->debug) {
				echo "setting: $cmd\n";
			}
			$handle = popen($cmd, 'r');
			if($this->debug) {
				echo "[DEBUG] InitChain [$cmd]:\n----------------\n".
					fread($handle, 2096).
					"\n------------------------\n";
			}
			pclose($handle);
		}
		foreach($this->hostdeny as $token) {
			if(strlen($token) <= 0)
				continue;
			$cmd = sprintf("%s -A %s -p %s -s %s --dport %s -j %s 2>&1",
				_IPTABLES, _CHAIN, _PROTOCOL, $token, _PORT, _DENY);
			if($this->debug) {
				echo "setting: $cmd\n";
			}
			$handle = popen($cmd, 'r');
			if($this->debug) {
				echo "[DEBUG] InitChain [$cmd]:\n----------------\n".
					fread($handle, 2096).
					"\n------------------------\n";
			}
			pclose($handle);
		}
		$cmd = sprintf("%s -A %s -p %s --dport %s -j %s 2>&1",
			_IPTABLES, _CHAIN, _PROTOCOL, _PORT, _DROP);
		$handle = popen($cmd, 'r');
		if($this->debug) {
			echo "[DEBUG] InitChain [$cmd]:\n----------------\n".
				fread($handle, 2096).
				"\n------------------------\n";
		}
		pclose($handle);
	}

//-----------------------------------------------------------------
//	public function ClearFilterList() {
//		$handle = popen(_IPTABLES.' -F '._CHAIN.' 2>&1', 'r');
//		pclose($handle);
//		$this->InitChain();
//	}
//-----------------------------------------------------------------

	private function GetFilterList() {
		$handle = popen(_IPTABLES.' -L '._CHAIN. ' -n --line-numbers 2>&1', 'r');
		$this->filter = fread($handle, 2096);
		if($this->debug) {
			echo "[DEBUG] filter situation:\n----------------\n$this->filter\n---------------\n";
		}
		if(eregi('(password|root|privilege)', $this->filter)) {
			die('oops! it seems there is no access to ['._IPTABLES.'] check your script privileges and retry. ');
		}
		pclose($handle);
	}

	public function GetBinaryValue($ip, & $mask = 32) {
		$retval = '';

		if($pos = strpos($ip,'/')) {
			$mask = (Int) substr($ip,$pos+1);
		} else {
			$mask = 32;
			$pos = 32;
		}
		$parts = explode('.',substr($ip,0,$pos));
		$retval=sprintf("%08b%08b%08b%08b",$parts[0],
			($parts[1] ? $parts[1] : 0),
			($parts[2] ? $parts[2] : 0),
			($parts[3] ? $parts[3] : 0));
		return $retval;
	}

	private function CheckFilterList() {
		if(!preg_match('/^[0-9]+.*'._PROTOCOL.'/im',$this->filter)) {	// empty chain
			$this->InitChain();
			$this->GetFilterList();
		}
		//--------------------------------------------------------------------------------------
		// if(preg_match('/^[0-9]+[ \t]+'._ACCEPT.'[ \t]+'._PROTOCOL.'[ \t]+[-A-Za-z0-9]+[ \t]+'.
		// 	$this->remoteip.'/im', $this->filter, $matches, PREG_OFFSET_CAPTURE)) {
		// 	if($this->debug) {
		// 		echo "[DEBUG] ip [".$this->remoteip."] access granted yet\n";
		// 	}
		// 	return;
		// }
		//--------------------------------------------------------------------------------------
		// check if remote ip is allowed/denied
		$mask = -1;
		$filter = explode("\n",$this->filter);
		for($i=2; $i < sizeof($filter); $i++) {
			$token = preg_split("/\s+/",trim($filter[$i]));
			$ipchain = $this->GetBinaryValue($token[4],$mask);
			if($mask == 0)
				continue;
			if($this->debug) {
				echo "ip [".$token[4]."]: ".substr($ipchain,0,$mask)." [$mask]\n";
			}
			if(!strcmp(substr($ipchain,0,$mask),substr($this->remotebinip,0,$mask))) {
				return;
			}
		}
		// no match, insert remote IP
		$cmd = sprintf("%s -I %s 1 -p %s -s %s --dport %s -j %s 2>&1",
			_IPTABLES, _CHAIN, _PROTOCOL, $this->remoteip, _PORT, _ACCEPT);
		$handle = popen($cmd, 'r');
		$read = fread($handle, 2096);
		if($this->debug) {
			echo "[DEBUG] apply filter:\n----------------\n$cmd\n---------------\n";
			echo "[DEBUG] filter result:\n----------------\n$read\n---------------\n";
		}
		pclose($handle);
		return;
	}

	function run() {
		$this->Init();
		$this->GetFilterList();
		if($this->CheckAccess() != true) {
			die("sorry, access denied for this ip [$this->remoteip]");
		}
		$this->CheckFilterList();
	}
};
?>
Return current item: phphilter