Для организации логирования, статистики посещенных сайтов и других сетевых соединений я воспользовался связкой Squid + Free-SA + ipcad

  • Squid - Прокси сервер, который работает у меня в прозрачном (transparent или intercept) режиме - пользователям ничего настраивать не придется. Более подробно о нем писать не вижу смысла.
  • Free-SA - Анализатор логов Squid написан на языке Си, по функциональности и назначению похож на LightSquid. Главное отличие - скорость формирования отчетов от 7 до 20 раз выше по сравнению с LightSquid (7х - для 50 Мб файла access.log, 20x - для 1 Гб). Присутствуют дополнительные отчеты (в том числе для оценки эффективности сервера), изменяемые "на лету" темы оформления, имеется поддержка различных форматов файлов журналов (Squid, CLF, Postfix, Qmail, CGP). Имеет мало зависимостей в отличие от того же LightSquid и малые требования к веб серверу! В настройках можно много чего интересного покрутить, об этом ниже. Еще хотелось бы отметить полезного из функционала - опционально можно включить в отчеты полные URL - для подробной отчетности, либо наоборот отключить (будет быстрее формироваться статистика).
  • Rejik - redirector для Squid, выполняющий функции контент фильтра. Поддерживает регулярные выражения, и просто списки сайтов. Можно добавлять исключения, применять правила по времени или ip адресам. Из плюсов - высокая скорость работы. Из минусов, чтобы скачать базы, нужно либо поработать - проверить несколько сотен сайтов на принадлежность, либо просто купить списки "плохих" сайтов.
  • ipcad - Коллектора для сбора трафика, идущего в обход прокси-сервера. Остается только взять извлечь из него статистику и записать в лог Squid. Скрипт для этого есть ниже.
  • nginx - Легковесный и производительный веб-сервер. Для запуска CGI скриптов/программ лучше всего использовать fcgiwrap, о настройке ниже. Более подробно расписывать не вижу смысла.

Весь выбранный софт бесплатный и имеется в портах FreeBSD и под Linux, думаю тоже все эти пакеты есть.

Итак по порядку, первым делом обновляем порты и устанавливаем весь перечисленный софт:

FreeBSD# cd /usr/ports
FreeBSD# portsnap fetch update
FreeBSD# cd /usr/ports/www/squid
FreeBSD# make config && make config-recursive
[x] SQUID_IDENT
[x] SQUID_KQUEUE
[x] SQUID_LARGEFILE
FreeBSD# make install clean
FreeBSD# cd /usr/ports/www/free-sa
FreeBSD# make install clean
FreeBSD# cd /usr/ports/www/rejik
FreeBSD# make config && make config-recursive
[x] BAN
[x] DBL
[x] WWW
FreeBSD# make install clean
FreeBSD# cd /usr/ports/www/nginx
FreeBSD# make config && make config-recursive
[x] HTTP
[x] HTTP_CACHE
[x] HTTP_REWRITE
[x] HTTP_STATUS
[x] WWW
FreeBSD# make install clean
FreeBSD# cd /usr/ports/www/fcgiwrap
FreeBSD# make install clean
FreeBSD# cd /usr/ports/net-mgmt/ipcad
FreeBSD# make install clean

Когда все успешно установится переходим к настройкам: Листинг free-sa.conf:

#
# Sample configuration file for free-sa(1)
#
# copy to /usr/local/etc/free-sa/free-sa.conf
#


#########
# FILES #
#########
log="/var/log/squid/access.log"
#usertab="/usr/local/etc/free-sa/users"
downloads="/usr/local/etc/free-sa/downloads.sample"
#local_filter=""
#global_filter=""


###############
# DIRECTORIES #
###############
targetdir="/usr/local/www/data/free-sa"
tmpdir="/var/cache/free-sa"


#####################
# REPORTS SELECTION #
#####################
ts="true"
paf="true"
saf="true"
pdn="true"
sdn="true"
cct="true"
pst="true"
dld="true"
fullurl="true"
users="true"
#email=""


##################
# REPORTS LIMITS #
##################
#paf_limit="50"
#saf_limit="50"
#pdn_limit="50"
#sdn_limit="50"
#cct_limit="50"
#pst_limit="50"
#dld_limit="50"
#lcf_limit="50"
#url_limit="50"
#ts_limit="0"
#dld_min="0"
#rtr_timeout="5000"


####################
# OTHER PARAMETERS #
####################
name="free-sa.conf"
logformat="0"
#skip_errors="false"
fulltraffic="true"
inameuser="true"
#user_unescape="false"
indicators="true"
overwrite="2"
resolveip="true"
showinfo="true"
#site=""
#logo=""
locale="ru_RU.KOI8-R"
#rotate=""
divisor="b"
#tz_shift="0"

Создаем каталог для скриптов:

mkdir /usr/local/etc/squid/scripts

И создаем в этой папке скрипты:

Листинг ipcadstat.sh:

#!/bin/sh

# Диапазон адресов локальной cети, указываем подсеть.
net="192\.168\.[0-9]?[0-9]?[0-9]\.[0-9]?[0-9]?[0-9]$" # 192.168.0.0/16
#net="192\.168\.0\.[0-9]?[0-9]?[0-9]$" # 192.168.0.0/24

# Каталог с логами squid'а
squid_DIR='/var/log/squid/'

ttime=`rsh localhost sh ip acco | grep 'Accounting data saved' | awk '{print ($4)}'`
rsh localhost clear ip accounting > /dev/null
rsh localhost show ip accounting checkpoint | awk -v vtime=$ttime '{
 if ( $2 ~ /^'$net'/ )
     print (vtime".000",1,$2,"TCP_MISS/200",$4,"CONNECT",$1":"$5,"-","DIRECT/"$1,"-")
 }' >> "$squid_DIR/access.log"

#TODO - если ошибок не было, то продолжаем.
/usr/local/bin/free-sa

Листинг rotate_log.sh:

#!/bin/sh

# Ротация логов Squid
/usr/local/sbin/squid -k rotate
for i in $(ls $squid_DIR | grep -i '\.log\.[4-9]'); do
    rm -f $squid_DIR/$i
done

Добавляем эти скрипты в планировщик заданий /etc/crontab:

# rotate squid logs
0    0  */1  *  *  root  /usr/local/etc/squid/scripts/rotate_log.sh >>/var/log/squid/rotate_log.log 2>&1

# Наполнение лога squid данными из ipcad.
*/5  *  *    *  *  root  /usr/local/etc/squid/scripts/ipcadstat.sh >>/var/log/squid/ipcadstat.log 2>&1

Привожу только те строки, которые изменил в дефолтном конфиге Squid - /usr/local/etc/squid/squid.conf:

http_port 3129 transparent
cache_mem 500 MB
maximum_object_size_in_memory 64 KB
cache_dir ufs /var/squid/cache 20480 16 256
maximum_object_size 100 MB
access_log /var/log/squid/access.log squid
cache_log /var/log/squid/cache.log
logfile_rotate 100
strip_query_terms off
url_rewrite_program /usr/local/rejik/redirector /usr/local/rejik/redirector.conf
url_rewrite_children 10
header_access Via deny all
cache_mgr Тут@Мое.мыло
visible_hostname имя.сервера.сквида
error_directory /usr/local/etc/squid/errors/Russian-1251
dns_nameservers Тут.ip.вашего.DNS.сервера
append_domain .local
forwarded_for off

Страницу блокировки я предпочитаю отдавать самим Squid, как это описано в FAQ по rejik'у - А нельзя ли обойтись без установки локального web сервера?

Добавляем строки в /usr/local/etc/squid/mime.conf:

# Для rejik
dfgxfdgdfg-squid-porno dfgxfdgdfg-squid-deny/dfgxfdgdfg-squid-porno-html rejik/porno.html - ascii
dfgxfdgdfg-squid-deny dfgxfdgdfg-squid-deny/dfgxfdgdfg-squid-deny-html rejik/deny.html  - ascii
dfgxfdgdfg-squid-banner dfgxfdgdfg-squid-banner/dfgxfdgdfg-squid-banner-1px rejik/1x1.gif  - image
dfgxfdgdfg-squid-js dfgxfdgdfg-squid-js/dfgxfdgdfg-squid-js-js  rejik/js.js  - ascii

Файл 1x1.gif - это пустая gif картинка размером 1x1 пиксель. Файл js.js - это пустой текстовый файл. Файлы porno.html, deny.html - произвольный html документ, который будут видеть те, кто откроет запрещенный сайт.

Например у меня deny.html выглядит так:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Доступ ограничен</title>
        <style type="text/css">
            <!--
            body,td,th {
                font-family: Verdana, Arial, Helvetica, sans-serif;
                font-size: 14px;
                color: #FFFFFF;
            }
            body {
                background-color: #000000;
                margin-top: 100px;
                margin-left: 100px;
                margin-right: 100px;
            }
            .style1 {
                color: #FF0000;
                font-size: 16px;
                font-weight: bold;
            }
            .style2 {font-size: 10px}
            -->
        </style>
    </head>

    <body>
        <div align="center">
            &nbsp; <p class="style1">Содержимое данного сайта заблокировано!</p>
            &nbsp; <p>Система контентной фильтрации определила,<br />
            &nbsp; что материалы запрашиваемого вами ресурса<br />
            &nbsp; могут противоречить целям и задачам <br />
            &nbsp; образовательного процесса.</p>
            &nbsp; <hr width="400" size="3" />
            &nbsp; <p><span class="style2">Если вы уверены, что сайт не содержит недопустимой информации,<br />
            &nbsp; обратитесь к системному администратору. После проверки адрес<br />
            &nbsp; будет добавлен в список разрешенных ресурсов.</span></p>
        </div>
    </body>
</html>

Листинг /usr/local/rejik/redirector.conf:

error_log /usr/local/rejik/redirector.err
change_log /usr/local/rejik/redirector.log
make-cache /usr/local/rejik/make-cache
allow_urls /usr/local/rejik/banlists/allow_urls

# Список ip - исключений. (для кого НЕ будут применяться правила фильтрации)
allow_ip f:/usr/local/rejik/ip/allow


#<audio-video>
#ban_dir  /usr/local/rejik/banlists/audio-video
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

#<avto-moto>
#ban_dir  /usr/local/rejik/banlists/avto-moto
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

<banner>
ban_dir /usr/local/rejik/banlists/banners
#файлы смотри в каталоге /usr/local/etc/squid/icons/rejik + mime.conf файл сквида
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/1x1.gif
log off

#<chats>
#ban_dir  /usr/local/rejik/banlists/chats
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

#<dating>
#ban_dir  /usr/local/rejik/banlists/dating
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

<extremism>
ban_dir  /usr/local/rejik/banlists/extremism
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

#<icq>
#ban_dir  /usr/local/rejik/banlists/icq
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

#<jobsearch>
#ban_dir  /usr/local/rejik/banlists/jobsearch
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

<online-games>
ban_dir  /usr/local/rejik/banlists/online-games
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

<phishihg>
ban_dir  /usr/local/rejik/banlists/phishing
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

#<photogallery>
#ban_dir  /usr/local/rejik/banlists/photogallery
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

<porno>
ban_dir  /usr/local/rejik/banlists/porno
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

<socnet>
ban_dir  /usr/local/rejik/banlists/socnet
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
work_ip f:/usr/local/rejik/ip/deny_socnet
log off

<spyware>
ban_dir  /usr/local/rejik/banlists/spyware
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

<torrents>
ban_dir  /usr/local/rejik/banlists/torrents
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

<virus-detect>
ban_dir  /usr/local/rejik/banlists/virus-detect
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

<warez>
ban_dir  /usr/local/rejik/banlists/warez
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

#<web-mail>
#ban_dir  /usr/local/rejik/banlists/web-mail
#url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
#log off

<web-proxy>
ban_dir  /usr/local/rejik/banlists/web-proxy
url http://127.0.0.1:3126/squid-internal-static/icons/rejik/deny.html
log off

Так как rejik из текстовых файлов со списками плохих сайтов делает файлы бинарные файлы, от после внесения изменений в списки, нужно обновлять *.cache файлы rejik'а, для этого я использую скрипт:

#!/bin/sh

# Путь  до rejik
REJIK_PATH=/usr/local/rejik


# Найдем и удалим файлы кеша rejik
find $REJIK_PATH -name '*.cache' -exec rm {} \;
# Создадим снова кеш rejik
$REJIK_PATH/make-cache

# говорим squid перечитать новую конфигурацию
/usr/local/sbin/squid -k reconfigure

Листинг с описанием виртуального хоста squid.local:

server {
#-------------------------- Options --------------------------#
    listen *:80;
    server_name squid.local squid;

    open_file_cache max=100000 inactive=40s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # Logs
    access_log /var/log/nginx/squid.local_http_access.log;
    error_log /var/log/nginx/squid.local_http_error.log;


#-------------------------- Configs --------------------------#
    # redirect server error pages to the static page /50x.html
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/local/www/nginx-dist;
    }

    # deny access to .htaccess files, if Apache's document root concurs with nginx's one
    location ~ /\.ht { deny all; }

    index index.html free-sa.cgi;

#-------------------------- Locations ------------------------#

    location ~ ^/favicon.ico$ {
        root /usr/local/www/data/free-sa;
        log_not_found off;
        access_log off;
        expires max;
    }

    # Main location
    location / {
        root /usr/local/www/data/free-sa;

        location ~ \.cgi$ {
            gzip off; #gzip makes scripts feel slower since they have to complete before getting gzipped
            fastcgi_pass unix:/var/run/fcgiwrap/lightsquid.socket;
            fastcgi_index free-sa.cgi;
            fastcgi_param SCRIPT_FILENAME /usr/local/www/data/free-sa/$fastcgi_script_name;
            fastcgi_param QUERY_STRING $query_string;
            fastcgi_param REQUEST_METHOD $request_method;
            fastcgi_param CONTENT_TYPE $content_type;
            fastcgi_param CONTENT_LENGTH $content_length;
            fastcgi_param GATEWAY_INTERFACE CGI/1.1;
            fastcgi_param SERVER_SOFTWARE nginx;
            fastcgi_param SCRIPT_NAME $fastcgi_script_name;
            fastcgi_param REQUEST_URI $request_uri;
            fastcgi_param DOCUMENT_URI $document_uri;
            fastcgi_param DOCUMENT_ROOT $document_root;
            fastcgi_param SERVER_PROTOCOL $server_protocol;
            fastcgi_param REMOTE_ADDR $remote_addr;
            fastcgi_param REMOTE_PORT $remote_port;
            fastcgi_param SERVER_ADDR $server_addr;
            fastcgi_param SERVER_PORT $server_port;
            fastcgi_param SERVER_NAME $server_name;
        }
    }
}

Конечно же каталог с логами должен существовать и права должны быть такие же как у nginx:

mkdir /var/log/nginx
chown www:www /var/log/nginx

Не забываем про ротацию логов - добавляем в /etc/newsyslog.conf:

# nginx
/var/log/nginx-error.log www:www  644  7    900 *     XC /var/run/nginx.pid 30
/var/log/nginx/*.log  www:www  644  7    900 *     GXC /var/run/nginx.pid 30

# rejik
/usr/local/rejik/redirector.err squid:squid 644  10    300 *     XC
# crontab for Squid
/var/log/squid/rotate_log.log   644  3    100 *     XC
/var/log/squid/ipcadstat.log   644  3    100 *     XC

И перезапускаем демона newsyslog:

service newsyslog restart

В качестве бонуса привожу скрипт для удобной перезагрузки конфига Squid. Так как после внесения изменений в конфигурацию Squid, нужно перезапускать сервис, либо из консоли давать команду squid -k reconfigure, что не всегда удобно + если мы допустили ошибку в конфиге ничего хорошего не будет от такой команды и уж темболее от перезагрузки сервиса - он не запустится, а у людей не будет интернета, чтобы всего этого избежать я написал простенький скриптик:

#!/bin/sh

# Функция вывода цветных сообщений
COLOR_STR() {
    case $2 in
        red) printf %b "\033[1;31m$1\033[0m" ;;
        green) printf %b "\033[1;32m$1\033[0m" ;;
    esac
}

squid -k check
if [ $? = 0 ]; then
    squid -k reconfigure
    COLOR_STR 'SUCCESS' green
    echo ': Squid config reloaded.'
else
    COLOR_STR 'ERROR' red
    echo ': in Squid config file.'
fi

В кратце как это работает - скрипт сперва проверяет синтаксис конфига squid -k check, и если ошибок небыло, то выполняет загрузку нового конфига squid -k reconfigure, если были ошибки, то он выдаст ошибку и Squid останется работать со старым конфигом, следовательно у всех будет интернет, а у вас будет время все исправить.

И последний конфиг - листинг файла конфигурации IpCad /usr/local/etc/ipcad.conf:

capture-ports enable;

interface lan0 filter "ip and dst net 192.168.0.0/16 and not src net 192.168.0.0/16 and not src port 80";

aggregate 0.0.0.0/0 strip 32; /* Drop the last octet of all other IPs */

aggregate 110 into 110;
aggregate 443 into 443;
aggregate 3129 into 0;
aggregate 3128 into 0;
aggregate 3130-65535 into 65535;

rsh enable at 127.0.0.1;
rsh root@127.0.0.1 admin;
rsh root@127.0.0.1 backup;
rsh root@127.0.0.1;
rsh 127.0.0.1 view-only;
rsh ttl = 3;
rsh timeout = 30;
chroot = /var/log/ipcad;
dumpfile = ipcad.dump;
pidfile = ipcad.pid;

Обратите внимание на строку interface lan0 filter "ip and dst net 192.168.0.0/16 and not src net 192.168.0.0/16 and not src port 80"; Эта строка предписывает ipcad собирать статистику пакетов попадающих в локальную сеть извне (из интернет) на LAN-интерфейсе. При этом в статистику не должны попадать пакеты от squid (т.е. те, порт источника которых равен 80 - у нас же прозрачный прокси) т.к. squid сам отразит их статистику в своем логе. Дублирование статистики нам ни к чему.

Как и чем заворачивать всех клиентов в Squid выбирайте сами - в интернете полно информации по этому поводу, я приведу 2 примера заворота при помощи pf и ipfw:

Пример для pf:

# редиректим всех, кроме таблицы <no_www_proxy> на наш Proxy сервер, чтобы отфильтровать "Плохие сайты"
rdr proto tcp from !<no_www_proxy> to !lan0:network port http -> 127.0.0.1 port 3129

Пример для ipfw:

# Squid transparent redirect
add fwd 127.0.0.1,3129 tcp from any to not 192.168.0.0/16 http via lan0

Где lan0 - имя локального интерфейса.

Теперь можно все это добавить в автозагрузку и запустить.

Вырезка из /etc/rc.conf:

#------------------------------ squid ------------------------------------#
squid_enable="YES" # Прозрачный прокси, для ведения статистики посещенных сайтов.
ipcad_enable="YES" # Для записи в статистику squid'а, всего остального трафика.
#-------------------------------------------------------------------------#


#------------------------------ nginx ------------------------------------#
nginx_enable="YES"  # (bool) Set to "NO" by default. Set it to "YES" to enable nginx

#php_fpm_enable="YES"

fcgiwrap_enable="YES"
fcgiwrap_profiles="lightsquid"
fcgiwrap_flags="-c 4"
fcgiwrap_lightsquid_socket="unix:/var/run/fcgiwrap/lightsquid.socket"
fcgiwrap_lightsquid_user="www"
#-------------------------------------------------------------------------#

Запускаем всех демонов:

service squid start
service ipcad start
service fcgiwrap start
service nginx start

Пробуем выйти в интернет, открыть запрещенные сайты - все должно работать как и предполагали. Через пять минут пробуем зайти в Free-SA http://squid.local/ и посмотреть статистику. Чтобы посмотреть статистику в режиме реального времени нужно открыть ссылку http://squid.local/cgi-bin/, где squid.local - имя вашего сервера с nginx.


Ссылки по теме:

  1. Rejik FAQ: А нельзя ли обойтись без установки локального web сервера?
  2. Wiki - IT рабочие заметки: ipcad
  3. lissyara.su: Анализатор статистики Free-SA
  4. rootmaster.at.ua: шлюз для небольшой сети на основе FreeBSD.
  5. Подсчет трафика с помощью Squid и ipcad в pfSense 1.2.3
  6. coolchevy's blog: Simple CGI support for Nginx
  7. Habrahabr: Вебсервер nginx + fastcgi-wrapper + matlab
  8. nginx.localdomain.pl: Simple CGI support for Nginx (fcgiwrap)
  9. Rejik: DBL листы - что это и где взять?
  10. Free-SA log processor

Comments

comments powered by Disqus