Archiwum kategorii: konfiguracja usług

Nowy zestaw reguł dla Spamassasina

Około miesiąc temu dodałem nowy zestaw reguł. Są to reguły generowane automatycznie z treści spamu który otrzymuję. Tych reguł jest dosyć dużo, wszystkie to są regexpy, zatem może zauważalnie wzrosnąć obciążenie Waszych serwerów jeśli obsługują one dużą ilość ruchu.
Gdyby były tego typu problemy to dajcie znać. Jeśli te reguły będą działać i wyłapią to czego nie łapią inne reguły, dajcie znać. Jak będą false positive to także proszę o informację.

2024-04 – reguły nadal są generowane i można z nich korzystać.

Nowy RBL (uribl) oraz kanał z regułami dla Spamassassina

Niedawno uruchomiłem swoją nową czarną listę, do tej pory była to lista oparta na adresach IP serwerów wysyłających emaile (http://blog.mejor.pl/2011/10/czarna-list-rbl/). Ta lista miała pewną wadę, część spamerów dosyć często zmienia adresy IP swoich serwerów, przez to często byłem „zaskakiwany”, że dany nadawca przedostał się przez sito. Zatem zacząłem dodatkowo używać nazw domenowych pojawiających się w treści emaili. Aby elastycznie zarządzać taką listą niechcianych domen to wybór był prosty: uribl. Tak o to powstał uri RBL o adresie uribl.mejor.pl.

Tak jak i „ipkowy” RBL jest głownie nastawiony na walkę z polskimi, niechcianymi mailami marketingowymi tak i ten ma podobny charakter. Co nie oznacza, że inny rodzaj spamu nie jest (o ile da się) dodawany do owych RBLi.

Aby w skorzystać z tego uribl w Spamassassinie proponuję taki zestaw reguł:

 

uridnsbl_skip_domain    www.spamcop.net openspf.net microsoft.com amazonaws.com
urirhssub       LR_URIBL_H1     uribl.mejor.pl. A   127.0.0.1
body            LR_URIBL_H1     eval:check_uridnsbl(’LR_URIBL_H1′)
describe        LR_URIBL_H1     Contains an URL listed in the uribl
tflags          LR_URIBL_H1     net domains_only
urirhssub       LR_URIBL_H2     uribl.mejor.pl. A   127.0.0.2
body            LR_URIBL_H2     eval:check_uridnsbl(’LR_URIBL_H2′)
describe        LR_URIBL_H2     Contains an URL listed in the uribl
tflags          LR_URIBL_H2     net domains_only

 

Punktację proszę sobie ustawić według własnego smaku:)

 

Drugą nowością u mnie jest uruchomienie kanału z regułami dla Spamassasina. Tam planuję umieszczać reguły do wyłapania tego czego nie wyłapią oba w/w RBLe (lub mimo tego dany spam będzie zbyt nisko punktowany) oraz zestaw reguł od Lemata. A także reguły wyłapujące aktualnie rozsyłany wiruso-spam z botnetów (zwłaszcza, że często nie jest on wykrywany przez antywirusa przez dosyć długi czas). Te reguły mogą być aktualizowane nawet kilka razy dziennie (albo w ogóle przez kilka tygodni:)) dlatego proponuję często uruchamiać sa-update. Do tego zestawu reguł dla SA dodałem w/w reguły dotyczące uribl. Więc jeśli skorzystasz z tego kanału to nie musisz dodawać powyższych reguł (ani reguł dodających rbl.mejor.pl ).

W celu dodania oraz aktualizacji tych reguł można użyć takiego polecenia: sa-update --nogpg --channel sa.mejor.pl

 

W razie pytań proszę o pozostawienie komentarza.

Czarna list adresów ip (RBL) nadawców maili

Pod adresem rbl.mejor.pl jest dostępna moja własna lista adresów ip, od których nie chcę otrzymywać emaili. Najczęściej są to maile z „to nie jest oferta handlowa”. Jest to lista (obecnie) trójstopniowa, zwracam rekordy o wartości 127.0.0.1, 127.0.0.2, 127.0.0.5. Zwykle wygląda to w ten sposób, że pierwszy email to jeden punkt, drugi to dwa, trzeci to pięć. Jak zawsze są wyjątki, jeśli mail dostał zbyt mało punktów z innych reguł to ipek nadawcy może już w pierwszym podejściu awansować na wyższy pułap (lub gdy treść była wyjątkowo irytująca).
Na swojej liście mam umieszczony np. Linkedin, za spamowanie zaproszeniami. Ostrzegam…
Sposób odpytywania rbla jest klasyczny, jeśli interesuje kogoś co sądzę o adresie 1.2.3.4 to odpytuje o rekord A dla hosta 4.3.2.1.rbl.mejor.pl.

Poniżej zamieszczam gotowca do spamassassina (zawierającego również punktację dla białej listy).


header __LR_NADAWCA_W_H eval:check_rbl('horhe-lastexternal', 'rbl.mejor.pl.')
describe __LR_NADAWCA_W_H Odebrane od nadawcy w RBL horhe
tflags __LR_NADAWCA_W_H net
reuse __LR_NADAWCA_W_H

header LR_NADAWCA_W_RBL_H1 eval:check_rbl_sub('horhe-lastexternal', '127.0.0.1')
describe LR_NADAWCA_W_RBL_H1 Odebrane od nadawcy w RBL horhe
tflags LR_NADAWCA_W_RBL_H1 net
score LR_NADAWCA_W_RBL_H1 1
reuse LR_NADAWCA_W_RBL_H1

header LR_NADAWCA_W_RBL_H2 eval:check_rbl_sub('horhe-lastexternal', '127.0.0.2')
describe LR_NADAWCA_W_RBL_H2 Odebrane od nadawcy w RBL horhe
tflags LR_NADAWCA_W_RBL_H2 net
score LR_NADAWCA_W_RBL_H2 2
reuse LR_NADAWCA_W_RBL_H2

header LR_NADAWCA_W_RBL_H5 eval:check_rbl_sub('horhe-lastexternal', '127.0.0.5')
describe LR_NADAWCA_W_RBL_H5 Odebrane od nadawcy w RBL horhe
tflags LR_NADAWCA_W_RBL_H5 net
score LR_NADAWCA_W_RBL_H5 5
reuse LR_NADAWCA_W_RBL_H5

header LR_NADAWCA_W_RWL_H1 eval:check_rbl_sub('horhe-lastexternal', '127.0.1.1')
describe LR_NADAWCA_W_RWL_H1 Odebrane od nadawcy w RWL horhe
tflags LR_NADAWCA_W_RWL_H1 net
score LR_NADAWCA_W_RWL_H1 -1
reuse LR_NADAWCA_W_RWL_H1

header LR_NADAWCA_W_RWL_H2 eval:check_rbl_sub('horhe-lastexternal', '127.0.1.2')
describe LR_NADAWCA_W_RWL_H2 Odebrane od nadawcy w RWL horhe
tflags LR_NADAWCA_W_RWL_H2 net
score LR_NADAWCA_W_RWL_H2 -2
reuse LR_NADAWCA_W_RWL_H2

To jest moja własna lista, nie ponoszę odpowiedzialności za skutki jej użycia przez innych.

Weryfikacja nadawcy maila część 2.

Założenie: chcemy pozwolić aby użytkownik, który przeszedł autoryzację, mógł wysłać maila z polem „From:” zawierającym jego główny adres mailowy lub alias prowadzący do bazowego konta.

Opis z poprzedniego wpisu załatwiał nam część do momentu „lub alias”.  Czyli mieliśmy tak:

deny

authenticated  = *
condition      = ${if eq {$authenticated_id}{${lc:$sender_address}}{no}{yes}}
message         = rejected: Nieprawidłowy nadawca.

Czyli potrzebujemy rozbudować to o warunek sprawdzający czy adres nadawcy jest aliasem do użytkownika, którym użytkownik się zautoryzował. Zaimplementowanie tego jest mocno uzależnione od sposobu przechowywania tych danych w konkretnej instalacji. I różnica powinna sprowadzić się do przepisania warunku w selekcie. Tutaj zapytanie będzie dostosowane do mojej bazy, która jest bardzo podobna do omawianej w innych wpisach na tym blogu. W międzyczasie od napisania poprzedniego artykułu, zmieniłem trochę ten warunek, obecnie wygląda następująco:
condition = ${if or {
{ !eqi{$authenticated_id} {$sender_address}}\
{ !eqi{$authenticated_id} {${address:$header_From:}} }\
}\
}

Czyli mamy tutaj drugi test (dodatkowo sprawdzam nagłówek „From:”) oraz została odwrócona logika warunku. Drobiazg:)

Zdefiniujmy zapytanie do bazy danych zwracające nam wszystkie aliasy dla danego konta. Nie możemy zapomnieć także, że to zapytanie powinno zwrócić także głównego użytkownika!:)
PGSQL_Q_AUTH = SELECT alias FROM aliasy WHERE destination = '${quote_pgsql:$authenticated_id}' UNION SELECT '${quote_pgsql:$authenticated_id}'

Oraz warunek, który sprawdza nadawcę:

!condition = ${if and{\
{forany{<\n ${lookup pgsql {PGSQL_Q_AUTH}}}{eqi{$item}{$sender_address}} }\
{forany{<\n ${lookup pgsql {PGSQL_Q_AUTH}}}{eqi{$item}{${address:$header_From:}}} }\
}\
}

Smacznego!

P.S. Nie mam pojęcia dlaczego tak trudno jest w wordpressie użyć tabulacji do robienia wcięć w tekście. Sprawdzałem jakieś dwie wtyczki, bez pozytywnego rezultatu. I z tego powodu, wpisy eximowe wyglądają okropnie.

exim i port 587

Najpierw mówimy eximowi aby słuchał na 587:

daemon_smtp_ports = 25 : 465 : 587

A teraz musimy wymusić aby wszystko co przychodzi na ten port musiało zautoryzować się:

acl_check_rcpt:

[…]

deny    condition      = ${if eq {$interface_port}{587} {yes}{no} }
!authenticated = *
message        = SMTP AUTH required over port 587 / wymagana autoryzacja na porcie 587

message        = 530 SMTP AUTH required over port 587 / wymagana autoryzacja na porcie 587

Poprawka, aby być zgodnym z rfc 4409 4.3 .

Walka z collateral spamem

Z fałszywymi zwrotkami napewno często mieliście doczynienia. Nagle dostajecie wiadomości, że wiadomość nie mogła być dostarczona użytkownikowi np. xxx@kolekcja.mejor.pl , albo dostajecie info o tym, że w mailu był wirus i został odrzucony.

Problem ten wynika z nieprawidłowej konfiguracji serwera. Powinien on jeszcze w czasie sesji sprawdzać czy istnieje odbiorca, czy mail nie spełnia warunków aby zostać zakwalifikowanym jako spam, czy nie zawiera wirusa. Część MTA przyjmuje całęgo maila, potem procmailem dostarcza do skrzynek użytkowników. I wtedy sprawdza czy mail to spma itp. Jeśli tak to generowana jest wtedy zwrotka, tylko nie idzie ona do prawdziwego nadawcy (ponieważ to zombie rozsiewajacy spam), tylko do niewinnego użytkownika.

I do tego dokładają się autorespondery („Jestem na urlopie..”).

Jak można więc wykryć czy zwrotka jest „nasza” czy nie? Na przykład można dodać coś w treści, i sprawdzać jest to zawarte w zwrotce. W eximie jest dostępna mechanizm o nazwie BATV. Wysyłany mail jest wtedy znakowany w taki sposób: envelope-from <prvs=03310137b9=xxx@kolekcja.mejor.pl> . Pojawia się nam fragment „prvs=xxxxxxx=”, jest  to hash generowany na podstawie wybranego hasła oraz bieżącej daty (sygnatura taka jest ważna tylko przez pewien czas). Jeżeli tego fragmentu nie będzie to exim odrzuci zwrotkę oraz poinformuje nas o tym w logu:

rejected after DATA: bounce messages must be returned to a BATV signed address

Zauważyłem niestety i minus korzystania z tego mechanizmu. Bywają odrzucane potwierdzenia przeczytania wiadomości. Generowane poprzez (nie jestem tym zaskoczony) „dużego” Outlooka. Trudno, zysk jest większy niż straty.

A teraz najważniejsze, jak to się konfiguruje.

Na początek musimy w głównej sekcji ustawić sobie hasełko do hasha:

BATVKEY = cosTAJEMNICZEGO

Potrzebujemy dwóch nowych ruterów (przypominam, o tym, że kolejność definicji ruterów ma znaczenie!):

dnslookup_batv:
driver = dnslookup
condition = ${if match_domain{$sender_address_domain}{+local_domains}}
domains = ! +local_domains
transport = external_smtp_batv
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8

batv_redirect:
driver = redirect
data = ${prvscheck {$local_part@$domain}{BATVKEY}}

Oraz potrzebujemy transportu:

external_smtp_batv:
driver = smtp
return_path = ${prvs {$return_path}{BATVKEY}}

Weryfikacja nadawcy maila część 1.

Podczas dotychczasowych opisów konfiguracji Exima umknęła mi kwestia weryfikacji nadawcy, czy nadawca jest taki sam jak użytkownik, który się zautoryzował poprzez SMTP AUTH. Na tą sytuację zwrócił mi uwagę Adrian H. Dzięki :)

Przykładowo, mamy konto pocztowe zbieram_spam@kolekcja.mejor.pl , w programie pocztowym konfigurujemy w połączenie do serwera SMTP użytkownika zbieram_spam@kolekcja.mejor.pl , natomiast w ustawieniach konta możemy wprowadzić: prezes_firmy@kolekcja.mejor.pl . Czyli w mailu pojawi nam się From:  prezes_firmy@kolekcja.mejor.pl pomimo tego, że nie mamy prawa korzystać z tego konta.

Musimy więc porównać, czy sender, czyli nadawca jest taki sam jak użytkownik, który odmeldował nam się loginem i hasłem. Zatem w acl_check_data (czyli tak naprawdę w acl_smtp_data) , gdzieś blisko początku, dodajemy:

deny     authenticated  = *
condition      = ${if eq {$authenticated_id}{${lc:$sender_address}}{no}{yes}}
message         = rejected: Nie
prawidłowy nadawca.

Tutaj pojawił mi się mały dylemat, pisząc poprzednie teksty, przyjąłem odruchowo, że alias do konta jest aliasem służącym tylko do odbierania poczty. Pisząc obrazowo, jest konto zbieram_spam@kolekcja.mejor.pl do którego zakładamy aliasy: uwielbiam_ICIC@kolekcja.mejor.pl oraz icic_to_miedzynarodowi_spamerzy@kolekcja.mejor.pl

to mail przychodzący pod dowolny w/w adres wyląduję w jednym i tym samym maildirze. Natomiast pocztę można wysyłać jedynie jako zbieram_spam@kolekcja.mejor.pl . Natomiast Adrian zasugerował, że zbieracz_spamu mógłby także chcieć wysłać maila jako icic_to_miedzynarodowi_spamerzy@kolekcja.mejor.pl . A tego powyższy wpis nie dopuszcza.

Jak to zrobić jest w drugiej części.

Jak odrzucić maila i zostawić sobie jednocześnie jego kopię

Ten post będzie o tym jak zapewnić większą ilość raportów wysyłanych przez SpamCopa do abuse@…

Zwykle (czyli tak jak np. ja miałem ;) ) serwer pocztowy jest tak skonfigurowany, że w momencie uznania iż dany mail jest spamem wysyła komunikat 550 i kończy sesję. Może to się stać zarówno podczas testów samego nagłowka, czyli zwykle jest to sprawdzenie poprawności syntaktycznej nagłówka i przede wszystkim odpytanie RBL, jak i po odebraniu całego maila, wtedy system wykrywający spam ( np. Spamassassin ) analizuje jego treść i oznacza go jako ham/spam.

Tak czy inaczej mail taki zostaje odrzucony, my wiemy, że była próba zaproponowania nam viagry ale nie mamy corpus delicti do zaraportowania.

Uważam, że jeśli nadawca siedzi już w RBLu to są dwa powody aby zakończyć konwersację natychmiast, bez przyjmowania całości maila. Pierwszy powód to taki, że skoro jest już na czarnej liście to znaczy, że został już zgłoszony odpowiednią ilość razy. Drugim jest fakt, że po to korzystam z czarnych list aby zmniejszyć obciążenie łącza jak i samego serwera, ciężkim SpamAssasinem. Czyli wybór prosty, jeżeli mail zostanie odrzucony poprzez antyspama to wtedy chciałbym mieć jego kopię do zaraportowania.

Do zaimplementowania tej funkcji w Eximie wykorzystałem fakereject .

Plan działania jest taki: oznaczam takiego maila zmienną, dodaje nowy router, przed routerem, który normalnie doręczył by maila do maildira. W nim sprawdzam stan zmiennej oznaczającej czy dany mail jest spamem czy nie. Jeśli wynik testu jest pozytywny to kieruje przesyłkę do oddzielnego transportu.

O to szczegóły, kolorem czerwonym oznaczam dodatkowe wpisy obok standardowo występujących.

acl_check_data:

……

deny warn message           = This message scored $spam_score spam points.

spam                  = nobody:true
condition         = ${if >{$spam_score_int}{44}{1}{0}}
set acl_m1        = spam
control              = fakereject/This message scored $spam_score spam points.SC.

begin routers

dnslookup:

………

spam_fakereject:

driver = accept
condition = ${if eq {$acl_m1}{spam}{true}{false}}
transport = spam_transport

……..

begin transports

spam_transport:

driver = appendfile
directory = /home/spam
maildir_format
delivery_date_add
envelope_to_add

To zapewni nam, że w katalogu /home/spam wyląduje wszystko ze zbyt wysoką punktacją. Teraż możemy sobie poczytać wszelkie oferty ;) oraz zgłosić je komu trzeba.

Jeżeli chcemy automagicznie, bez czytania, wysłać zgłoszenie do SpamCopa to możemy to zrobić poprzez modyfikację transportu tak aby wołaj od razu spamassassina (za pomocą którego będziemy wysyłać raport).

Skorzystamy z drivera pipe

spam_transport:

driver = pipe
command = /usr/bin/spamassassin -r

Potrzebujemy także uaktywnić wymagany plugin w Spamassassinie.

W pliku v310.pre dodajemy:

loadplugin Mail::SpamAssassin::Plugin::SpamCop

a w pliku local.cf podajemy adres do submitowania przypisany do naszego konta na SC:

spamcop_to_address      submit……@…..

Voila.


Exim i aliasy z bazy postgresowej

Aliasy trzymam w bardzo prostej tabelce:

CREATE TABLE aliasy
(
id serial NOT NULL,
alias text NOT NULL DEFAULT ”::text,
destination text NOT NULL DEFAULT ”::text,
CONSTRAINT aliasy_pkey PRIMARY KEY (id)
);

CREATE UNIQUE INDEX ind_alias
ON aliasy
USING btree
(alias);

CREATE TRIGGER cleanup_aliases
BEFORE INSERT OR UPDATE
ON aliasy
FOR EACH ROW
EXECUTE PROCEDURE cleanup_aliases();

CREATE OR REPLACE FUNCTION cleanup_aliases()
RETURNS „trigger” AS
$BODY$
DECLARE
BEGIN
NEW.alias := trim(both FROM lower(NEW.alias));
NEW.destination := trim(both FROM lower(NEW.destination));
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql’ VOLATILE;

Do tego jest trigger mający na celu zapisać w bazie dane małymi literami z obciętymi spacjami na początku oraz końcu. Ten trigger jest zapożyczony z blogu depesza.

Sam ruter w eximie wygląda następująco:

aliasy_postgres:
driver = redirect
allow_fail
allow_defer
data = ${lookup pgsql{ SELECT destination FROM aliasy where alias = (’${quote_pgsql:$local_part}@${quote_pgsql:$domain}’) }}

Exim + postgresql

Nadeszła chwila, kiedy to unixowe konta nie wystarczają do obsługi poczty. Witajcie wirtualni userzy.

Dlaczego postgres? Ponieważ bardzo nie lubię mysqla.

Podczas migracji korzystałem z różnych opisów dostępnych w sieci, wiele informacji (oraz trigerów :)  ) zaczerpnąłem ze strony depesza oraz ze strony Baseciqa . Okazało się jednak, że w powyższych opisach,  oraz w wielu innych jakie google podsuwały, brakowało kilku kluczowych elementów aby exim działał tak jak powinien działać serwer pocztowy. Tym „drobiazgiem” była przede wszystkim nieomówiona autoryzacja użytkowników wysyłających pocztę. Silnie podpierając się stroną ( http://devel.reinikainen.net/attachments/Exim/configure ) uruchomiłem możliwość wysyłania poczty wirtualnym użytkownikom.

Uff, następuje pierwsza próba wysłania maila. I zonk. Okazuje się, że exim dokleja swój primary hostname do adresu mailowego nadawcy. Czyli miałem nadawce takiego:

„user@wirtualna.domena.tld@moj.komputer.tld”

Tutaj wszystko zamykało się w jednej linijce:

control       = submission/sender_retain

Kolejna próba.. I? Pełny sukces! Zadziałało!

Kolejnym etapem będzie uruchomienie aliasów.