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