Wprowadzenie do procmaila

Transkrypt

Wprowadzenie do procmaila
Wprowadzenie do procmaila
Łukasz Komsta
31 grudnia 2002 roku
Spis treści
1 Wstęp
3
2 Zagadnienia ogólne
2.1 Przydatne makra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Backup poczty i logowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 Najprostsze przykłady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
4
4
5
3 Użycie formaila
3.1 Wyławianie tematu wiadomości . . . . . . . . . . . . . . .
3.2 Obcinanie dłuższych wiadomości . . . . . . . . . . . . . .
3.3 Użycie formaila jako testera . . . . . . . . . . . . . . . . .
3.4 Czarna lista serwerów . . . . . . . . . . . . . . . . . . . .
3.5 Czarna lista nadawców . . . . . . . . . . . . . . . . . . . .
3.6 Naprawianie pola „From:” . . . . . . . . . . . . . . . . . .
3.7 Dzielenie przeglądów (digests) . . . . . . . . . . . . . . . .
3.8 Autoresponder . . . . . . . . . . . . . . . . . . . . . . . .
3.9 Eliminacja duplikatów wiadomości . . . . . . . . . . . . .
3.10 Forwardowanie pomiędzy kontami . . . . . . . . . . . . .
3.11 Automatyczne dekodowanie „quoted-printable” i „base64”
3.12 Likwidacja listy adresów w „To:” . . . . . . . . . . . . . .
3.13 Uzupełnianie nagłówka wiadomości z PGP . . . . . . . . .
3.14 Prosty system antywirusowy . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8
8
8
8
9
9
9
10
10
10
11
11
11
12
12
4 Scoring
4.1 Identyfikacja koreańskiego spamu . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 Szczegółowy opis działania scoringu . . . . . . . . . . . . . . . . . . . . . . . . . .
13
14
14
5 Kruczki i sztuczki
5.1 Drukowanie wiadomości postscript . . .
5.2 Ekstrakcja pola „Reply-To:” . . . . . . .
5.3 Wyławianie adresu postmastera . . . . .
5.4 Warunek na równość zmiennych . . . . .
5.5 Identyfikacja kodu HTML w wiadomości
14
14
15
15
15
15
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Łukasz Komsta
5.6
5.7
5.8
5.9
5.10
Wprowadzenie do procmaila
Ekstrakcja identyfikatora „multipart boundary”
Porównywanie adresu nadawcy z docelowym . .
Forward tylko w określonych godzinach . . . .
Whitelist z możliwością dopisywania . . . . . .
Odbijanie poczty . . . . . . . . . . . . . . . . .
6 Zakończenie
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
16
16
16
18
18
Warunki dystrybucji
Kopiowanie w formie elektronicznej dozwolone wyłącznie w postaci niezmienionej, z zachowaniem
informacji o autorze oraz warunkach dystrybucji, tylko w celach niekomercyjnych. Przedruk, sprzedaż i inne formy wykorzystania dozwolone wyłącznie za zgodą autora.
Zmiany
• 2002.12.31 - 0.11 - poprawiono kilka literówek, wprowadzono poprawki merytoryczne.
Ogromne podziękowania za recenzję i korektę tekstu składam Dariuszowi Sznajderowi.
• 2002.12.30 - 0.10 - pierwsza wersja dokumentu.
Aktualna wersja dokumentu: 0.11
Strona domowa autora: http://www.komsta.net.
Opracowanie złożono w systemie TEX/LATEX.
2
Łukasz Komsta
Wprowadzenie do procmaila
1. Wstęp
Procmail jest programem pocztowym typu TA (Transfer Agent), przetwarzającym pocztę po stronie serwera. Stanowi część składową większości systemów typu Unix.
Choć jest to program niemłody, niewielu użytkowników potrafi wykorzystać jego możliwości.
Niniejszy tekst ma pomóc czytelnikowi w przezwyciężeniu początkowych trudności w obsłudze.
Na samym początku pracy należy upewnić się, czy MTA (sendmail, qmail) na serwerze wywołuje procmaila jako domyślnego dostawcę poczty. Tak jest najczęściej. Czasem niektórzy administratorzy ustawiają MTA na dostarczanie poczty wyłącznie do domyślnego Mailbox-u lub Maildir-a.
W przypadku MTA obsługujących pliki .forward, wstawiamy do tego pliku
"|IFS=’ ’&&exec /usr/local/bin/procmail -f-||exit 75 #NAZWAKONTA"
Natomiast użytkownicy qmaila powinni w plikach .qmail i .qmail-default (w katalogu domowym) umieścić linię:
| preline procmail
Po takiej modyfikacji trzeba przystąpić do edycji pliku .procmailrc1 .
Aby przetworzyć plik z pocztą (w formacie mailbox) przez procmaila, możliwe jest użycie
następującego tricku:
formail -s procmail < mailboxfile
2. Zagadnienia ogólne
Plik .procmailrc składa się z deklaracji zmiennych oraz jednej lub wielu reguł przetwarzania
poczty. Reguły mogą być zagnieżdżane poprzez ujmowanie w nawiasy klamrowe. Każda reguła
(recipe) składa się z:
• dwukropka, zera, flag oznaczających tryb jej przetwarzania, oraz opcjonalnie nazwy pliku
blokady (lockfile)
• jednej lub więcej linii z warunkami (zaczynają się od gwiazdki; wszystkie muszą być spełnione)
• jednej linii definiującej postępowanie z pocztą w razie spełnienia warunków. Linia ta może
zawierać nazwę pliku, do którego będzie ona składowana, katalogu (składowanie w formacie
maildir), jak również polecenia, do którego ma być przekazana treść wiadomości (znak |).
Można również forwardować pocztę przez umieszczenie wykrzyknika i adresów docelowych
oddzielonych przecinkami.
Do sprawnego stosowania procmaila warto poznać, chociażby w minimalnym stopniu, zasady
tworzenia wyrażeń regularnych (man regexp). Na nich opierają się linie reguł sortowania. Jeśli
podaje się kilka warunków, a wystarczy spełnienie tylko jednego, trzeba to zrobić w formie jednego
warunku, będącego złożonym wyrażeniem regularnym2 .
1 Gorąco zaleca się utworzenie tego pliku i jawną deklarację reguły domyślnego dostarczania poczty. Inaczej może
się okazać, że domyślne reguły ustawione przez administratora daleko odbiegają od naszych oczekiwań, lub też
poczta trafia w przysłowiową próżnię.
2 Np. oddzielić warunki składowe znakiem | (fajki).
3
Łukasz Komsta
Wprowadzenie do procmaila
2.1. Przydatne makra
Linie reguł składają się z gwiazdki, spacji i odpowiedniego wyrażenia regularnego. Składnia procmaila przewiduje kilka przydatnych makr, zamienianych na skomplikowane reguły. Są to:
• ^TO - jest rozwijane na
(^((Original-)?(Resent-)?(To|Cc|Bcc)|(X-Envelope|Apparently
(-Resent)?)-To):(.*[^a-zA-Z])?),
co pozwala wyłapać np. siebie jako adresata wiadomości
• ^FROM DAEMON - jest rozwijane na
(^(Precedence:.\*(junk|bulk|list)|
(((Resent-)?(From|Sender)|X-Envelope-From):|>?From)
(.*[^(.\%@a-z0-9])?(Post(ma?(st(e?r)?|n)|office)|(send)
?Mail(er)?|daemon|mmdf|root|n?uucp|smtp|response|LISTSERV|
owner|request|bounce|serv(ices?|er)|Admin(istrator)?)
([^).!:a-z0-9].*)?$[^>])),
co zapewnia wyłapanie wszystkich listów od demonów, list dyskusyjnych, jak również zwrotów i meldunków o innych błędach.
• ^FROM MAILER - jest rozwijane na
(^(((Resent-)?(From|Sender)|X-Envelope-From):|>?From
)(.*[^(.\%@a-z0-9])?(Post(ma(st(er)?|n)|office)|
(send)?Mail(er)?|daemon|mmdf|root|n?uucp|smtp
|response|serv(ices?|er)|Admin(istrator)?)
([^).!:a-z0-9].*)?$[^>]),
co zapewnia wyłapanie poczty od mailerów (zwroty), ale nie zahaczy już o listy dyskusyjne.
2.2. Backup poczty i logowanie
Na samym początku eksperymentów możemy obawiać się, że poprzez stworzenie niewłaściwego
pliku możemy zagubić lub uszkodzić przychodzącą pocztę. W takiej sytuacji warto na samym
początku pliku ustawiać regułkę
:0 c
backup
Spowoduje ona dodatkowe składowanie całej poczty (przed jakimkolwiek dalszym przetwarzeniem) w pliku backup. Można również od razu kompresować wiadomości, poprzez „karmienie” nimi
programu gzip:
:0 cw:
| gzip -9 >> backup
4
Łukasz Komsta
Wprowadzenie do procmaila
W powyższym przykładzie flaga w nakazuje oczekiwanie na zakończenie wykonywanego programu, po czym bada kod powrotu. Jeśli program wykonał się bez błędów, regułka uznawana jest za
wykonaną.
Drugi dwukropek (po literze w) nakazuje stworzenie pliku blokady (lockfile). Zabezpiecza to
przed jednoczesnym uruchomieniem programu przez kilka procesów procmaila (przy nadejściu
większej ilości wiadomości naraz).
Inną metodą kontroli zachowania procmaila jest logging. Aby go uaktywnić, na początku pliku
piszemy np.
LOGFILE=/home/user/log
ABSTRACT=no
VERBOSE=no
Zmienna LOGFILE zawiera lokalizację pliku, w którym procmail zapisuje wykonane przez siebie operacje. Ustawienie zmiennej VERBOSE na wartość yes powoduje generowanie szczegółowych
raportów, zaś zmienna ABSTRACT odpowiada w analogiczny sposób za generowanie „streszczenia”
każdej przetwarzanej wiadomości.
2.3. Najprostsze przykłady
Prosty plik .procmailrc może wyglądać tak:
:0:
* ^TOlinux
linux-list
:0
* ^FROM_DAEMON
Mailbox
:0
! [email protected]
Powoduje on składowanie listów mających w adresie odbiorcy ciąg linux (np. lista dyskusyjna)
do pliku linux-list, a pozostałych list dyskusyjnych i zwrotów w pliku Mailbox. Wszystkie
pozostałe listy są forwardowane na [email protected].
Załóżmy, że chcemy filtrować listy od luckyluke, zawierające w temacie słowo tajne. Mają
one być składowane w oddzielnym pliku. Najprościej osiągnąć to w taki sposób:
:0 c
* ^From.*luckyluke
* ^Subject:.*tajne
! inny@adres
:0
* ^From.*luckyluke
* ^Subject:.*tajne
tajnyplik
Od razu zwracają uwagę 2 regułki z tym samym warunkiem. Pierwsza forwarduje kopię wiadomości (flaga c) na nowy adres, druga zaś składuje wiadomość w pliku. Deklaracja kopii wiadomości
5
Łukasz Komsta
Wprowadzenie do procmaila
(właśnie przez flagę c) jest tu bardzo ważna. W razie jej nieobecności procmail przetwarzałby tylko
pierwszą regułę i nie składowałby już poczty w tajnyplik. Aby ten cel osiągnąć, nie trzeba się
powtarzać; wystarczy zastosować zagnieżdżenie reguł w nawiasach klamrowych. Procmail traktuje
wtedy wszystko, co jest wzięte w klamrę, jako jedną linijkę do wykonania:
:0
* ^From.*luckyluke
* ^Subject:.*tajne
{
:0 c
! inny@adres
:0
tajnyplik
}
Istnieje także flaga A, która nakazuje wykonać regułę dostarczenia tylko w razie spełnienia poprzedniego warunku. Jeśli zastosujemy a (małe), konieczne będzie dodatkowo pomyślne wykonanie
poprzedniej reguły dostarczenia. Konstrukcje te są stosunkowo rzadko stosowane. Analogiczny plik
wyglądałby tak:
:0 c
* ^From.*luckyluke
* ^Subject:.*tajne
! inny@adres
:0 a
tajnyplik
Bardzo pożyteczną opcją jest reagowanie na rozmiar wiadomości. Np. poniższa regułka:
:0 c
* < 10000
! inny@adres
spowoduje przekazanie kopii wiadomości na inny adres tylko w przypadku listów krótszych od
10000 bajtów.
A teraz przykładowy plik sortujący pocztę root’a.
6
Łukasz Komsta
Wprowadzenie do procmaila
:0 c
* !^FROM_DAEMON
{
:0 c
/home/backup/rootmail
:0 c
! admin1
:0 c
! admin2
:0 fhw
| cat - ; \ echo "-WIADOMOSC FORWARDOWANA-"
:0
! [email protected], [email protected]
}
:0
Mailbox
Wspomniano już wcześniej, że flaga c oznacza utworzenie kopii wiadomości. W przeciwnym
przypadku filtrowanie zatrzymałoby się na pierwszej pasującej regule. Na samym początku sprawdzane jest, czy poczta nie pochodzi od jakiegoś demona (wykrzyknik oznacza negację reguły). Jeśli
nie, składowana jest w pliku /home/backup/rootmail, forwardowana na konta admin1, admin2
i do dwóch innych administratorów. Przed forwardowaniem poza serwer dopisywany jest do tej wiadomosci napis ”WIADOMOSC FORWARDOWANA” (flagi fh opisane będą dalej [3]). Niezależnie
od wszystkiego, każda przesyłka trafi do pliku Mailbox w katalogu domowym.
Jeszcze jeden nieco egzotyczny przykład. Przypuśćmy, iż poczta ze słowem ”tajne” ma być
składowana w pliku tajne, w folderze o nazwie takiej, jak bieżący miesiąc i rok. Dodatkowo każdy
taki folder musi zostać utworzony, jeśli nie istnieje. Można to osiągnąć na dwa sposoby:
FOLDER=‘date +%y-%m‘
:0 ic
* ? test ! -d $FOLDER
| mkdir $FOLDER
:0:
* tajne
${FOLDER}/tajne
...lub:
FOLDER=‘date +%y-%m‘
DUMMY=‘test -d $FOLDER || mkdir $FOLDER‘
:0:
* tajne
${FOLDER}/tajne
7
Łukasz Komsta
Wprowadzenie do procmaila
3. Użycie formaila
Formail jest standardowym narzędziem służącym do szeroko rozumianego przetwarzania wiadomości. Pełna dokumentacja zawarta jest w podręczniku man do tego programu. Poniżej zostanie
zaprezentowanych kilka przykładów regułek używających formaila.
3.1. Wyławianie tematu wiadomości
Najprostszym przykładem jest uzyskanie na początku pliku w zmiennej SUBJECT tematu wiadomości. Taki temat może być analizowany i wykorzystywany w wywoływanych poleceniach zewnętrznych. Na przykład można coś do niego dopisać na początku, jak zaprezentowano poniżej:
SUBJECT=‘formail -xSubject: \ | sed -e ’s/[;\‘\\]/ /g’ \ | expand
| sed -e ’s/^[ ]*//g’ -e ’s/[ ]*$//g’‘
* ^From.*luke
{
:0fwh
| formail -I"Subject: WhateverYouAdd_ ${SUBJECT}"
:0:
pliknatakielisty
}
3.2. Obcinanie dłuższych wiadomości
Innym przykładem (choć nie bezpośrednim) jest obcinanie wiadomości dłuższych niż podana wartość:
:0
* > 4000
{ :0 fwh
* ^Content-Length:
| formail -IContent-Length:
:0: Maillock
| head -100 >> truncated
}
Każda wiadomość dłuższa niż 4000 bajtów jest obcinana do 100 pierwszych linijek i dopisywana
do pliku truncated. Wcześniej jednak wywoływany jest formail, który zamienia w wiadomości pole
Content-Length na Old-Content-Length.3 .
Flaga h oznacza przesyłanie do formaila jedynie nagłówka, zaś f mówi, iż program zewnętrzny
ma być traktowany jako filtr, tzn. wiadomość musi być przez niego „przepuszczona”.
3.3. Użycie formaila jako testera
Formail może być również użyty jako tester wiadomości. Jeśli warunek zaczyna się od znaku zapytania, dalsza część nie jest traktowana jako wyrażenie regularne, lecz jako program do wykonania4 .
3 Eliminuje
to niebezpieczeństwo nieprawidłowego odczytywania takiej wiadomości przez programy pocztowe
korzystające „na siłę” z tego pola do uzyskania rozmiaru pojedynczej przesyłki.
4 Wykonanie reguły zależy oczywiście od kodu powrotu wywoływanego polecenia.
8
Łukasz Komsta
Wprowadzenie do procmaila
Popatrzmy:
:0
* ? formail -x"Received:"\
| egrep -i "cyberspam\.com"
/dev/null
W powyższym przykładzie nagłówki Received są testowane na obecność ciągu „cyberspam.com”.
Można w ten sposób łatwo wyłapać wiadomości przechodzące przez określone serwery. Backslash
przed kropką mówi o tym, iż jest ona znakiem kropki, a nie dowolnym znakiem5 . W tym konkretnym przypadku poczta taka jest kierowana do /dev/null, czyli kasowana.
3.4. Czarna lista serwerów
Jeśli posiadamy czarną listę serwerów, przez którą przechodzi spam, można zastosować następującą
regułkę:
:0
* ? formail -x"Received:" | egrep -is -f blacklist
spam
Regułka testuje pola Received w nagłówku wiadomości na obecność ciągów zawartych w pliku
blacklist6 oraz kieruje podejrzane listy do pliku spam.
3.5. Czarna lista nadawców
Analogicznie do poprzedniego przykładu można prowadzić czarną listę nadawców następującą regułką:
:0
* ? formail -x"From" -x"From:" -x"Sender:" \
-x"Reply-To:" -x"Return-Path:" -x"To:" \
| egrep -is -f blacklist
spam
3.6. Naprawianie pola „From:”
Formail może być np. użyty do naprawiania pola From7 :
:0 fhw
| formail -I "From " -a "From "
5 Jest
to w pełni zgodne ze składnią wyrażeń regularnych.
ten zawiera w kolejnych liniach wzorce, czyli fragmenty adresu e-mail.
7 Opcja ta jest przydatna tylko wtedy, gdy system pocztowy nie dodaje na początku każdej wiadomości linii
„From”. Dzieje się to obecnie bardzo rzadko, warto jednak zaprezentować to zastosowanie jako przykład elastyczności
procmaila.
6 Plik
9
Łukasz Komsta
Wprowadzenie do procmaila
3.7. Dzielenie przeglądów (digests)
Formailem można również dokonać automatycznego dzielenia przeglądów (digests) na pojedyncze
wiadomości przed składowaniem ich w pliku:
:0:
* ^Subject:.*igest
| formail +1 -ds >> digests
Trzeba tutaj zwrócić uwagę na obecność dwukropka (plik blokady).
3.8. Autoresponder
Najbardziej „książkowym” przykładem użycia formaila jest automatyczna generacja odpowiedzi na
mail. Zastosowania tego są przeróżne. Może to być informowanie naszych korespondentów o tym,
że jesteśmy na wakacjach, czy zmieniliśmy adres.
Prezentowany przykład zawiera dwie regułki. Pierwsza „prowadzi” spis nadawców, którzy już
mają taką odpowiedź. Jeśli w pliku cache nie ma jeszcze danego nadawcy, wykonywana jest druga
regułka, generująca mail zwrotny. Poczta jest wtedy niezależnie dostarczana dalej. W tej regule bardzo ważna jest deklaracja !^FROM DAEMON. Bez niej procmail odpowiadałby na wszystkie
listy, nawet z list dyskusyjnych, co spowodowałoby spory bałagan. Odrzucane są również listy zawierające pole X-Loop z naszym adresem. W przeciwnym razie wysłanie listu do samego siebie
spowodowałoby nieskończoną pętlę wysyłania odpowiedzi. Flaga e w drugiej regułce powoduje,
iż jest ona wykonywana tylko w przypadku niepowodzenia pierwszej (tu: nie znalezienia adresata
w cache).
:0 Whc: vacation.lock
* !^FROM_DAEMON
* !^X-Loop: nasz@adres
| formail -rD 8192 vacation.cache
:0 ehc
| (formail -rA"Precedence: junk" \ -A"X-Loop: nasz@adres" ; \
echo "Odebralem wiadomosc"; \
echo "ale odpowiem dopiero po niedzieli."; \
echo "-- "; cat $HOME/.signature \ ) | $SENDMAIL -oi -t
3.9. Eliminacja duplikatów wiadomości
Jeśli jesteśmy zapisani na kilka list dyskusyjnych i nadawcy wysyłają na nie ten sam list, będziemy
dostawać kilkakrotnie tą samą wiadomość. Można temu zapobiec następująco:
:0 Wh: msgid.lock
| formail -D 8192 msgid.cache
W tym przypadku w pliku msgid.cache prowadzona jest lista msgid-ów wiadomości, a żaden
duplikat nie przejdzie poza tę regułę do dalszego przetwarzania.
10
Łukasz Komsta
Wprowadzenie do procmaila
3.10. Forwardowanie pomiędzy kontami
Przypuśćmy, iż posiadamy dwa konta i chcemy forwardować wiadomości pomiędzy nimi. Typowa
technika doprowadziłaby do powstania nieskończonej pętli. Tymczasem wystarczy na obu kontach
ustawić następujące (podobne do poprzedniej) regułki:
:0 c
* !^X-Loop: moj@adres
| formail -A "X-Loop: moj@adres" | \
$SENDMAIL -oi drugie@konto
3.11. Automatyczne dekodowanie „quoted-printable” i „base64”
Połączenie programu formail z programem mimencode 8 pozwala na łatwe przekodowywanie dochodzących wiadomości w standardzie quoted-printable lub base64 na format ośmiobitowy:
:0
* ^Content-Type: *text/plain
{
:0 fbw
* ^Content-Transfer-Encoding: *quoted-printable
| mimencode -u -q
:0 Afhw
| formail -I "Content-Transfer-Encoding: 8bit"
:0 fbw
* ^Content-Transfer-Encoding: *base64
| mimencode -u -b
:0 Afhw
| formail -I "Content-Transfer-Encoding: 8bit"
}
3.12. Likwidacja listy adresów w „To:”
Niekiedy jesteśmy zapisani na tragicznie skonfigurowaną listę dyskusyjną, której listy zawierają
wszystkich odbiorców w polu To, zaś same listy przychodzą w tekście i HTML-u. Wtedy wystarczy
następująca regułka, likwidująca listę adresów i załącznik HTML:
8 Program
ten nie zawsze jest w systemie, przed tworzeniem regułek należy sprawdzić jego obecność.
11
Łukasz Komsta
Wprowadzenie do procmaila
:0 fwh
| formail -z -i"Content-Length:"
:0
* From:.*adminlisty
* ^TO_pierwszyodbiorca
{ :0 fw
| formail -I"To:" -I"X-" -I"Content-Type:" \
-I"MIME-Version:" -A "To: Dluuuga lista odbiorcow" \
| sed -e ’/^This is a~multi-part \
/,/^Content-Transfer-Encoding: /d’ \ -e \
’/------=_NextPart_/,$d’
:0:
${DEFAULT}
}
3.13. Uzupełnianie nagłówka wiadomości z PGP
Poniższy przykład powoduje dodanie stosownego pola (tzw. PGP MIME Headerdo nagłówka wiadomości szyfrowanych lub sygnowanych PGP, celem ich automatycznej obróbki przez program
mutt, plugin PGP Outlooka, czy rozszerzenia Mozilli, takie jak Enigmail:
:0 fBw
* ^-----BEGIN PGP MESSAGE----* !Content-type: multipart
| formail \
-i "Content-Type: application/pgp; format=text; x-action=encryptsign"
:0 fBw
* ^-----BEGIN PGP SIGNED MESSAGE----* !Content-type: multipart
| formail \
-i "Content-Type: application/pgp; format=text; x-action=sign"
3.14. Prosty system antywirusowy
Na zakończenie przykład prostego systemu antywirusowego:
12
Łukasz Komsta
Wprowadzenie do procmaila
SUBJECT=‘formail -xSubject: \ | sed -e ’s/[;\‘\\]/ /g’ \ | expand \
| sed -e ’s/^[ ]*//g’ -e ’s/[ ]*$//g’‘
:0 Bw
* !^X-Loop: (identyfikator)
* !^From:.*postmaster
* ABC1234567890DEF
{
:0 c
| (formail -rtb \
-i"From: Skaner wirusowy serwer.pl <[email protected]>" \
-A"X-Loop: (identyfikator)" \
-A"Precedence: junk" ; cat /usr/share/virfrom) | \
sed -e "s/To: _/To: /g" | sendmail -oi -t
:0 fBw
| (formail -i \
"Content-Type: text/plain" \
-i "Subject: [Przeczytaj dopisek na dole] $SUBJECT" ; \
cat /usr/share/virto)
}
Powyższy przykład jest obroną przed autentycznym wirusem, rozsyłającym załącznik o objętości ok. 40 KB i dodającym podkreślnik przed adresem nadawcy. Z założenia przeznaczony
jest do globalnego /etc/procmailrc. Na samym początku temat wiadomości umieszczany jest
w zmiennej SUBJECT. Jeśli wiadomość nie zawiera stosownego pola X-Loop, zaś zawiera ciąg
”ABC1234567890DEF” (boundary wirusa), podejmowane jest dwojakie działanie9 . Mail dostarczany jest do adresata, jednak zmieniane jest pole Content-Type na text/plain, dodawany jest
do tematu tekst „[Przeczytaj dopisek na dole]”, a na koniec wiadomości zawartość pliku
/usr/share/virto). W ten sposób zakażenie komputera adresata nie jest możliwe, jest on informowany o modyfikacji maila, ale mail jest nadal czytelny, w razie gdyby nie był to przypadkowo wirus. Tekst dołączany na końcu powinien zawierać informację, iż nadawca został poinformowany o wirusie, dzieje się to bowiem w pierwszej regułce. Wysyłana jest doń zawartość pliku
/usr/share/virfrom. Warto zwrócić uwagę na wywołanie sed-a, który w tym przypadku usuwa
podkreślnik z adresu docelowego.
4. Scoring
Procmail posiada wbudowany mechanizm scoringu. Oznacza to, iż każdy warunek w danej regułce może przynosić wiadomości określoną ilość „punktów”. Regułka spełniona jest tylko przy
przekroczeniu określonej ilości. Rozważmy następujący przykład:
:0:
* -1^0
* 1^0 ^Subject:.*money
* 1^0 ^Subject:.*fast
* 2^0 ^Subject:.*\$\$\$
spammail
9 Poprzez
dodanie kolejnych warunków zawierających charakterystyczne ciągi, system ten można rozbudowywać
o kolejne wirusy.
13
Łukasz Komsta
Wprowadzenie do procmaila
Początkowa liczba punktów ustawiana jest na -1. Następnie każdy z warunków przynosi jeden,
lub (ostatni) dwa punkty. Jeśli końcowy wynik większy jest niż 0, list wędruje do pliku spammail.
W powyższym przypadku wystarczą znaki dolara w temacie lub oba słowa ”money” i ”fast”.
4.1. Identyfikacja koreańskiego spamu
Doskonałym przykładem zastosowania scoringu jest identyfikacja e-maila z językiem koreańskim:
:0BD
* -1^1 .
* 2^1 =[0-9A-F][0-9A-F]
* 20^1 [################################]
* 20^1 [################################]
* 20^1 [################################]
* 20^1 =[89A-F][0-9A-F]
junkmail
Pierwsza linijka nakazuje odjąć 1 punkt dla każdego bajtu wiadomości. Następnie treść jest
przeszukiwana pod kątem występowania znaków ASCII o kodzie 160..255 (zamienione na # dla
celów wydruku). Każdy znak daje 20 punktów. Końcowy rezultat będzie większy od zera wtedy,
gdy co najmniej na 20 znaków ogólnych występuje jeden taki znak.
Na scoringu może być oparty również warunek dotyczący wielkości przesyłki i jest to wtedy jeszcze bardziej skompilowane (odsyłam do procmailsc(5)). Scoring ma zastosowanie głównie w filtrach
antyspamowych.
4.2. Szczegółowy opis działania scoringu
Jeśli przypiszemy do oznaczenia zmienne wˆx (w poprzednim pliku w = −1 a x = 1), pierwsze spełnienie danego warunku dodaje w punktów, następne wx, jeszcze następne wx2 itd. Jak
nietrudno wydedukować, rezultat będzie zależny od wartości x:
• jeśli x = 0, wartość doda się tylko przy pierwszym wystąpieniu
• jeśli 0 < x < 1, każde następne wystąpienie będzie owocowało mniejszą ilością punktów
(asymptotycznie)
• jeśli x < 1, zależność będzie wykładnicza
• jeśli x < 0, końcowa wartość będzie dodatnia lub ujemna w zależności od parzystości lub
nieparzystości wystąpień.
5. Kruczki i sztuczki
5.1. Drukowanie wiadomości postscript
Następująca regułka spowoduje wydrukowanie każdej nadchodzącej wiadomości, która jest plikiem
postscripowym:
:0 Bb
* ^^%!
| lpr
14
Łukasz Komsta
Wprowadzenie do procmaila
5.2. Ekstrakcja pola „Reply-To:”
Kolejna reguła pozwala na uzyskanie adresu z pola Reply-To (i tylko z tego):
REPLYTO_=‘egrep "^Reply-To:" | head -1 \ | formail -c -rt -xTo: \
| expand | sed -e ’s/^[ ]*//g’ -e ’s/[ ]*$//g’‘
5.3. Wyławianie adresu postmastera
Czasami chcemy automatycznie odpowiadać do postmastera domeny, z której przychodzi np. spam.
Jego adres można uzyskać w następujący sposób:
FROM_=‘formail -rt -xTo: \ | expand | sed -e ’s/^[ ]*//g’ \
-e ’s/[]*$//g’‘ FHOST_=‘echo "${FROM_}" | awk -F@ ’{ print $2 }’‘
FMAST_="postmaster@${FHOST_}"
5.4. Warunek na równość zmiennych
Jeśli w trakcie obróbki poczty chcemy sprawdzić, czy dwie zmienne są sobie równe, wystarczy:
:0:
* $ VAR1_ ?? ${VAR2_}
cokolwiek
5.5. Identyfikacja kodu HTML w wiadomości
Czasem poszukujemy w treści wiadomości znaczników HTML. Okazuje się wtedy, iż regułka
* </body>
* </html>
nie działa. Przyczyna jest prosta - procmail doszukuje się w niej testu na wielkość przesyłki
(znak mniejszości). Zamiast tego należy użyć składni, w której znak mniejszości nie będzie pierwszy,
np.
*
*
*
*
()</body>
(<)/body>
(</body>)
\</body>
5.6. Ekstrakcja identyfikatora „multipart boundary”
Jeśli chcemy wyekstrahować z nagłówka identyfikator wiadomości wieloczęściowej (multipart boundary) wystarczy:
15
Łukasz Komsta
Wprowadzenie do procmaila
BOUND1=‘formail -z -x"Content-Type:" \ | awk -F= ’{ print $2 }’ \
| sed -e ’s/\"//g’ | tr -d ’\n’‘
...lub:
:0h
* ^Content-Type:
{
BOUND2=‘egrep -i ’boundary=’ \
| awk -F= ’{ print $2 }’ | sed -e ’s/\"//g’‘
}
5.7. Porównywanie adresu nadawcy z docelowym
Jeśli chcemy sprawdzić, czy adres nadawcy i adresata jest taki sam
10
należy zastosować regułkę:
WHOFROM=‘formail -xFrom: \ | expand \ | sed -e ’s/ */ /g’ \
| sed -e ’s/^[ ]*//g’ -e ’s/[ ]*$//g’‘
WHOTO=‘formail -xTo: \ | expand \ | sed -e ’s/ */ /g’ \
| sed -e ’s/^[ ]*//g’ -e ’s/[ ]*$//g’‘
:0:
* $ WHOFROM ?? ${WHOTO}
spam
5.8. Forward tylko w określonych godzinach
Jeśli chcemy forwardować wiadomości tylko w określonych porach dnia, np. 9 — 17, można poradzić
sobie w ten sposób:
:0
{
:0
{
TIME=‘date +%H%M‘
ISGT=‘expr ${TIME} \> 0900‘
ISLT=‘expr ${TIME} \< 1700‘
}
:0
* ISGT ?? ^^1^^
* ISLT ?? ^^1^^
! [email protected]
}
5.9. Whitelist z możliwością dopisywania
Na zakończenie bardziej rozbudowany .procmailrc, spełniający założenia:
10 Sytuacja ta zdarzała się niegdyś bardzo często w przesyłkach typu spam, jednak ostatnio spotyka się to coraz
rzadziej.
16
Łukasz Komsta
Wprowadzenie do procmaila
• cała poczta docierającego użytkownika, pochodząca z list dyskusyjnych ma być forwardowana
na inne konto
• jeśli nie jest to wiadomość z listy dyskusyjnej, tylko list prywatny, sprawdzane jest, czy
nadawca znajduje się w specjalnym pliku
• jeśli tak, list jest też forwardowany na inne konto
• jeśli nie, autor otrzymuje automatyczną odpowiedź, że jego adres nie jest na liście, ale może
się na nią dopisać, podając w temacie listu słowo subscribe
• jeśli taki mail przyjdzie, autor jest dopisywany i otrzymuje zwrotne potwierdzenie
• należy nie dopuścić do tego, aby jedna osoba dopisywała się kilkakrotnie.
FROMMAIL=‘egrep "^From:" | head -1 \
| formail -c -rt -xTo: \
| expand | sed -e ’s/^[ ]*//g’ -e ’s/[ ]*$//g’‘
:0
* ^FROM_DAEMON
! inny@adres
:0
* ? formail -x"From" -x"From:" -x"Sender:" \
-x"Reply-To:" -x"Return-Path:" -x"To:" \
| egrep -is -f list
! inny@adres
:0 Whc: new.lock
* ^Subject:.*subscribe
* !^X-Loop: nasz@adres
| formail -rD 8192 trusted.cache
:0 eh
* !^FROM_DAEMON
| (echo $FROMMAIL >> list; formail -rkA"Precedence: junk" \
-A"X-Loop: nasz@adres" ; \
echo "Twoj adres zostal dopisany"; \
echo "na liste uprawnionych nadawcow - dziekuje."; \
echo "Mozesz ponownie wyslac poprzedni list."; \
echo " "; cat $HOME/.signature ) \
| $SENDMAIL -oi -t
:0 h
* !^FROM_DAEMON
| (formail -rkA"Precedence: junk" \
-A"X-Loop: nasz@adres" ; \
echo "Twoj adres nie jest na uprawnionej liscie"; \
echo "(ochrona przed spamerami)"; \
echo "Wyslij pusty list z wyrazem subscribe w tytule"; \
echo "aby uzyskac dostep"; \ echo " "; cat $HOME/.signature
| /usr/sbin/sendmail -oi -t
17
) \
Łukasz Komsta
Wprowadzenie do procmaila
5.10. Odbijanie poczty
W większości MTA11 istnieje możliwość odmowy przyjęcia przesyłki i wygenerowania zwrotu, poprzez ustawienie odpowiedniego kodu powrotu, np.
:
^(Subject.*Bounce this|From.*[email protected])
{
LOG="Stop mailbombing me!"
EXITCODE=69
HOST=done
}
6. Zakończenie
Procmail jest obecnie programem tak często instalowanym, że ustanowił swego rodzaju standard.
Pojawiło się wprawdzie kilka konkurencyjnych projektów, jednak nie są one w stanie ani trochę
zaszkodzić jego popularności. Dlatego też znajomość procmaila stanowi istotny element znajomości
Sieci.
Literatura
[1] Timo’s procmail tips and recipes, http://www.uwasa.fi/ ts/info/proctips.html
[2] Strony podręcznika (man) systemu procmail
[3] Komsta Ł., Procmail w przykładach. LinuxPlus 2002;59(3):20-5.
11 Na
pewno dzieje się tak w sendmailu, a nie dzieje w qmailu. Zachowanie poszczególnych MTA w zależności od
konkretnych kodów powrotu jest opisane w ich dokumentacji.
18