initial commit of file from CVS for smeserver-webfilter on Sat Sep 7 16:44:31 AEST 2024
This commit is contained in:
223
root/usr/bin/squid-db-logd
Normal file
223
root/usr/bin/squid-db-logd
Normal file
@@ -0,0 +1,223 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use File::Tail;
|
||||
use DBI;
|
||||
use URI;
|
||||
use Getopt::Long;
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use strict;
|
||||
|
||||
our %opts = ();
|
||||
|
||||
# Set default options
|
||||
$opts{squidlog} = '/var/log/squid/access.log';
|
||||
$opts{squidguardlog} = '/var/log/squidGuard/deny.log';
|
||||
$opts{squid} = 1;
|
||||
$opts{squidguard} = 0;
|
||||
$opts{debug} = 0;
|
||||
$opts{dbhost} = 'localhost';
|
||||
$opts{dbname} = 'squid_log';
|
||||
$opts{dbuser} = 'squid';
|
||||
$opts{dbpass} = 'squid';
|
||||
|
||||
# get command line arguments
|
||||
GetOptions(
|
||||
"debug=i" => \$opts{debug},
|
||||
"squidlog=s" => \$opts{squidlog},
|
||||
"squidguardlog=s" => \$opts{squidguardlog},
|
||||
"squid!" => \$opts{squid},
|
||||
"squidguard!" => \$opts{squidguard},
|
||||
"dbhost=s" => \$opts{dbhost},
|
||||
"dbname=s" => \$opts{dbname},
|
||||
"dbuser=s" => \$opts{dbuser},
|
||||
"dbpass=s" => \$opts{dbpass}
|
||||
);
|
||||
|
||||
# Disable output buffering
|
||||
select(STDOUT);
|
||||
$| = 1;
|
||||
select(STDERR);
|
||||
$| = 1;
|
||||
|
||||
open STDERR, '>&STDOUT';
|
||||
|
||||
# Set process name
|
||||
$0 = 'squid-db-logd';
|
||||
|
||||
# Get hostname
|
||||
our $host = `hostname`;
|
||||
chomp($host);
|
||||
|
||||
### Subroutines
|
||||
|
||||
# Print messages on stderr
|
||||
# for debuging purpose
|
||||
sub printlog {
|
||||
my $msg = shift;
|
||||
print "$msg\n";
|
||||
return;
|
||||
}
|
||||
|
||||
# Connect to the database
|
||||
sub db_connect {
|
||||
my $dbh = DBI->connect("DBI:mysql:database=$opts{dbname};host=$opts{dbhost}",
|
||||
$opts{dbuser}, $opts{dbpass}, {RaiseError => 1});
|
||||
die "Couldn't connect to database\n" unless ($dbh);
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
# escape chars for MySQL queries
|
||||
sub mysql_escape {
|
||||
my $string = shift;
|
||||
$string =~ s|'|\\'|g;
|
||||
return $string;
|
||||
}
|
||||
|
||||
# log squid access
|
||||
|
||||
# prepare squid insert query
|
||||
sub squid_prepare {
|
||||
my $dbh = shift;
|
||||
my $q = "INSERT INTO access_log (proxy_host, timestamp, response_time, ".
|
||||
"client_ip, squid_status, http_status, reply_size, request_method, ".
|
||||
"url, domain, username, squid_connect, server_ip, mime_type) ".
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
my $qh = $dbh->prepare($q);
|
||||
return $qh;
|
||||
}
|
||||
|
||||
# prepare squidGuard insert query
|
||||
sub squidguard_prepare {
|
||||
my $dbh = shift;
|
||||
my $q = "INSERT INTO deny_log (proxy_host, date_day, date_time, ".
|
||||
"category, client_ip, url, domain, username) ".
|
||||
"VALUES(?,?,?,?,?,?,?,?)";
|
||||
my $qh = $dbh->prepare($q);
|
||||
return $qh;
|
||||
}
|
||||
|
||||
sub squid_log {
|
||||
|
||||
my $logfile = shift;
|
||||
|
||||
printlog("squid_log thread connecting to database") if ($opts{debug} ge 1);
|
||||
my $dbh = db_connect;
|
||||
my $qh = squid_prepare($dbh);
|
||||
# Open log file
|
||||
|
||||
printlog("opening squid log file") if ($opts{debug} ge 1);
|
||||
my $tail = File::Tail->new(name=>$logfile, maxinterval=>15);
|
||||
|
||||
while (defined(my $line=$tail->read)){
|
||||
my ($timestamp, $response_time, $client_ip, $status, $reply_size,
|
||||
$request_method, $url, $username, $server, $mime_type) = split /\s+/, $line;
|
||||
my ($squid_status, $http_status) = split /\//, $status;
|
||||
my ($squid_connect, $server_ip) = split /\//, $server;
|
||||
|
||||
# Skip stats requested by squidclient
|
||||
next if ($url =~ m/^cache_object:/);
|
||||
|
||||
my $domain;
|
||||
if ($request_method eq 'CONNECT'){
|
||||
($domain,undef) = split /:/, $url;
|
||||
}
|
||||
elsif ($url =~ m/^error:/){
|
||||
(undef,$domain) = split /:/, $url;
|
||||
}
|
||||
else{
|
||||
my $uri = URI->new($url);
|
||||
$domain = $uri->host;
|
||||
}
|
||||
|
||||
# MySQL escape
|
||||
# Shouldn't be needed, but just in case logs contains junk
|
||||
$timestamp = mysql_escape($timestamp);
|
||||
$response_time = mysql_escape($response_time);
|
||||
$client_ip = mysql_escape($client_ip);
|
||||
$squid_status = mysql_escape($squid_status);
|
||||
$http_status = mysql_escape($http_status);
|
||||
$reply_size = mysql_escape($reply_size);
|
||||
$request_method = mysql_escape($request_method);
|
||||
$url = mysql_escape($url);
|
||||
$domain = mysql_escape($domain);
|
||||
$username = mysql_escape($username);
|
||||
$squid_connect = mysql_escape($squid_connect);
|
||||
$server_ip = mysql_escape($server_ip);
|
||||
$mime_type = mysql_escape($mime_type);
|
||||
|
||||
printlog("New access_log entry:\ntimestamp: $timestamp\nresponse_time: $response_time\n".
|
||||
"client_ip: $client_ip\nsquid_status: $squid_status\nhttp_status: $http_status\n".
|
||||
"reply_size: $reply_size\nrequest_method: $request_method\nurl: $url\n".
|
||||
"username: $username\nsquid_connect: $squid_connect\n".
|
||||
"server_ip: $server_ip\nmime_type: $mime_type\n\n") if ($opts{debug} ge 2);
|
||||
|
||||
$qh->execute($host, $timestamp,$response_time,$client_ip,$squid_status,
|
||||
$http_status,$reply_size,$request_method,$url,$domain,
|
||||
$username,$squid_connect,$server_ip,$mime_type) || die "Database error: ".$qh->errstr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# log squid access
|
||||
sub squidguard_log {
|
||||
|
||||
my $logfile = shift;
|
||||
|
||||
printlog("squidguard_log thread connecting to database") if ($opts{debug} ge 1);
|
||||
my $dbh = db_connect;
|
||||
my $qh = squidguard_prepare($dbh);
|
||||
|
||||
# Open log file
|
||||
printlog("opening squidGuard log file") if ($opts{debug} ge 1);
|
||||
my $tail = File::Tail->new(name=>$logfile, maxinterval=>15);
|
||||
|
||||
while (defined(my $line=$tail->read)){
|
||||
my ($date_day, $date_time, undef, $category, $url, $client_ip, $username) = split /\s+/, $line;
|
||||
# Clean some values
|
||||
$category =~ m/default\/(\w+)/;
|
||||
$category = $1;
|
||||
$client_ip =~ s/\/\-$//;
|
||||
|
||||
my $domain;
|
||||
# Use the URI parser if possible
|
||||
if ($url =~ m/^https?:\/\//){
|
||||
my $uri = URI->new($url);
|
||||
$domain = $uri->host;
|
||||
}
|
||||
# Else, it's a CONNECT method like www.domain.tld:443
|
||||
else {
|
||||
($domain,undef) = split /:/, $url;
|
||||
}
|
||||
$domain = mysql_escape($domain);
|
||||
|
||||
# MySQL escape
|
||||
$date_day = mysql_escape($date_day);
|
||||
$date_time = mysql_escape($date_time);
|
||||
$category = mysql_escape($category);
|
||||
$url = mysql_escape($url);
|
||||
$client_ip = mysql_escape($client_ip);
|
||||
$username = mysql_escape($username);
|
||||
|
||||
printlog("New deny_log entry:\ndate: $date_day\ntime: $date_time\ncategory: $category\n".
|
||||
"client_ip: $client_ip\nurl: $url\nusername: $username\n\n") if ($opts{debug} ge 2);
|
||||
|
||||
$qh->execute($host,$date_day,$date_time,$category,$client_ip,$url,$domain,$username) ||
|
||||
die "Database error: ".$qh->errstr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
printlog("Starting log monitoring threads") if ($opts{debug} ge 1);
|
||||
my $thr1 = threads->create('squid_log', $opts{squidlog}) if ($opts{squid});
|
||||
my $thr = 1;
|
||||
if ($opts{squidguard}){
|
||||
my $thr2 = threads->create('squidguard_log', $opts{squidguardlog}) if ($opts{squidguard});
|
||||
$thr++;
|
||||
}
|
||||
|
||||
while (scalar(threads->list(threads::running)) ge $thr){
|
||||
sleep(5);
|
||||
}
|
||||
|
||||
die "At least one thread died\n";
|
Reference in New Issue
Block a user