Statystyki odwiedzin dla wielu serwisów z AWStats

Co prawda na swojej stronie zrobiłem kilka podstawowych statystyk i coś tam sobie loguję do bazy danych, ale gdyby się chwilę zastanowić to przecież to samo robi serwer www – wrzuca do logów każde zapytanie HTTP, kod błędu, nazwę agenta, itd. Dublowanie tych danych nie jest najbardziej optymalne.
Stąd też chwilę pogooglałem i znalazłem świetny Open Source’owy projekt: AWStats, który jest webowym analizatorem logów dla serwerów HTTP, FTP i SMTP.

Instalacja i konfiguracja

Najpierw instalacja, na moim Debianie leci to tak:

sudo apt-get install awstats

Teraz trzeba się chwilę zastanowić nad konfiguracją serwera i celem, który chcemy osiągnąć:

  • czy staty będą dostępne publicznie?
  • czy tylko dla ograniczonego grona zainsteresowanych (np. w pewnej sieci)?
  • a może zabezpieczenie hasłem?

Wiedząc, że AWStats działają jako skrypt CGI wystawianie takiego serwisu “na świat” nie wydaje mi się bezpiecznym rozwiązaniem. Wolę np. skonfigurować serwis tak aby był dostępny tylko w LAN’ie, gdzie mam większą władzę i szybciej poradzę sobie z namierzeniem i zablokowaniem ewentualnego napastnika 😉

Opiszę tylko dwa pierwsze przypadki (jak ktoś chce hasło to szybko znajdzie jak je ustawić) – pierwsza dla leniwych, druga dla ambitnych 😉

Przygotowania

Bez względu na wybraną metodę konfiguracji (leniwą, bądź nie) do działania serwisu potrzebny jest włączony w Apache moduł CGI. Jest tak w domyślnej konfiguracji ale jeśli nie masz pewności to odpal:

a2enmod cgi

Musi też być zdefiniowany katalog ze skryptami CGI z uaktywnioną interpretacją CGI – domyślnie w pliku /etc/apache2/sites-available w pliku default jest poniższa konfiguracja:

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>

Na potrzeby metody leniwej jest to wystarczająca konfiguracja, dla ambitnych zalecam trochę inne umiejscowienie tego kodu.

Metoda dla leniwych

Ponieważ pakiet AWStats instaluje się przykładową konfiguracją można bardzo szybko uruchomić staty, wystarczy skopiować jeden plik:

cp /usr/share/doc/awstats/examples/apache.conf /etc/apache2/conf.d/awstats

No i tyle 😉

Metoda dla ambitnych

Ambitnym zalecam nieco inną konfigurację: z ograniczeniem dostępu do statystyk wyłącznie z LAN’u i tak samo z dostępem do skryptów CGI. W moim przypadku żaden z wystawianych przezemnie serwisów nie korzysta z CGI, więc udostępnianie tych skryptów wszystkim “zainteresowanym” nie ma sensu.

Proponuję wykorzystać taki lub podobny plik konfiguracyjny dla hosta serwującego statystyki:

<VirtualHost *:80>
        ServerName staty.domena.pl
        ServerAdmin webmaster@domena.pl

        DocumentRoot /var/www/stats/
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/stats/>
                Options -Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order Deny,Allow
                Deny from all
                Allow from 192.168.1.0/24
        </Directory>

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order Deny,Allow
                Deny from all
                Allow from 192.168.1.0/24
        </Directory>

        <Directory /var/lib/awstats>
                Options None
                AllowOverride None
                Order Deny,Allow
                Deny from all
                Allow from 192.168.1.0/24
        </Directory>

        Alias /awstats-icon/ /usr/share/awstats/icon/
        <Directory /usr/share/awstats/icon>
                Options None
                AllowOverride None
                Order Deny,Allow
                Deny from all
                Allow from 192.168.1.0/24
        </Directory>

        ErrorLog /var/log/apache2/error.log
        LogLevel warn

        CustomLog /var/log/apache2/access.log combined

	<IfModule mod_rewrite.c>
		RewriteEngine On
		RewriteCond $1 !^$
		RewriteCond %{REQUEST_URI} !.*cgi-bin
		RewriteCond %{REQUEST_URI} !.*awstats.pl
		RewriteRule /(.*)/? /cgi-bin/awstats.pl?config=$1 [PT]
		RewriteRule ^/awstats.pl(.*?) /cgi-bin/awstats.pl$1 [QSA,R,L]
	</IfModule>
</VirtualHost>

Z ważnych rzeczy do personalizacji:

  • ServerName – wpisz swoją nazwę serwisu,
  • Allow from 192.168.1.0/24 – zamień na adres/adresy, które Tobie odpowiadają,
  • mod_rewrite – ostatnich kilka linijek wykorzystuje mod_rewrite do uproszczenia odwołań do statystyk, wystarczy wtedy wpisać adres np. tak: http://staty.domena.pl/nazwa.domeny.ktora.nas.interesuje.pl
  • plik zapisujemy jako /etc/apache2/sites-available/awstats

Teraz zostało nam uaktywnienie site’a:

a2ensite awstats

Część wspólna konfiguracji

Teraz tworzymy katalog na skrypt, który wypisze nam dostępne statystyki:

mkdir /var/www/stats
chown -R www-data:www-data /var/www/stats/

Właściwa konfiguracja AWStats

Pliki konfiguracyjne AWStats znajdują się w katalogu /etc/awstats. Jest ich dokładnie 2 szt.:

  • awstats.conf
  • awstats.conf.local

Plik awstats.conf zawiera przykładową konfigurację wystarczającą do odpalenia statystyk dla pojedynczego hosta. Z kolei plik awstats.conf.local jest miejscem gdzie można wrzucić wspólną konfigurację dla kilku plików hostów.

Jeżeli mamy wiele hostów (a taki przypadek tutaj omawiam) to wygodniej będzie nam wrzucić cały plik awstats.conf do awstats.conf.local i w kolejnych plikach konfiguracyjnych zmieniać tylko parametry rozróżniające poszczególne hosty. Robimy więc tak:

mv /etc/awstats/awstats.conf.local /etc/awstats/awstats.conf.local.orig
mv /etc/awstats/awstats.conf /etc/awstats/awstats.conf.local

Teraz musimy zmienić kilka linijek w pliku awstats.conf.local:

# musimy odszukać i zakomentować poniższe linie

LogFile="/var/log/apache/access.log"
SiteDomain=""
HostAliases="localhost 127.0.0.1"
Include "/etc/awstats/awstats.conf.local"

# w ten sposób

#LogFile="/var/log/apache/access.log"
#SiteDomain=""
#HostAliases="localhost 127.0.0.1"
#Include "/etc/awstats/awstats.conf.local"

# dodatkowo odszukujemy linię
LogFormat=4
# i zamieniamy na
LogFormat=1

Teraz możemy utworzyć pliki konfiguracyjne dla naszych vhostów raptem w kilku linijkach, np.:

LogFile="/var/log/apache2/access.log"
SiteDomain="domena.pl"
HostAliases="www.domena.pl"

Include "/etc/awstats/awstats.conf.local"

Oczywiście trzeba wpisać własną lokalizację pliku access.log. W powyższym przypadku jest to lokalizacja domyślna, wspólna dla wszystkich vhostów – rozróżnienie ruchu do poszczególnych vhostów następuje dzięki podaniu parametrów SiteDomain (podstawowej domeny danej strony) oraz HostAliases (innych domen wskazujących na tego samego vhosta).

Ostatnim elementem jest załadowanie pliku ze wspólną konfiguracją.

Zmiana uprawnień do logów

Aby umożliwić dostęp AWStats do logów serwera Apache musimy wykonać dwie czynności. Na początek zmiana atrybutu dla aktualnego pliku log:

chmod o+r /var/log/apache2/access.log

Później musimy zadbać aby logi po rotacji przez logrotate również zachowywały atrybuty, oraz aby przed rotacją AWStats wygenerowało statystyki, których nie zebrało wcześniej. W tym celu zmieniamy plik /etc/logrotate.d/apache2 tak by wyglądał jak poniżej:

/var/log/apache2/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 644 root adm
        sharedscripts
        prerotate
            /usr/share/doc/awstats/examples/awstats-update
        endscript
        postrotate
                if [ -f /var/run/apache2.pid ]; then
                        /etc/init.d/apache2 restart > /dev/null
                fi
        endscript
}

Przeładowanie konfiguracji Apache

Po tych wszystkich zmianach w konfiguracji musimy zrestartować Apache:

invoke-rc.d apache2 restart

Testy konfiguracji

Aby sprawdzić konfigurację AWStats spróbujemy wejść na stronę:http://staty.domena.pl/cgi-bin/awstats.pl?config=domena.pl

Jeżeli na żadnym z etapów nie popełniliśmy błedu to naszym oczom powinny ukazać się “wspaniałe i upragnione statystyki” 🙂

Jedyną delikatną wadą awstats jest “brzydki” i długi link z cgi w środku… Nieco mnie to irytowało, więc przysiadłem chwilę przy mod_rewrite i przygotowałem regułki (były podane w konfiguracji dla ambitnych), które pozwalają rozpocząć przeglądanie statystyk z uproszczonego linku postaci:

http://staty.domena.pl/domena.pl

Proste, czyste i klarowne, bez zbędnych śmieci.

Co prawda koniec tutora, ale nie koniec samej konfiguracji – poponuję aby przejrzeć przykładowy plik z konfiguracją i zapoznać się z zawartymi tam opcjami.

Konfiguracja backportów na Debianie

Tak się składa, że Debian ze względu na stosunkowo rzadkie wydawanie kolejnych wersji szybko staje się niezbyt świeży a dostępne w nim pakiety często nie spełaniają naszych oczekiwań. Nie ma najnowszej wersji Subversion… Nie ma mod_security itd, itp…

Rozwiązaniem tego problemu może być instalacja pakietów z testowej gałęzi ale można polec na zależnościach. Można też kompilować ze źródeł… Tak czy siak w obu przypadkach aktualizacja i utrzymanie tak zmodyfikowanego systemu byłoby jak wrzód na zadku.

Na szczęście jest prostsze rozwiązanie. System backportów – czyli repozytorium dostarczające możliwie najnowsze wersje pakietów dla gałęzi stabilnej. Dodając jedno źródło można zainstalować subversion, mod_security i inne, a przy tym równocześnie nie rozwalić sobie systemu.

Konfiguracja – Squeeze

Najpierw trzeba dodać dodatkowe źródło pakietów:

echo "deb http://backports.debian.org/debian-backports \
squeeze-backports main contrib non-free" >> /etc/apt/sources.list

Konfiguracja – Lenny

Najpierw trzeba dodać dodatkowe źródło pakietów:

echo "deb http://backports.debian.org/debian-backports \
lenny-backports main contrib non-free" >> /etc/apt/sources.list

Ponadto w Lennym dostępne jest drugie repozytorium backportów tzw. lenny-backports-sloppy – to repozytorium nie gwarantuje bezproblemowej aktualizacji do Squeeze’a ale powinny się tam znaleźć nowsze wersje pakietów niż w przypadku podstawowego repo.

Dodatkowym krokiem w przypadku Lennego, aczkolwiek zalecanym jest ustawienie tzw. pinningu dla backportów, aby pakiety zainstalowane z nich były aktualizowane. Robimy to wklepując:

echo "Package: *" >> /etc/apt/preferences
echo "Pin: release a=lenny-backports" >> /etc/apt/preferences
echo "Pin-Priority: 200" >> /etc/apt/preferences

Odświeżanie repozytoriów

Teraz odświeżamy repozytoria:

apt-get update

Instalacja pakietów z backportów

Instalacja pakietów z backportów wymaga wymuszenia ich użycia, dzięki czemu jedynie wybrane przez nas pakiety zostaną zainstalowane w nowszych wersjach. Robimy to przykładowo tak:

apt-get -t squeeze-backports install subversion

lub

apt-get -t lenny-backports install subversion

To tyle. Możemy korzystać z aktualnych wersji paczek.

Dynamiczne IP i RBL’e

Mój serwer pocztowy działa od jakiegoś czasu na dynamicznym IP (dobre bo tanie…) i przeważnie nie ma z tym problemów. Postarałem się jak mogłem ustawiając SPF’a i DomainKeys aby uwiarygodnić go u większych dostawców poczty.

Niestety wszystko to diabli biorą w momencie gdy wygasa mi leasse DHCP i dostaję nowe IP po jakimś spamerze/zombiaku. Wisi takie w 2-3 większych RBL’ach i o dostarczaniu poczty można zapomnieć. Miło gdy jeszcze zdalny MTA zechce odesłać zwrotkę “zróbta coś bo wisisz w RBL’u takim a takim…”, ale zdecydowania niefajnie gdy wysyłasz pocztę a ona od razu leci do /dev/null 🙁

rblcheck

Poszperałem trochę i znalazłem fajne narzędzie aka rblcheck, które sprawdza domyślnie kilka RBL’i. Można też dodać kolejne jako parametry. Wygląda to mniej więcej tak:

$ rblcheck 89.76.116.114
89.76.116.114 not listed by sbl.spamhaus.org
89.76.116.114 not listed by xbl.spamhaus.org
89.76.116.114 not listed by pbl.spamhaus.org
89.76.116.114 not listed by bl.spamcop.net
89.76.116.114 not listed by list.dsbl.org
89.76.116.114 not listed by dnsbl.njabl.org
89.76.116.114 listed by dul.dnsbl.sorbs.net

Jak widać IP wisi w jednym z RBL’i.

Można odpytać RBL’e o konkretny powód znalezienia się na liście (o ile funkcja taka jest obsługiwana):

$ rblcheck 89.76.116.114 -t
89.76.116.114 not listed by sbl.spamhaus.org
89.76.116.114 not listed by xbl.spamhaus.org
89.76.116.114 not listed by pbl.spamhaus.org
89.76.116.114 not listed by bl.spamcop.net
89.76.116.114 not listed by list.dsbl.org
89.76.116.114 not listed by dnsbl.njabl.org
89.76.116.114 listed by dul.dnsbl.sorbs.net: \
Dynamic IP Addresses See: http://www.sorbs.net/lookup.shtml?89.76.116.114

W tym przypadku nie było się czym przejmować. Ta lista zawiera wszystkie IP dynamiczne, więc nic dziwnego że nasze dynamiczne też tam jest. Nawet jeżeli ktoś będzie korzystać z tej listy to raczej nie na zasadzie odcinania się od dynamicznych IP, ale w ramach punktowania wiarygodności danego adresu. Z naszej strony za bardzo nie jesteśmy w stanie nic z tym zrobić (bo nie zamierzamy dopłacić za statyczne IP), więc tak musi być.

Automatyzacja

Najpierw zainstalowałem rblcheck‘a:

sudo apt-get install rblcheck

Później w /usr/local/sbin/check_rbls.sh utworzyłem skrypt sprawdzający kilka interesujących mnie RBL’i:

#!/bin/bash

IP=`host mojadomena.pl | head -n1  | awk '{print $4}'`
RBLCHECK="rblcheck -t -s dul.dnsbl.sorbs.net \
        -s abuse.rfc-ignorant.org \
        -s postmaster.rfc-ignorant.org \
        -s dsn.rfc-ignorant.org \
        -s ix.dnsbl.manitu.net \
        -s rhsbl.ahbl.org"

$RBLCHECK $IP | awk '{if($2 != "not") print $0 }'

Skrypt ten podlinkowałem aby uruchamiał się co godzinę:

ln -s /usr/local/sbin/check_rbls.sh /etc/cron.hourly/

Dzięki temu prostemu skryptowie jeżeli dostanę IP wiszące w tych kilku RBL’ach to stosunkowo szybko (maksymalnie w ciągu godziny) się o tym dowiem. Jeżeli natomiast IP będzie czyste to nie będę dostawać zbędnych maili. Do tego listę sprawdzanych RBL’i można bardzo łatwo powiększyć o kolejne w razie takiej potrzeby.

Wysyłanie załączników poleceniem mail

Kiedyś potrzebowałem w ramach testu obciążeniowego wysłać dużo wiadomości z załącznikami. Chciałem to zrobić na szybko z shell’a i tutaj chwilę musiałem pogooglać aby znaleźć działające polecenie. To co znalazłem wygląda tak:

(echo "testowa wiadomosc"; uuencode test.zip test.zip) \
| mail -s "Test" testowy@mail.pl

Wiedząc już jak wysyłać maile z załącznikami, mały mail bombing mogłem zrobić tak:

for i in `seq 1 100`; do
   (cat tekst.txt; uuencode test.zip test.zip) \
   | mail -s "Test $i" testowy@mail.pl;
done

Włam na lokalne konto root’a

Jeżeli tu zaglądasz pewnie zdarzyło Ci się kiedyś, że przykładowo wygrzebujesz jakiś stary serwer i nie masz pojęcia co na nim było, ani do czego służyło, czy jeszcze działa… Albo jeszcze inaczej – serwer działał tak długo, że wszystkie osoby znające hasło na root’a przeszły na emeryturę lub zmarły… Nieistotne 🙂

Jest pewna prosta sztuczka, pozwalająca wbić się na konto root’a nie znając hasła – dając nam możliwość jego zmiany. Potrzebne dwa restarty ale za to nie trzeba korzystać z żadnychlive cd.

  1. Na początek zmuszamy serwer do restartu – mieć nadzieję, że maszyna obsługuje ACPI i delikatne wciśnięcie przycisku power subtelnie ją wyłączy. Jeśli to nie zadziała to kojarzą mi się tylko brzydkie rzeczy 🙂
  2. Gdy po restarcie załaduje się grub na domyślnej opcji bootowania wybieramy edycję wciskając “e“.
  3. Wybieramy linię zaczynającą się od kernel i znów wybieramy edycję wciskając “e“.
  4. Jeżeli znajduje się tam parametr ro to zastępujemy go rw i dopisujemy na końcu init=/bin/bash
  5. Wbijamy “enter” zapisując zmieniony wiersz.
  6. Bootujemy się z tak zmienionej konfiguracji wciskając “b“.
  7. Po chwili system zamiast wystartować init’a i uruchamiać usługi, ląduje w bash’u z uprawnieniami root’a. A skoro mamy root’a to możemy wpisać passwd i zmienić rootowi hasło 🙂
  8. Teraz już tylko reboot i startujemy system normalnie – hasło root’a powinno działać.

Niestety ta prosta sztuczka nie działa na wszystkich linux’ach – szczególnie tych wykorzystujących initramfs-tools. Na tych systemach trzeba ciut więcej pokombinować ale przynajmniej ma się jakiś punkt wyjścia.