Lightsquid Ubuntu Server 16.04

squid-lightsquidLightsquid является анализатором логов squid. На основе логов, создаются отчеты об использовании сети интернет. Установка lightsquid будет производиться на proxy сервер, сконфигурированный в этой статье.

Установим lightsquid, apache2 и cgi модуль

# apt install lightsquid apache2 libcgi-fast-perl

В /etc/lightsquid/lightsquid.cfg укажем корректный путь до access.log. Так же поменяем язык интерфейса lightsquid на русский в кодировке utf8, и выставим максимальный размер трафика в сутки в 1Gb. По превышению этого лимита, пользователь будет попадать в колонку «Превысили»

# nano /etc/lightsquid/lightsquid.cfg
. . .
$logpath ="/var/log/squid";
. . .
$lang ="ru-utf8";
. . .
$perusertrafficlimit = 1000*1024*1024;
. . .

Для авто заполнения полей «Ф.И.О.» и «Группа» добавим скрипт. Идея скрипта взята из комментария к этой статье.

# nano /etc/lightsquid/generate_name_group.pl

#!/usr/bin/perl -wT

use Net::LDAP;
use Encode qw(from_to);

my $prefix = '/etc/lightsquid/';
my $users = $prefix.'/realname.cfg';
my $groups = $prefix.'/group.cfg';

my $ldap = Net::LDAP->new('ldap://dc1.4skill.loc') or die "$@";
my $result = $ldap->bind('CN=squid,CN=Users,DC=4skill,DC=loc', 'password' => 'Pa$$w0rd');

if($result->code) {
    die 'Bind failed!\n';
}

$result = $ldap->search(
    'base' => 'OU=Domain Users,DC=4skill,DC=loc',
    'filter' => '(&(objectClass=user)(!(UserAccountControl=66050)))',
    'scope' => 'sub',
    'attrs' => [ 'cn', 'sAMAccountName', 'Department' ]
);

if($result->entries <= 0) {
    die "Found no users\n";
}

my %groups = ();

open(OUT, '>' . $users);
foreach my $entry ($result->entries) {
    my $name = $entry->get_value('cn');
    my $login = lc($entry->get_value('sAMAccountName'));
    my $dept = $entry->get_value('Department');

    if(defined $dept) {
        $groups{$dept}{$login} = 1;
    }

    print OUT $login . "\t" . $name . "\n";
}
close(OUT);

my $i = 1;
open(OUT, '>' . $groups);
foreach my $group (sort keys %groups) {
    foreach my $login (sort keys %{$groups{$group}} ) {
        my $num = sprintf("%02d", $i);
        print OUT $login . "\t" . $num . "\t" . $group . "\n";
    }
    $i++;
}
close(OUT);

/etc/lightsquid/ — каталог, содержащий конфигурационные файлы lightsquid.
dc1.4skill.loc — dns имя контроллер домена.
squid Pa$$w0rd — логин и пароль пользователя, от имени которого squid просматривает информацию в AD. Пользователь был создан на этом этапе.
Domain Users — контейнер, содержащий учетные записи пользователей домена.

Для успешного запуска скрипта нужно установить LDAP модуль

# apt install libnet-ldap-perl

Добавим возможность выполнения скрипта и запустим его

# chmod +x /etc/lightsquid/generate_name_group.pl
# /etc/lightsquid/generate_name_group.pl

В каталоге /etc/lightsquid должны появиться файлы group.cfg и realname.cfg, содержащие описания групп и пользователей. Эта информация берется из полей объектов AD «Выводимое имя» и «Отдел». Поля должны быть заполнены.

Файлы group.cfg и realname.cfg создаются в кодировке utf8. Чтобы при просмотре отчетов, не было иероглифов, добавим новый языковой файл для lightsquid в кодировке utf8. Для этого переконвертируем имеющийся языковой файл

# iconv -f cp1251 -t utf8 /usr/share/lightsquid/lang/ru.lng -o /usr/share/lightsquid/lang/ru-utf8.lng

И изменим эту строку

# nano /usr/share/lightsquid/lang/ru-utf8.lng
. . .
MSG_CODEPAGE=utf8
. . .

Чтобы исключить некоторых пользователей из отчета, нужно создать файл /etc/lightsquid/skipuser.cfg.

# nano /etc/lightsquid/skipuser.cfg
user1
user2
. . .

При генерации отчетов у пользователей с маленьким трафиком, вместо отчета открывается пустая страница. Для исправления этой ошибки нужно применить патч. Идея патча взята отсюда.

Добавим патч

# nano /usr/lib/cgi-bin/lightsquid/user_detail.cgi.patch

# When user have only 'hit' traffic, $calculatedtotal become zero
# and script die with "Illegal division by zero" error
--- user_detail.cgi~     2014-06-25 13:26:16.576149494 +0400
+++ user_detail.cgi      2014-06-25 13:25:58.108485852 +0400
@@ -88,7 +88,7 @@
   $hit=$h{$site}{hit};
   $size=$h{$site}{size};
   $total+=$size;
-  $percent   =sprintf("%2.1f",int($size*1000/$calculatedtotal)/10);
+  $percent   =$calculatedtotal?sprintf("%2.1f",int($size*1000/$calculatedtotal)/10):'&infin;';
   $printhit  =FineDec($hit);
   $printsize =FineDec($size);
   $printtotal=FineDec($total);
@@ -145,4 +145,4 @@
 2006-06-28 ADD : die -> MyDie
 2006-06-28 ADD : &tpl= support
 2006-09-13 ADD : add &user= in bigfiles URL
-2006-11-20 ADD : /g for ##SITEURL_B## & ##SITEURL_L##, my need in some cases
\ No newline at end of file
+2006-11-20 ADD : /g for ##SITEURL_B## & ##SITEURL_L##, my need in some cases

Перейдем в каталог с проблемным cgi скриптом, создадим его копию и применим патч

# cd /usr/lib/cgi-bin/lightsquid/
# cp user_detail.cgi user_detail.cgi.default
# patch user_detail.cgi user_detail.cgi.patch
patching file user_detail.cgi

В сгенерированных отчетах по мимо списка учетных записей пользователей, записываются ip адреса компьютеров. Чтобы убрать из отчетов ip адреса создадим скрипт

# nano /etc/lightsquid/lightsquid_no-ip.sh

#!/bin/sh

unset path
path=/var/lib/lightsquid/report/$(date +%Y%m%d)
mv $path/.total $path/.total_orig

user=`grep -v -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" $path/.total_orig | grep -v "user:*" | grep -v "size:*" | wc -l`
login=`grep -v -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" $path/.total_orig | grep -v "user:*"`
echo "user: $user" > $path/.total
echo "$login" >> $path/.total

rm $path/.total_orig

exit 0

Добавим права на выполнение

# chmod +x /etc/lightsquid/lightsquid_no-ip.sh

Переместим файл, отвечающий за ротацию логов squid, в родительскую директорию squid и отредактируем его

# mv /etc/logrotate.d/squid /etc/squid/squid.logrotate

# nano /etc/squid/squid.logrotate

#
#       Logrotate fragment for squid.
#
/var/log/squid/*.log {
        daily
        compress
#       delaycompress
        rotate 1
        missingok
        nocreate
        sharedscripts
#       prerotate
#               test ! -x /usr/sbin/sarg-reports || /usr/sbin/sarg-reports
#       endscript
        postrotate
                test ! -e /var/run/squid.pid || test ! -x /usr/sbin/squid || /usr/sbin/squid -k rotate
        endscript
}

Отчеты генерируются автоматически каждый день в 4 часа. Это поведение определено в файле /etc/cron.d/lightsquid. Отредактируем этот файл, с учетом созданных скриптов

# nano /etc/cron.d/lightsquid

# Regular cron jobs for the lightsquid package
#
0 23 * * * root /etc/lightsquid/generate_name_group.pl
0 0 * * * root /usr/sbin/logrotate -f /etc/squid/squid.logrotate
5 * * * * root [ -x /usr/share/lightsquid/lightparser.pl ] && /usr/share/lightsquid/lightparser.pl && /etc/lightsquid/lightsquid_no-ip.sh
35 * * * * root [ -x /usr/share/lightsquid/lightparser.pl ] && /usr/share/lightsquid/lightparser.pl && /etc/lightsquid/lightsquid_no-ip.sh

Теперь каждый день в 23:00 будут обновляться файлы group.cfg и realname.cfg. Каждый день в 0:00 будет происходить ротация логов squid. Каждую 5 и 35 минуту каждого часа будет обновляться отчет lightsquid.

Отредактируем конфигурационный файл lightsquid для apache

# nano /etc/apache2/conf-available/lightsquid.conf

Alias /lightsquid/ /usr/lib/cgi-bin/lightsquid/

<Location "/lightsquid/">
        AddHandler cgi-script .cgi
        Require ip 192.168.1.10 192.168.1.11
</Location>

В Require ip указываем адреса сотрудников, имеющих право просматривать отчеты. Для того, чтобы все пользователи имели доступ к отчетам, Require ip нужно поменять на

Require all granted

Активируем в apache конфигурационный файл lightsquid и CGI модуль, а так же перезапустим сервис

# a2enconf lightsquid
# a2enmod cgi
# service apache2 restart

Проверим /etc/lightsquid/lightsquid.cfg на наличие ошибок

# /usr/share/lightsquid/check-setup.pl

Сгенерируем первый отчет

# /usr/share/lightsquid/lightparser.pl && /etc/lightsquid/lightsquid_no-ip.sh

Для просмотра отчета, нужно открыть браузер по адресу http://proxy_ip/lightsquid/

Lightsquid Ubuntu Server 16.04: 18 комментариев

  1. Павел

    Добрый день, застрял на запуске скрипта, просто висит и все.
    #!/bin/bash

    rnfile=»/etc/lightsquid/realname.cfg»;
    groupdn=»CN=group,OU=sec group,DC=bsi,DC=local»;

    if [ -f $rnfile ];then
    sudo rm $rnfile
    fi
    sudo touch $rnfile;

    for i in `sudo net ads search «(&(objectclass=person)(memberOf:1.2.840.113556.1.4.1941:=$groupdn))» samAccountName -P | grep «^sAMAccountName:» | sed «s/^sAMAccountName: //»`;
    do
    login_low=`echo $i | tr «[:upper:]» «[:lower:]»`;
    full_name=`sudo net ads search «(sAMAccountName=$login_low)» name -P | grep «^name:» | sed «s/^name: //»`;
    echo «$login_low $full_name» >> $rnfile;
    done
    #

    1. Андрей Автор записи

      Здравствуйте! Скорость обработки скрипта зависит от количества пользователей. К примеру если в AD около 500 пользователей скрипт может висеть 1-2 минуты. Для чистоты эксперимента, я повторил Вашу ситуацию. В начале по каким-то причинам файл realname.cfg создавался пустым. Я перезагнал машину в домен командой

      net ads join -U Administrator osName='Ubuntu Server GNU/Linux' osVer='16.04 LTS'

      . Далее все заработало. Вот скрин Отчет AD Первое что бросается в глаза в Вашем коментарии, это кавычки, направленные в одну сторону

      (»») rnfile=»/etc/lightsquid/realname.cfg»;
      groupdn=»CN=group,OU=sec group,DC=bsi,DC=local»;


      Возможно проблема в них.

      1. Павел

        Спасибо. После повторного создания файла, и получаса выгрузка наконец-то прошла. Иду дальше, опять возник вопрос: файл /etc/lightsquid/group.cfg руками заполнять получается? Для всех 500 овер пользователей? А если добавляется новый пользователь, то его опять руками добавлять? Может вопрос немного не по сабжу, но вы не знаете есть ли вариант разграничения пользователей по группам AD? Честно говоря в скриптах не сильно разбирюсь, поэтому и задаю вопрос.

        1. Андрей Автор записи

          По умолчанию в lightsquid файлы описания пользователей и групп заполняются вручную. Для автоматизации заполнения нужно писать скрипты. К сожалению я тоже не силен в написании скриптов. Есть несколько готовых вариантов на перле habrahabr.ru и habrahabr.ru. Перед их запуском потребуется установка LDAP модуля, производится командой

          apt install libnet-ldap-perl

          . Честно говоря не было времени на тестирование, в результате скрипты отработали, но файлы realname.cfg и group.cfg добавились в пустом виде. Как-будто в AD нет пользователей. Чуть позже я постараюсь разобраться детальнее с этим вопросом.
          P.S. На боевом сервере я отключил в отчете отображение столбца «Группа». Сделать это можно в /etc/lightsquid/lightsquid.cfg выставив следующий параметр в значение 0

          #if you dont need Group mode, do =0
          $showgrouplink       = 0;

          1. Павел

            Большое спасибо цикл ваших статей очень помог, буду копать в сторону заполнения групп. Если найду напишу вам. Кстати еще один вопрос не встречали случайно скриптов для блокировки пользователей превысивших лимит?

  2. Павел

    Находил этот скрипт, но у меня он не отрабатывается, выдвет ошибку Bind failed!\n at /etc/lightsquid/generate_name_group.pl line 14, line 755. Складывается впечатление что ему не нравится имя моего домена оканчивающееся на local потому что в редакторе подсвечивается красным. Хоть и глупо звучит.

    1. Андрей Автор записи

      Теоретически возможно три варианта:
      — ошибка в указании имени контроллера домена.
      — ошибка в синтаксисе указания пути расположения пользователя, от имени которого происходит подключение к AD.
      — ошибка в логине или пароле пользователя, от имени которого происходит подключение к AD.
      Путь расположения лучше скопировать из редактора атрибутов
      Атрибуты пользователя squid
      Еще могу предположить, что скрипту может не понравиться контейнер, в котором лежит пользователь для просмотра AD. Попробуйте переместить его в стандартную папку Users как в примере, возможно поможет.

      1. Павел

        Пробовал разных пользователей, разные контейнеры все перепробовал. Один результат. Я с perl вообще никак. В имени контроллера он мне выделяет красным символ s и local.

        1. Андрей Автор записи

          Я тоже уже писал, что не силен в изобретении скриптов. Но тут все уже за нас написано, нужно только правильно свои значения вставить. Пришлите кусок скрипта, с названием Вашего контроллера, расположением и именем пользователя. Я попробую воспроизвести Ваш случай. Также укажите версию ОС на контроллере.

  3. Павел

    Вот так выглядит winad2008
    my $ldap = Net::LDAP->new(‘ldap://khv-it-s-ad2.bsi.local’) or die «$@»;
    my $result = $ldap->bind(‘CN=squid,CN=Users,DC=dsi,DC=local’, ‘password’ => ‘Pa$$w0rd’);

    if($result->code) {
    die ‘Bind failed!\n’;

    1. Андрей Автор записи

      Сразу же видна ошибка.

      ldap://khv-it-s-ad2.bsi.local
      CN=squid,CN=Users,DC=dsi,DC=local
      

      1. Павел

        Это здесь ошибка, извиняюсь, скопировал из виндового редактора. Перепроверил в конфиге везде dsi

        1. Андрей Автор записи

          Воспроизвел Вашу ситуацию. Контроллер домена на WS 2008R2 RUS. Имя контроллера khv-it-s-ad2.dsi.local.
          Ubuntu server 16.04.01. В /etc/network/interfaces указал в качестве dns адрес контроллера, и dns суффикс dsi.local.
          Установил libnet-ldap-perl и создал скрипт. Больше ничего не настраивал.

          #!/usr/bin/perl -wT
          
          use Net::LDAP;
          use Encode qw(from_to);
          
          my $prefix = '/etc/lightsquid/';
          my $users = $prefix.'/realname.cfg';
          my $groups = $prefix.'/group.cfg';
          
          my $ldap = Net::LDAP->new('ldap://khv-it-s-ad2.dsi.local') or die "$@";
          my $result = $ldap->bind('CN=squid,CN=Users,DC=dsi,DC=local', 'password' => 'Pa$$w0rd');
          
          if($result->code) {
              die 'Bind failed!\n';
          }
          
          $result = $ldap->search(
              'base' => 'OU=Domain Users,DC=dsi,DC=local',
              'filter' => '(&(objectClass=user)(!(UserAccountControl=66050)))',
              'scope' => 'sub',
              'attrs' => [ 'cn', 'sAMAccountName', 'Department' ]
          );
          
          if($result->entries < = 0) {
              die "Found no users\n";
          }
          
          my %groups = ();
          
          open(OUT, '>' . $users);
          foreach my $entry ($result->entries) {
              my $name = $entry->get_value('cn');
              my $login = lc($entry->get_value('sAMAccountName'));
              my $dept = $entry->get_value('Department');
          
              if(defined $dept) {
                  $groups{$dept}{$login} = 1;
              }
          
              print OUT $login . "\t" . $name . "\n";
          }
          close(OUT);
          
          my $i = 1;
          open(OUT, '>' . $groups);
          foreach my $group (sort keys %groups) {
              foreach my $login (sort keys %{$groups{$group}} ) {
                  my $num = sprintf("%02d", $i);
                  print OUT $login . "\t" . $num . "\t" . $group . "\n";
              }
              $i++;
          }
          close(OUT);
          


          dsi.loc

  4. Роман

    Товарищ, преспасибище тебе титанических размеров!
    Заработало, и довольно быстро.
    Все по полочкам, и думаю, это самый лаконичный и доходчивый мануал по настройке «ркасивых» отчетов по пользователям!

    1. Андрей Автор записи

      Спасибо! Такие отзывы очень мотивируют в написании нового материала=)

  5. Дмитрий

    Добрый день!
    Большое спасибо за статью.
    Но, к сожалению, у меня следующая ошибка —

    /etc/lightsquid/generate_name_group.pl: line 4: use: command not found
    /etc/lightsquid/generate_name_group.pl: line 5: syntax error near unexpected token `(‘
    /etc/lightsquid/generate_name_group.pl: line 5: `use Encode qw(from_to);’

    Все необходимые модули установлены. КД 2008R2
    Может знаете в чем дело…

    1. Андрей Автор записи

      Вечер добрый!
      Первая ссылка гугла по запросу «use: command not found» содержит потенциальный ответ.
      Первая строка скрипта должна начинаться со знаков «#!» и содержать корректный путь до перла(#!/usr/bin/perl -wT). В Вашем случае, скрипт выполняется не через перл, а через bash, в котором отсутствует команда «use».

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *