Proxylizer Squid Support

Hey,

I’ve modified proxylizer daemon to support squid log files. Here is php code to do that:

#!/usr/bin/php
<?php
/****************************************************************************
*                                                                           *
*    MikroTik Proxylizer, Web-proxy log analyzer                            *
*    Copyright (C) 2009  MikroTik                                           *
*                                                                           *
*    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 3 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, see <http://www.gnu.org/licenses/>.  *
*                                                                           *
****************************************************************************/
/****************************************************************************
SQUID support added by ayufan (ayufan(at)osk-net(dot)pl)
****************************************************************************/
if (isset($_SERVER['REQUEST_URI'])) return;

// DB_URL format: 
//    DB_TYPE://DB_USER:DB_PASSWORD@DB_HOSTNAME/DB_NAME
define("DB_URL", "mysql://proxylizer:proxylizer@localhost/proxylizer"); 
define("HOST_IP", "127.0.0.1");

define("STARTED_FROM_INDEX", 2);
define("DEBUG", 0);
define("IP_DIGIT", "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)");
define("IP_REGEXP", "^" . IP_DIGIT . "\\." . IP_DIGIT . "\\." . IP_DIGIT . "\\." . IP_DIGIT . "$");
chdir(dirname($argv[0]));

$host = ip2long(HOST_IP);//exec("hostname");

include('DB.php');
	
set_time_limit(0);
ob_implicit_flush();

// tell PEAR to write no backtrace
$skiptrace = &PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
$skiptrace = true;

if (!($db = connectDB())) {
	echo date("Y-m-d H:i | ") . "Couldn't connect to database!!!\n";
	exit(2);
}

while (($line = fgets(STDIN)) !== FALSE) {
	$line = str_replace("\n", "", $line);
	$line = ereg_replace("[ \t]+", " ", $line);
	$rawlog = explode(" ", $line);
	if(count($rawlog) != 10) {
		echo date("Y-m-d H:i | ") . "Invalid Squid line!!!\n";
		continue;	
	}
	$date = date("Y-m-d", intval($rawlog[0]));
	$time = date("H:i", intval($rawlog[0]));
	$IP = eregIP($rawlog[2]);
	if($IP === FALSE) {
		echo date("Y-m-d H:i | ") . "Invalid IP address!!!\n";
		continue;
	}
	$IP = ip2long($rawlog[2]);
	parseURL($rawlog[6]);
	parseDomain($fulldomain);
	parseActionSquid($rawlog[3]);
	parseCacheSquid($rawlog[3]);
	insertLine($db);
}
$db->disconnect();

function eregIP ($ip) {
    if (ereg(IP_REGEXP, $ip)) {
        return $ip;
    } else {
        return false;
    }
}

function connectDB() {
    $options = array(
    'debug'       => 2,
    'portability' => DB_PORTABILITY_ALL,
    );
    do {
        $db = & DB::connect(DB_URL, $options);
        if (PEAR::isError($db)) {
            echo "/1/ ";
            echo date("Y-m-d H:i | ") . "Code " . $errcode=$db->getcode() . " ";
            echo $db->getMessage() . "\n";
            if ($errcode == DB_ERROR_ACCESS_VIOLATION || $errcode == DB_ERROR_NOSUCHDB) {
                return false;
            }
            return false;
        } else {
            return $db;
        }
    } while (true);
}

function insertLine (& $db) {
global $subdomain, $domain, $topdomain, $domainid , $cofig_const ;
    $query = "INSERT INTO domain(subdomain, domain, topdomain)
                    VALUES ('{$subdomain}', '{$domain}', '{$topdomain}')";
        do {
            $insertdata = & $db->query($query);
            $iserror = false;
            if (PEAR::isError($insertdata)) {
                $msg = $insertdata->getMessage() . "\n";
                $errcode = $insertdata->getCode();
                if ($errcode = DB_ERROR_CONSTRAINT || $errcode = DB_ERROR_ALREADY_EXISTS) {
                    $testquery = "SELECT ID from domain WHERE subdomain = '{$subdomain}'
                                and domain = '{$domain}' and topdomain = '{$topdomain}'";
                    // domain exists
                    $res =& $db->query($testquery);
                    if (PEAR::isError($res)) {
                        $errorcode = $res->getCode();
                        if ($errorcode == DB_ERROR_ACCESS_VIOLATION || $errcode == DB_ERROR_NOSUCHDB || 
                            $errcode == DB_ERROR_NODBSELECTED || $errcode == DB_ERROR || 
                            $errcode == DB_ERROR_NODBSELECTED) {
                            // domain exists but connection lost
                            echo "/2/ ";
                            echo date("Y-m-d H:i | ") . "CODE: " . $res->getCode() . " ";
                            echo $res->getMessage() . " \n";
                            $iserror = true;
                            $db->disconnect();
                            $db = connectDB();
                        } else {
                            $iserror = false;
                        }
                    } else {
                        // domain exists, id selected
                        $row =& $res->fetchRow();
                        $domainid = $row['0'];
                        insertWebproxyTable($db);
                        $iserror = false;
                    }
                } elseif ($errcode == DB_ERROR_ACCESS_VIOLATION || $errcode == DB_ERROR_NOSUCHDB || 
                            $errcode == DB_ERROR_NODBSELECTED || $errcode == DB_ERROR ||
                            $errcode == DB_ERROR_NODBSELECTED) {
                    // no connection, etc
                    echo "/3/ ";
                    echo date("Y-m-d H:i | ") . "CODE: " . $res->getCode() . " ";
                    echo $res->getMessage() . " \n";
                    $iserror = false;
                    $db->disconnect();
                    $db = connectDB();
                } else {
                    echo "/4/ ";
                    echo date("Y-m-d H:i | ") . $insertdata->getMessage() . "\n";
                }
            } else {
                // domain inserted
                $querymaxid = "SELECT max(ID) FROM domain";
                $res =& $db->query($querymaxid);
                if (PEAR::isError($res)) {
                    echo "/5/ ";
                    echo date("Y-m-d H:i | ") . "CODE: " . $res->getCode() . " ";
                    echo $res->getMessage() . "\n";
                } else {
                    $row =& $res->fetchRow();
                    $domainid = $row['0'];
                    insertWebproxyTable($db);
                    $iserror = false;
                }
            }
        } while ($iserror ==true);
    }

function insertWebproxyTable (& $db) {
global $domainid, $host, $date, $time, $IP, $domainid, $path, $action, $cache, $iserror, $line;
    $query = "INSERT INTO webproxylog (host, event_date, event_time, IP, domain_id, path, action, cache)"
    . " VALUES ('{$host}', '{$date}', '{$time}', "
    . "'{$IP}', '{$domainid}', '{$path}', '{$action}', '{$cache}')";
    $insertdata = & $db->query($query);
    if (PEAR::isError($insertdata)) {
        echo "/6/ ";
        echo date("Y-m-d H:i | ") . $insertdata->getMessage() . "\n";
        $iserror = false;
    } else if (DEBUG) {
        $query = "SELECT MAX(id) FROM webproxylog";
        $res = & $db->query($query);
        if (!PEAR::isError($res)) {
            $row = $res->fetchRow();
            if ($row) {
                $logID = $row[0];
                $msg = str_replace("'", "''", $line);
                $query = "INSERT INTO msg (logid, msg) VALUES ({$logID}, '{$msg}')";
                $res = & $db->query($query);
            }
        }
    }
}

function parseDomain($d) {
global $subdomain, $domain, $topdomain;
    $is_ipv4 = ip2long($d);
    if ($is_ipv4 !== false) {
        $subdomain = "";
        $domain = $d;
        $topdomain = "";
    } else {
        $posoflastdot = strrpos($d, '.');
        if ($posoflastdot === false) {
            $subdomain = "";
            $domain = $d;
            $topdomain = "";
        } else {
            $topdomain = substr($d, $posoflastdot + 1);
            $rawdomain = substr($d, 0, $posoflastdot);
            $posofprelastdot = strrpos($rawdomain, '.');
            if ($posofprelastdot !== false) {
                $domain = substr($rawdomain, $posofprelastdot + 1);
                $subdomain = substr($rawdomain, 0, $posofprelastdot);
            } else {
                $domain = $rawdomain;
                $subdomain = "";
            }
        }
    }
}

function parseURL($u) {
global $fulldomain, $path;
    $posofquestion = strpos($u, '?');
    if ($posofquestion != false) {
        $u = substr($u, 0, $posofquestion);
    }
    $posofcolonslash = strpos($u, '://');
    $address = substr($u, $posofcolonslash + 3);
    $posofslash = strpos($address, '/');
    if ($posofslash != false) {
        $fulldomain = substr($address, 0, $posofslash);
        $path = substr($address, $posofslash + 1);
    } else {
        $fulldomain = $address;
        $path = "";
    }
}

function parseAction($a) {
global $action;
    $action = $a == 'action=allow' ? 1 : 0;
}

function parseActionSquid($a) {
	global $action;
    $action = (strpos($a, "DENIED") !== FALSE);
}

function parseCache($l) {
	global $cache;
    $c = substr($l, -9);
    $cache = $c == 'cache=HIT' ? 1 : 0;
}

function parseCacheSquid($l) {
	global $cache;
    $cache = (strpos($l, "HIT") !== FALSE);
}

?>

Simply copy above code and paste it to squidproxylizer.php file (you can use nano to do that). After that configure DB_URL and DB_HOST in source. My version reads logs from STDIN.



Simplest usage is to redirect squid logs to script:

tail -f /var/log/squid/access.log | php squidproxylizer.php

In Debian you can add it to crontab with nice daemon solution. Add following line which automatically starts squidproxylizer to root’s crontab: crontab -e -u root (Of course tune script and log location)

* *  * * * tail -n 0 -f /var/log/squid/access.log | /sbin/start-stop-daemon --start --name squidproxylizer --quiet --chuid proxy --startas /srv/squidproxylizer.php 1>/dev/null 2>/dev/null &

When daemon starts you can stop it for one minute with following command:

start-stop-daemon --stop --name squidproxylizer

It’s test version and works nice for me.

I’m looking for feedback.

ayufan

Nice work!

Can you copy/paste this into the wiki?

Ron.

Fixed small bugs and added annotation about deamonising it :wink: Someday maybe i’ll add :smiley: