• email
  • facebook
  • linkedin
  • google+
  • pinteres

Vírus és spamszűrés beállítása

Ez a leírás elavult, újabb változata megtalálható ezen a linken, amely Ubuntu 12.04-es telepítést mutat be.

1.   Dspam

A Dspam kíváló spamszűrő alkalmazás, csak jókat olvastam róla, és ami a legszimpatikusabb, a felhasználók egyénileg alakíthatják saját vírus adatbázisukat -- ehhez jól működő webes felületet is ad az alkalmazás.

Mivel ez a rész a leghosszab, a spam-szűrés beállítása a legmacerásabb, mindenkinek ajánlom, hogy mielőtt nekiállna a konfigurálásnak, előbb olvassa végig az alábbiakat -- így sok szívás elkerülhető.

A dspam postfixszel történő integrációnak a következő módját választottam (az egyéb lehetséges használati módokat lásd a /usr/share/doc/dspam/README.gz fájlban):

                        |----> (SMTP Reinjection) --->|
[Postfix] (LMTP) -> [DSPAM]                         [Postfix] -> {kézbesítés}
                     |  ^  \
                     ˇ  |    \
                   [CLAMAV]   [karantén]

Ez a következőt jelenti: a postfix SMTP szerver fogadja a leveleket, majd LMTP-vel átadja a dspamnak. A dspam elvégzi a spamek kiszűrését és átadja a clamavnak is a levelet vírusszűrésre. Amit onnan visszakap, és nem vírusos (azokat ti. a clamav eldobja) azt visszainjektálja a postfixnek (ami egy másik porton is figyel) és kézbesíti a leveleket a végfelhasználóknak. Azért ez a megoldás a legkényelmesebb, mert így nem kell sem az SMTP, sem a kézbesítés oldalán leváltani a postfixet.

1.1.   Telepítés

A következő csomagok telepítésére van szükség:

  • dspam libdspam7-drv-pgsql
    • vele: dbconfig-common libdspam7 procmail

Figyelem: a csomag konfigurálásánál ne hozzuk létre az adatbázist, azt majd kézzel fogjuk megtenni, ezért nyomjunk escape-et és ignore-t.

1.2.   Adatbázis

Először az /etc/postgresql/8.1/main/pg_hba.conf fájlban állítjuk be az adatbázis elérést -- kényelmi okokból a lokális elérést is érdemes engedni, hogy majd tudjuk a szkripteket futtatni.

host   dspam           *DSPAMUSER*            127.0.0.1/32           md5
local  dspam           *DSPAMUSER*                                   md5

Az adatbázis szerver újraindítása/reload-ja után jöhet a dspam adatbázis, felhasználó, illetve a táblák létrehozása:

$ /etc/init.d/postgresql-8.1 force-reload
$ psql template1 postgres

CREATE USER *DSPAMUSER* WITH PASSWORD '*DSPAMPASS*';
CREATE DATABASE dspam OWNER *DSPAMUSER*;
\q

$ createlang -U postgres plpgsql dspam
$ psql dspam *DSPAMUSER* -f /usr/share/doc/libdspam7-drv-pgsql/pgsql_objects.sql
$ psql dspam *DSPAMUSER* -f /usr/share/doc/libdspam7-drv-pgsql/virtual_users.sql

Most már törölhetjük a lokális elérést engedő sort a /etc/postgresql/8.1/main/pg_hba.conf fájlból, ami után persze reload-oljuk újra az adatbázist.

1.3.   Konfigurálás

A beállítások elvégzése során az /etc/dspam/dspam.d/pgsql.conf fájlban adhatnánk meg az adatbázis elérésére vonatkozó adatokat, illetve itt állíthatnánk be, hogy az adatbázis uid mezejét használja a felhasználók azonosítására (ez a virtuális felhasználók miatt fontos). Mi ehelyett ezt is az /etc/dspam/dspam.conf fájlba írjuk, ahol egyébként is minden részletes konfigurálás következik (minden érvényes, azaz nem kommentezett sort idevettem):

Home /var/spool/dspam
StorageDriver /usr/lib/dspam/libpgsql_drv.so

#Kokommentezzük:
#TrustedDeliveryAgent "/usr/bin/procmail

#hogy hova kézbesítse a Dspam az e-maileket a szűrés után
# mi átadjuk újra a Postfixnek
DeliveryHost        127.0.0.1
DeliveryPort        10026
DeliveryIdent       localhost
DeliveryProto       SMTP

OnFail error

Trust root
Trust dspam
Trust mail
Trust mailnull
Trust smmsp
Trust daemon
Trust postfix
# A nobody user fontos, ő futtatja az aliasként megadott dspam parancsokat:
Trust nobody

#Debuggoláshoz, ezt érdemes lehet ki- majd visszavenni, ha működik rendesen,
# de élesben mindenképpen kapcsoljuk ki!
#Debug *

# Ez nem teljesen világos mire való
ClassAliasSpam badstuff
ClassAliasNonspam goodstuff

# Alapértelmezetten a teft metódust használjuk
TrainingMode teft
TestConditionalTraining on
Feature noise
Feature chained
Feature whitelist
Feature tb=5
Algorithm graham burton
PValue graham

# lehetne quarantine az érték, ha karanént szeretnénk alapértelmezetten,
# így a Dspam csag tag-el és továbbküld
Preference "spamAction=tag"
# Az üzenet szövegébe tesszük, a dspam azonosítót -- de ez egyénileg
# lehet headers, de így csak attachmentként lehetne elküldeni a spam és nemspam
# aliaszokra a leveleket, a message opcióval inline kerül, és az egyszerű forward is működik
Preference "signatureLocation=message"
Preference "showFactors=off"
Preference "spamSubject=[SPAM]"

AllowOverride trainingMode
AllowOverride spamAction spamSubject
AllowOverride statisticalSedation
AllowOverride enableBNR
AllowOverride enableWhitelist
AllowOverride signatureLocation
AllowOverride showFactors
AllowOverride optIn optOut
AllowOverride whitelistThreshold

PgSQLServer     127.0.0.1
#PgSQLPort       5432
PgSQLUser       *DSPAMUSER*
PgSQLPass       *DSPAMPASS*
PgSQLDb         dspam
PgSQLUIDInSignature     on
PgSQLVirtualTable          dspam_virtual_uids
PgSQLVirtualUIDField       uid
PgSQLVirtualUsernameField  username

Notifications   off

#A /etc/postfix/main.cf-ben lévő myhostname értéke jön ide
LocalMX mester.nir.hu

SystemLog on
UserLog   on

Opt in

#Clamavhoz -- lásd később
ClamAVPort      3310
ClamAVHost      127.0.0.1
ClamAVResponse  spam

ServerPort              10024
ServerQueueSize         32
ServerPID              /var/run/dspam.pid
ServerMode standard

ServerParameters        "--deliver=innocent"
ServerIdent             "localhost.localdomain"

ProcessorBias on

# itt lenne a postgres elérét beállító /etc/dspam/dspam.d/pgsql.conf fájl,
# de mi ezt beleraktuk ebbe a fájlba, így ki kell kommentezni
#Include /etc/dspam/dspam.d/

1.4.   Globális user

Létrehozhatunk egy globális usert, hogy azok a felhasználók is kapjanak majd szűrést, akik nem vacakolnak az egyéni tanítással. Ezután több megoldás van arra, hogy a globális felhasználó vírus adatbázisát minden felhasználó elérje. Tapasztalataim szerint ez igazából árt a rendszernek, én végül kihagytam, de ha valaki ragaszkodik ehhez, vagy netalán nem is akar egyéni szűrést, akkor így kellene csinálni.

A user létrehozásához a /var/spool/dspam/group fájlba a következőt írjuk:

classificationgroup:classification:*global

Az globális felhasználó adatanak egyéni olvasására az egyik lehetőség a merge, amikor az egyéni felhasználói adatokkal minden ellenőrzésnél összeolvasásra kerülnek a globális felhasználó statisztikái. Ehhez a /var/spool/dspam/group fájlba írjuk még a következőt:

global:merged:*

Ezzel tehát (a merge beállításnak köszönhetően) az összes felhasználó egyszerre a saját és a global user szűrési statisztikáit is használja majd. A global felhasználó metaadatainak létrehozásához és/vagy bővítéséhez néha érdemes rendszeresen lefuttatni a dspam_merge parancsot, ami egyes felhasználók adatait összedolgozza egy kijelölt felhasználó metadataiban:

$ dspam_merge user1@foo.hu user2@foo.hu -o global

A másik lehetőség a betanítást közössé tenné a felhasználók számára a rendkívül agresszíven súlyozó inoculation betanítási módszer segítségével. Tapasztalataim szerint ez nagyon veszélyes: ezzel beoltani lehet a rendszert egy spam levél ellen, és utána hiába jelöljük hamis pozitívnak a hasonló leveleket, szinte kiirthatatlanok az első, spamként megadott levél sajátosságai/leírása a spam-szókészletből:

inoculationgroup:inoculation:*global

1.5.   Spam és notspam aliaszok

A dspam szépsége, hogy e-mail aliaszokat hozhatunk létre, amelyekre a felhasználók elküldhetik az átcsúszott leveleket spam vagy ham (nem-spam) újratanításra. Az felhasználóknak nem is kell egyénileg létrehozott e-mail cím ehhez, a dspam minden üzenetet egyéni aláírással lát el, amely alapján beazonosítható, kié az e-mail.

Az aliaszokat két domainre állítjuk be példaképp. Ezek után mindenki elküldheti a spam@foo.hu és a spam@bar.hu címekre a spam-jeit feldolgozásta, illetve notspam@foo.hu és a notspam@bar.hu címre a hamis-pozitív e-maileket (a foo és bar persze behelyettesítendők). Először is a /etc/aliases fájlban kell definiálnunk két globális aliast:

spam:       "|/usr/bin/dspam --user global --class=spam --source=error"
notspam:    "|/usr/bin/dspam --user global --class=innocent --source=error"

De még szebb, ha kliens-szerver üzemmódban használjuk a dspamot és kliensként hívjuk:

spam:       "| /usr/bin/dspamc --client --user global --class=spam --source=error"
nemspam:    "| /usr/bin/dspamc --client --user global --class=innocent --source=error"

Fontos: ennek a binárisnak a futtatásához kell egy kis jogosultságkezelés:

$ chown dspam:dspam /usr/bin/dspamc
$ chmod g+s /usr/bin/dspamc

Illetve a szerver-kliens üzemmód beállításához a dspam.conf-ban a következő beállítások megváltoztatására van szükség:

ServerMode     auto
ServerPass.PipeRelay   "*CLIENTPASS*"

ClientHost     127.0.0.1
ClientPort     10024
ClientIdent     "*CLIENTPASS*@PipeRelay"

Végül lefordítjuk az aliasz fájlt:

$ newaliases

És ne feledjük el, hogy az adatbázisban is fel kell vennünk a négy virtuális aliast:

$ psql mail postgres

INSERT INTO aliases (email, destination) VALUES ('spam@foo.hu', 'spam');
INSERT INTO aliases (email, destination) VALUES ('spam@bar.hu', 'spam');
INSERT INTO aliases (email, destination) VALUES ('notpam@foo.hu', 'notspam');
INSERT INTO aliases (email, destination) VALUES ('notspam@bar.hu', 'notspam');

A /etc/default/dspam fájlban beállítjuk, hogy elinduljon a démon (debbugoláshoz is itt állíthatjuk be a kapcsolót):

START=yes
#OPTIONS="--debug"

Majd elindítjuk:

$ /etc/init.d/dspam start

Ne feledjük, a dspam egyes felhasználók azonosítását lehetővé aláírása alapbeállításunk szerint az üzenet szövegébe kerül. Ha így zavarja az ügyfeleket, a következő módon állíthajuk át parancssorból adott felhasználóra vonatkozóan úgy, hogy a fejlécbe kerüljön az azonosító:

$ dspam_admin ch pref user@foo.hu signatureLocation headers

Fontos: ezzel a beállítással az újratanulásra (az aliaszokra) küldött leveleket csak mellékletként forwardolva tudja a dspam értelmezni, ami elég kényelmetlen, mivel ezt némely levelezőkliensek egyáltalán nem is támogatják, és ha mégis, a legtöbb helyen nem így van beállítva a továbbküldés. Ezért ajánlott a messege-es megoldás.

Visszaálítás:

$ dspam_admin ch pref user@foo.hu signatureLocation message

Az aliaszokkal kapcsolatos egyik probléma, hogy az ezekre érkező levelek egyből bekerülnek a dspamhoz feldolgozásra (Opt out választása esetén, hogy mi is ez, lásd még később), mintha most érkeznének először és csak utána kerülnek az aliaszokhoz (amik igazából speciális kapcsolókkal jelzik a dspam szervernek, hogy ezeknek a leveleknek az esetében újrafeldolgozás (--source=error) történik). Számos lehetőség van rá, hogy elkerüljük a többszöri feldolgozást -- a legjobb a postfixnek megmondani, hogy az általunk megadott spam és notspam e-mail címekre érkező üzeneteket ne adja az LMTP-vel át a dspamnak, hanem egyből küldje az aliaszokra. Hogy ez hogyan történik, azt majd a postfix beállításánál láthatjuk. Egyéb izgalmas/jópofa lehetőségek is lennének a probléma elhárítására -- ezeket a függelékben azért összefoglalom, hátha valakit érdekelnek.

Ezen a ponton még egy apróság van: mivel az aliaszaink egy nem létező global nevű felhasználó nevében hívják a szervert, ezen felhasználó számára be kell kapcsolnunk a szűrést. Erre azért van szükség mert Opt in beállítást választottunk, ami azt jelenti, hogy apalértelmezetten a dspam senkinek a leveleit nem szűri, csak aki belép. (A másik lehetőség az Opt out lett volna, ami éppen a fordítottja.)

Ha valaki használ globális felhasználót (pl. merge vagy inoculation beállítással), akkor erősen javallott ennek a felhasználónak a Train On Error tanítási metódus beállítása. (Ti. alapértelmezetten TEFT-et választottunk -- hogy melyik mit jelent, lásd a /usr/share/doc/dspam/README.gz fájlban.)

A következő két parancs közül az első belépteti a global usert, a második átállítja a tanítási metódusát:

$ dspam_admin ch pref global optIn on
$ dspam_admin ch pref global trainingMode TOE

Végső lépésként az adatbázisban is állítsuk be az egyes alapértelmezéseket, arra az esetre, ha belép valaki a rendszerbe, de nem konfigurál.

$ dspam_admin ch pref default trainingMode TEFT
$ dspam_admin ch pref default spamAction tag
$ dspam_admin ch pref default spamSubject "[SPAM]"
$ dspam_admin ch pref default enableWhitelist on
$ dspam_admin ch pref default showFactors off

1.6.   Tanítás

A dspam tanítása spam-re parancssorból, még nem szűrt, azaz azonosítóval nem megjelölt e-mailre -- ez akkor hasznos, ha e-mail korpuszt szeretnénk betanítani a rendszernek (a global felhasználó lehet bármelyik létező dspam user, pl: valaki@pelda.hu):

$ /usr/bin/dspam --user global --class=spam --source=corpus < /tmp/spam.eml

Ugyanez nem-spamre:

$ /usr/bin/dspam --user global --class=innocent --source=corpus < /tmp/spam.eml

A korpusz-tanítással kapcsolatban: ez a módszer bevett dolog, főleg SpamAssassin felhasználók között, a dspam esetében mégis ellenjavallt, a legtöbb tapasztalt felhasználó azt mondja/írja, az egyéni tanítás sokkal hatékonyabb. Talán akkor van értelme, ha globális felhasználót is használunk mondjuk mergeléssel, de még abban az esetben is jobbnak mondják a dspam_merge rendszeres lefuttatását. Mindenesetre én, főleg mivel globális usert sem használok közös ellenőrzésre, a korpusz-tanítást kihagytam. A spamszűrés pár tucat levél után beindul, pár száz után pedig 99% hatékonyság fölött működik.

1.7.   Adatbázis rendszeres tisztítása

Hátra van még a logfájlok és az adatbázis tisztogatásának automatizálása cron-ból. Ehhez a következőt írjuk a /etc/crontab-ba.

# dspam adatbázis és logfájlok rendberakása
0  0    * * *   root    psql dspam postgres -f /usr/share/doc/libdspam7-drv-pgsql/purge-pe.sql
0  0    * * *   dspam   dspam_logrotate -a 30 -d /var/spool/dspam

Fontos: Ha az elsőt nem a postgres user nevében futtatjuk, akinek trust-ra van állítva az adatbázis elérése, akkor a lefutásához kell, hogy a /root/.pgpass fájlban legyen jelszó a postgres user számára a mail adatbázishoz, 600 jogokkal!

Illetve arra is vigyázzunk, hogy a dspam_logrotate a dspam felhasználóval fusson, különben a root-é lesz a log fájl, és a webes felületről történő tanítás ezek után nem fog tuni működni.

*:*:mail:postgres:*POSTGRESPASS*

Ha tanítási metódust is használunk (a global usernél), különösen fontos, hogy a /usr/share/doc/libdspam7-drv-pgsql/purge-pe.sql fájlt használjuk, ami sajnos ebben az ubuntus dspam csomagban nem volt meg, így kézzel raktam fel a dspam CVS-ből. A lényeg, hogy itt az olyan felhasználóknál, akik TOE tanítási metódust használnak, nem törli a régi adatokat, mivel ezek náluk ritkábban frissülnek majd.

A fájl tartalma egyébként:

DELETE FROM dspam_token_data
  WHERE (innocent_hits*2) + spam_hits < 5
  AND last_hit < CURRENT_DATE - 60;

DELETE FROM dspam_token_data
  WHERE innocent_hits = 0 AND spam_hits = 1
  AND last_hit < CURRENT_DATE - 15;

DELETE FROM dspam_token_data
  WHERE innocent_hits = 1 AND spam_hits = 0
  AND last_hit < CURRENT_DATE - 15;

DELETE FROM dspam_token_data
  WHERE last_hit < CURRENT_DATE - 90
  AND uid NOT IN
    (SELECT uid FROM dspam_preferences
     WHERE preference = 'trainingMode'
     AND value IN('TOE','TUM','NOTRAIN'));

DELETE FROM dspam_token_data
  WHERE uid IN
    (SELECT uid FROM dspam_preferences
     WHERE preference = 'trainingMode'
     AND value = 'TUM')
  AND last_hit < CURRENT_DATE - 90
  AND innocent_hits + spam_hits < 50;

DELETE FROM dspam_signature_data
  WHERE created_on < CURRENT_DATE - 14;

VACUUM ANALYSE;

1.8.   Postfix konfigurálása

Itt két lehetőséget mérlegeltem. Az első szerint minden SMTP-n keresztül érkező levelet szűrnénk. Ehhez az /etc/postfix/master.cf-ben kellene a következő beállítása megejteni (az első sor már bene van, csak a másodikat kell hozzávenni):

smtp      inet  n       -       n       -       -        smtpd
            -o content_filter=lmtp:unix:/tmp/dspam.sock

Ezzel az a probléma, hogy így az összes a szerveren keresztül kiküldött levél is szűrésre kerül és spam azonosítót kap teljesen fölöslegesen, illetve hogy a spam és notspam aliaszokra érkező leveleket is átadná a postfix szűrésre Opt in beállítás esetén. Sokkal jobb lenne, hogy csak a nem autentikált userektől érkezett leveleket szűrnénk, és azokat is kihagynánk, amelyek említett aliaszokra érkeznek. Ez egyszerű is, hiszen a relay-hez SASL autentikáció kell, így minden SASL autentikált levelet tovább engedhetünk szűrés nélkül.

Az előző próbálkozásunkat tehát felejtsük el (töröljük a beállítás), és hozzunk létre egy fájlt ezen a néven /etc/postfix/filter_catchall.regexp és ezzel a tartalommal (a foo és bar persze itt is behelyettesítendő):

!/(spam|notspam)@(foo|bar).hu/ FILTER lmtp:127.0.0.1:10024

Majd a /etc/postfix/main.cf fájlban a a következő megszorítást állítjuk be (csak az utolsó sor új):

smtpd_recipient_restrictions =
    permit_sasl_authenticated,
    reject_unauth_destination,
    permit_mynetworks
    # spam és vírus check a kívülről érkezőkre
    check_recipient_access regexp:/etc/postfix/filter_catchall.regexp

A regexp-es ellenőrzést kihasználva ügyesen megúsztuk azt is, hogy az aliaszainkra érkező leveleink szűrésre kerüljenek Opt in esetén.

(További tippek számos esetre, hogy hogyan kerülhetők meg postfixen az ellenőrzések: http://www200.pair.com/mecham/spam/bypassing.html)

Még hátra van, hogy a Postfixet beállítsuk, hogy a 10026-os porton is foagdjon érkező leveleket, ide fogja ugyanis a Dspam átadni őket. Ehhez a /etc/postfix/master.cf fájlba vegyük fel a következő bejegyzést:

localhost:10026 inet  n -       n       -       -        smtpd
  -o content_filter=
  -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks,no_address_mappings
  -o smtpd_helo_restrictions=
  -o smtpd_client_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks=127.0.0.0/8
  -o smtpd_authorized_xforward_hosts=127.0.0.0/8

Amire különösen figyeljünk, az a receive_override_options bejegyzés: itt adjuk meg, hogy a levelek első, kívülről történő érkezésekor szükséges ellenőrzések és feldolgozási műveletek itt már ne történjenek meg ismét. A no_address_mappings flag például azt adja meg, hogy a címek manipulálása (pl. aliasok beállítása) itt már nem szükséges. Így kerüljük el, hogy kétszer is megkapja minden alias a levelet: az első, és a 10026-os porton történő fogadás után is.

1.9.   Webes felület

Az felhasználók részére hasznos a jól használható webes felület a dspam egyéni szintű konfigurálásához, a karantén ellenőrzéséhez és az újratanításhoz.

Telepítendő csomagok:

  • dspam-webfrontend libapache2-mod-auth-pgsql
    • vele: libfreetype6 libgd-gd2-noxpm-perl libgd-graph-perl libgd-graph3d-perl libgd-text-perl libgd2-noxpm libjpeg62 libpng12-0 libxpm4

Először ejtsük meg a webes interfész konfigurálását. A /etc/dspam/webfrontend.conf fájlban beállítjuk, hogy a felhasználó szintű beállítások az adatbázisban vannak:

$CONFIG{'PREFERENCES_EXTENSION'} = 1;

A /etc/dspam/default.prefs fájlban (a webes felület innen olvassa be a default értékeket) a következő beállítások szerepeljenek:

spamAction=tag
spamSubject=[SPAM]
enableBNR=on
trainingMode=TEFT
enableWhitelist=on
statisticalSedation=5
signatureLocation=message
whitelistThreshold=10
showFactors=off
optIn=off

A /usr/share/dspam/upstream-templates/nav_preferences.html sablonban hozzáadtam a következőt a végére, a checkboxok közé, hogy a szűrést felhasználói szinten is ki-be lehessen kapcsolni:

<br>
<INPUT TYPE=CHECKBOX NAME=optIn $C_OPTIN$>
Opt into DSPAM filtering

Ha Opt out üzemmódot használnánk, akkor ezt kéne helyette írni:

<br>
<INPUT TYPE=CHECKBOX NAME=optOut $C_OPTOUT$>
Opt out of DSPAM filtering

A /usr/share/dspam/upstream-templates/nav_performance.html fájlban pedig beállítjuk az újratanítós spam címünket, hogy szépen látszódjék a dspam adminisztrációs felületen:

<p>
If you receive a message in your e-mail application that was not caught by
the filter, please forward it to
<strong>notspam@foo.hu</strong>
so that it can be analyzed and learned as SPAM. This will improve the filter's accuracy in the future.
</p>

Ezek után következhet az apache beállítása, amelyhez először is két modult kell aktiválnunk:

$ a2enmod suexec
$ a2enmod auth_pgsql

Most jöhet a dspam.enier.hu virtuális hoszt konfigurálása. Itt két célunk van:

  • Egyrészt suexec-kel futtatjuk a cgi fájlokat, dspam user és dspam group nevében, az interfész használata így biztonságosabb, illetve így lesznek jók a jogosultságok, mikor a dspam az adatokat változtatja.
  • Másrészt a mail adatbázisból kérjük majd le a virtuális userek jelszavát az autentikációhoz, így külön adatbázissal vagy .htpasswd fájllal sem kell vacakolni, és a felhasználók az SMTP és POP3 jelszavukkal léphetnek be a dspam webes felületére is.

Először is az adatbázis elérést tegyük lehetővé az apache-nak:

$ psql mail postgres
CREATE USER *DSPAMCGIUSER* WITH PASSWORD '*DSPAMCGIPASS*';
GRANT SELECT ON users TO *DSPAMCGIUSER*;

És ne feledjük a /etc/postgresql/8.1/main/pg_hba.conf ba felvenni:

host   mail            *DSPAMCGIUSER*        127.0.0.1/32           md5

Majd generáljuk le és telepítsük a használandó SSL kulcsot:

$ cd /opt/CA
$ openssl genrsa -out dspam.enier.hu.key 1024
$ openssl req -new -key dspam.enier.hu.key -out dspam.enier.hu.csr
    ...
    Organization Name (eg, company) [NiR Informatikai Megoldások Kft.]:Enier Bt
    Organizational Unit Name (eg, section) [Software Development Team]:Enier Web Services
    Common Name (eg, YOUR name) []:webmail.enier.hu
    Email Address []:hostmaster@enier.hu
    ...

$ openssl x509 -req -in dspam.enier.hu.csr -out dspam.enier.hu.crt -sha1 -CA nir.crt -CAkey nir.key -CAcreateserial -days 365

$ chmod 600 *
$ cp dspam.enier.hu.crt dspam.enier.hu.key /etc/apache2/ssl/

És következhet a /etc/apache2/sites-available/dspam.enier.hu fájl:

<VirtualHost *:4344>
  DocumentRoot "/var/www/dspam/"
  ServerName dspam.enier.hu
  ServerAdmin webmaster@enier.hu

  SuexecUserGroup dspam dspam
  Addhandler cgi-script .cgi
  Options +ExecCGI -Indexes

  <Directory /var/www/dspam/>
    Addhandler cgi-script .cgi
    Options +ExecCGI -Indexes
    DirectoryIndex dspam.cgi

    AuthType Basic
    AuthName "DSPAM Control Center"
    Auth_PG_host localhost
    Auth_PG_database mail
    Auth_PG_user *DSPAMCGIUSER*
    Auth_PG_pwd *DSPAMCGIPASS*
    Auth_PG_pwd_table users
    Auth_PG_uid_field email
    Auth_PG_pwd_field password
    ##Auth_PG_pwd_whereclause
    Auth_PG_hash_type CRYPT

    <LIMIT GET POST>
      require valid-user
    </LIMIT>
  </Directory>

  SSLEngine On
  SSLCipherSuite HIGH:MEDIUM
  SSLProtocol all -SSLv2
  SSLCertificateFile /etc/apache2/ssl/dspam.enier.hu.crt
  SSLCertificateKeyFile /etc/apache2/ssl/dspam.enier.hu.key
  SSLCertificateChainFile /etc/apache2/ssl/nir.crt
  SSLCACertificateFile /etc/apache2/ssl/nir.crt
</VirtualHost>

Hasznos még, hogy ha a sima HTTP portra érkező kéréseket átdobjuk a HTTPS-re, ehhez a fájl elejére még odaírtam:

# Először definiáljuk a sima 80-as porton figyelő
# oldalt ami átdob a https-re
<VirtualHost *>
  ServerAdmin webmaster@enier.hu
  ServerName dspam.enier.hu

  RewriteEngine On
  RewriteRule ^/(.*) https://dspam.enier.hu:4344/$1 [R=301,L]

  RewriteLogLevel 0
  RewriteLog /data/www/enierweb/logs.www-enier.hu/dspam.enier.hu.rewrite.log
  ErrorLog /data/www/enierweb/logs.www-enier.hu/dspam.enier.hu.error.log
  CustomLog /data/www/enierweb/logs.www-enier.hu/dspam.enier.hu.access.log combined
</VirtualHost>

A ports.conf és a conf.d/namevirtualhost értelemszerű frissítése, és az a2ensite dspam.enier.hu után mehet az apache újraindítása és kész is vagyunk!

Patch: A perlben íródott CGI fájl kisebb hibája miatt a felhasználó hibaüzenetet kap az Analyzis oldalon, ha az egyik megjelenítendő grafikonhoz nincs még adat. A hiba nem komoly, miután levelet kap a felhasználó, amit a dspam szűr neki, megszűnik, de mégsem szép. Ha valaki ki szeretné javítani, akkor megteheti John Peacock alábbi patch-ével, amit én a Dspam levlistán találtam.

Vigyázat: A patch nem ehhez az ubuntus verzióhoz való, így a sorok már elcsúsztak. A 495. és az 510. sor környékén kell keresgélni és kézzel javítani.

(Megjegyzés: nekem elrontotta a grafikont, és nem volt kedvem vele vacakolni, ezért kivettem, de ha valakit zavar a jelenség, jó kiindulási pont lehet az alábbi patch.)

$ svn diff -r30:31
Index: dspam.cgi
===================================================================
--- dspam.cgi   (revision 30)
+++ dspam.cgi   (revision 31)
@@ -532,10 +532,13 @@
   foreach my $period (qw( daily weekly )) {
     my $uc_period=uc($period);
     my $hk="DATA_$uc_period";
-    my %lst=();
+    my %lst=(
+       spam => [],
+       nonspam => [],
+       title   => []
+    );
     foreach my $hr (sort {$a->{idx}<=>$b->{idx}} (values %{$Stats{$period}})) {
       foreach my $type (qw( spam nonspam title )) {
-        (exists $lst{$type}) || ($lst{$type}=[]);
         push(@{$lst{$type}},$hr->{$type});
         my $totk="";
         if ($type eq "spam") { $totk="S"; }
@@ -547,9 +550,9 @@
       }
     }
     $DATA{$hk}=join("_",
-               join(",",@{$lst{spam}}),
-               join(",",@{$lst{nonspam}}),
-               join(",",@{$lst{title}}),
+               join(",",@{$lst{spam}}    || [0]),
+               join(",",@{$lst{nonspam}} || [0]),
+               join(",",@{$lst{title}}   || [0]),
        );
   }

Egy másik patch, más problémákat is megold (vigyázat: ez is egy újabb változathoz van, mint ami a Dapperben felkerül):

Index: webui/cgi-bin/dspam.cgi
===================================================================
--- webui/cgi-bin/dspam.cgi   (revision 26)
+++ webui/cgi-bin/dspam.cgi   (working copy)
@@ -531,10 +531,13 @@
   foreach my $period (qw( daily weekly )) {
     my $uc_period=uc($period);
     my $hk="DATA_$uc_period";
-    my %lst=();
+    my %lst=(
+     spam => [],
+     nonspam => [],
+     title   => []
+    );
     foreach my $hr (sort {$a->{idx}<=>$b->{idx}} (values %{$Stats{$period}})) {
       foreach my $type (qw( spam nonspam title )) {
-        (exists $lst{$type}) || ($lst{$type}=[]);
         push(@{$lst{$type}},$hr->{$type});
         my $totk="";
         if ($type eq "spam") { $totk="S"; }
@@ -698,7 +701,7 @@
   }
   open(FILE, "<$MAILBOX");
   while(<FILE>) {
-    chomp;
+    s/\r?\n$//;
     push(@buffer, $_);
   }
   close(FILE);
@@ -759,7 +762,7 @@

   open(FILE, "<$MAILBOX");
   while(<FILE>) {
-    chomp;
+    s/\r?\n$//;
     push(@buffer, $_);
   }
   close(FILE);
@@ -839,7 +842,7 @@

   open(FILE, "<$MAILBOX");
   while(<FILE>) {
-    chomp;
+    s/\r?\n//;
     push(@buffer, $_);
   }
   close(FILE);
@@ -907,7 +910,7 @@
   }
   open(FILE, "<$MAILBOX");
   while(<FILE>) {
-    chomp;
+    s/\r?\n//;
     push(@buffer, $_);
   }
   close(FILE);
@@ -980,7 +983,7 @@
   $rowclass="rowEven";
   open(FILE, "<$MAILBOX");
   while(<FILE>) {
-    chomp;
+    s/\r?\n//;
     if ($_ ne "") {
       if ($mode eq "") {
         if ($_ =~ /^From /) {

2.   Clamav

Spamszűrő rendszerünkhöz illesszünk vírusszűrést is. Ehhez először telepítsük a Clamavot. A levelek átadásáról a vírusszűrőnek majd a dspam gondoskodik.

Telepítendő csomagok:

  • clamav clamav-freshclam clamav-base clamav-daemon clamav-docs arj unzoo * ca-certificates libclamav1 libcurl3 libgmp3c2 sharutils

A Clamav démon beállításai a /etc/clamav/clamd.conf fájlban találhatók, nincs vele sok teendő, gyakorlatilag a 3310-es portot kell csak megnyitnunk:

TCPSocket 3310
User clamav
AllowSupplementaryGroups
ScanMail
ScanArchive
ArchiveMaxRecursion 5
ArchiveMaxFiles 1000
ArchiveMaxFileSize 20M
ArchiveMaxCompressionRatio 250
ReadTimeout 180
MaxThreads 12
MaxConnectionQueueLength 15
LogFile /var/log/clamav/clamav.log
LogTime
LogFileMaxSize 100M
PidFile /var/run/clamav/clamd.pid
DatabaseDirectory /var/lib/clamav
SelfCheck 3600

#A részletes logoláshoz ezt kikommentezhetjük
#LogVerbose

(Az ArchiveBlockMax inkább paranoiásoknak való kapcsolót jobb kivenni, alapértelmezetten ki is van kapcsolva, csak a debian/ubuntu csapat kapcsolja be.)

A vírusszűrésre való átadásért a dspam lesz a felelős, így nem kell az Amavisd-new vacakolnunk. Csak a /etc/dspam/dspam.conf fájlban kell a következőket beállítani:

ClamAVPort      3310
ClamAVHost      127.0.0.1
ClamAVResponse  spam

Hogy a Freshclam, a vírus adatbázist frissítő démon ne a default mirror-t használja, állítsuk be a /etc/clamav/freshclam.conf fájlban a következőt:

DatabaseMirror clamavdb.ikk.sztaki.hu

A démonok újraindítása után működik is minden:

$ /etc/init.d/clamav-freshclam restart
$ /etc/init.d/clamav-daemon restart

Ha zavar minket a dirname-s hibaüzenet a clamav démon újraindításakor, akkor a /etc/init.d/clamav-daemon fájlban kommentezzük ki a következő két sort:

#CLAMSOCKETDIR="$(dirname $(grep "^LocalSocket" ${CLAMAVCONF} | awk '{print $2}'))"
#  [ -x $CLAMSOCKETDIR ] && chown $CLAMUSER $CLAMSOCKETDIR -R

3.   Postgrey

A postgrey egy ügyes kis eszköz, ami elsőre eldob minden feladót adott e-mail címre, és csak ha X idő múlva másodszor is elküldi a levelet, akkor teszi whitelist-re a küldő IP-t. Ez a módszer igen hatékonynak bizonyult a spamek ellen -- egyelőre.

Telepítendő:

  • postgrey
    • vele: libberkeleydb-perl libdigest-hmac-perl libdigest-sha1-perl libio-multiplex-perl libnet-dns-perl libnet-ip-perl libnet-server-perl

A /etc/default/postgrey fájlban kicsit alacsonyabbra vesszük az alapértelmezett delay-t:

POSTGREY_OPTS="--inet=127.0.0.1:60000 --delay=150"

És a /etc/postfix/main.cf fájlban a smtpd_recipient_restrictions paraméterei között aktiváljuk az ellenőrzést:

smtpd_recipient_restrictions =
smtpd_recipient_restrictions =
    permit_sasl_authenticated,
    reject_unauth_destination,
    # greylisting bekapcsolása postgrey-yel
    check_policy_service inet:127.0.0.1:60000
    permit_mynetworks
    check_sender_access regexp:/etc/postfix/filter_catchall.regexp

Jöhet a démonok újraindítása és kész is:

$ /etc/init.d/postgrey restart
$ /etc/init.d/postfix restart

4.   Dspam karantén tisztító szkript

Ha tartunk tőle, hogy a karantén egy idő után túl naggyra nő, érdemes lehet rendszeressen ellenőrizni az ott lévő mailboxokat, és a bizonyos időnél régebbi leveleket törölni. Ezt a feladatot végzi el az alábbi szkript.

Figyelem: a futtatáshoz telepítenünk kell az archivemail csomagot!

#!/bin/bash
# age_spam_quarantine - Remove quarantined messages older
# than a specified number of days.
#    Steve Pellegrin (spellegrin at convoglio dot com)
#
# History:
#    1.0   2005-January-1    Original code
#    1.1   2005-February-3   Works with large, domain or standard
#
# Usage:
#    age_spam_quarantine

DAYS=33                                 # Messages left in quarantine older
                                        # than this many days will be deleted.
DATA=~dspam/data                        # DSpam data directory
ARCHIVEMAIL="/usr/bin/archivemail"      # Path to utility

# For each user mailbox...
for mbox in ``find ${DATA} -follow -name *mbox`
do
    if [ -s $mbox ]; then
        # Tell archivemail to remove the messages.
        ${ARCHIVEMAIL} --days=${DAYS} --delete --include-flagged --quiet $mbox
    fi;
done

A hatodik részben a webmailt illesztünk rendszerünkhöz.


5.   Függelék -- más módszerek a dspam aliaszok megkerültetésére

Emlékszünk a problémára: ha Opt out belépési módot választottunk, azaz alapértelmezetten minden érkező levelet szűrünk, akkor ha a spam és notspam aliaszokra küldünk levelet, hogy újrataníttassuk a rendszerrel, a dspam előbb azokat is feldolgozza újként, és feldologzás adatai a spam@szerver.neve.hu és notspam@szerver.neve.hu felhasználó adataihoz kerülnek, akik persze nem is létező userek. Ez azért van, mert mint minden bejövő levél, az ezen aliaszokra érkezők is a dspam filterhez kerülnek, és sajnos még azelőtt, hogy az aliaszokat elérve kerülnének a dspam szerver felé átadásra (más kapcsolókkal). Itt tehát kétszer is átmennek a rendszeren, de sajnos a második már mitsem ér.

Első megoldás:

A következő hack megoldja a problémát, igaz csúnya: kikapcsolhatjuk a spam és nemspam aliasokhoz kapcsolódó usereknél a dspam szűrést, magában a dspamben, és így azok elemzés nélkül kerülnek ki onnan, tovább a második dspam állomásra, ahol már a megfelelő felhasználó adatai alapján kerülnek feldolgozásra.:

$ dspam_admin ch pref spam@szerver.neve.hu optOut on
$ dspam_admin ch pref notspam@szerver.neve.hu optOut on

Másik megoldás:

A fenti aliaszokat meghagyjuk az adatbázisban, mert továbbra is ezek alapján, a spam@szerver.neve.hu és a notspam@szerver.neve.hu e-mail cím lesz a névleges végállomás, illetve a /etc/aliases-ban is meghagyjuk, hogy lokálisan is lehessen küldeni hibásan osztályozott e-mailt. Viszont átírjuk, hogy kliensként hívja a dspam szervert, és nem is a dspam binárist, hanem a "vékonyabb kliens"-ként aposztrofált dspamc-t hívjuk. (Ne feledjük utána a newaliases parancsot kiadni!):

spam:           "| /usr/bin/dspamc --client --user global --class=spam --source=error"
nemspam:        "| /usr/bin/dspamc --client --user global --class=innocent --source=error"

Írunk egy szkiptet a /usr/local/bin/dspamit.sh fájlba a következő tartalommal:

#!/bin/sh

PATH=/usr/local/bin:/usr/bin:/bin
DSPAM="/usr/bin/dspamc"
SPAM="spam@szerver.neve.hu"
NEMSPAM="notspam@szerver.neve.hu"

# Get arguments
recip="$1"; shift

if [ "$recip" = "$SPAM" ]; then
    $DSPAM --client --user global --class=spam --source=error
elif [ "$recip" = "$NEMSPAM" ]; then
    $DSPAM --client --user global --class=innocent --source=error
else
   $DSPAM --client --deliver=innocent --user $recip
fi

exit $?

Majd kis jogosultságkezelés:

$ chown dspam.dspam /usr/local/bin/dspamit.sh
$ chmod 770 /usr/local/bin/dspamit.sh

A /etc/postfix/master.cf fájlban létrehozunk egy szűrőt:

dspamit     unix  -       n       n       -       10      pipe
    flags=Rhqu user=dspam argv=/usr/local/bin/dspamit.sh ${recipient}

És a korábban szűrésre létrehozott /etc/postfix/filter_catchall.regexp fájlt átírjuk így:

/^/ FILTER dspamit:dspamit

Illetve a /etc/postfix/main.cf fájlhoz adjuk hozzá a következő sort, hogy a dspamit szkript egyszerre csak egy levelet kapjon feldolgozásra:

dspamit_destination_recipient_limit = 1

Ezzel az utolsó meglodással az összes kívánt eredményt elérjük:

  • a Dspam csak egyszer szűri a leveleket
  • működnek a globális aliasok a Dspam tanításához
  • és lokálisan is taníthatjuk a Dspamot
  • csak a bejövő leveleket szűrjük
  • de a SASL autentikált felhasználóknál azokat sem

Ez esetben használhatnánk egyszerű parancssori alkalmazásként, és ki is kapcsolhatnánk a /etc/init.d/dspam démont, de sokkal erőforráskímélőbb, ha továbbra is démonként futtatjuk, és a parancssorból kliensként hívjuk. Egy példa az erőforrások kímélésére: így nem kell minden alkalommal új adatbáziskapcsolatot létrehozni, mert arról a szerver gondoskodik. -->