Saturday 30 December 2006

Centralny serwer logów MS Windows na PostgreSQL

© 2006-04-18 Bartłomiej Siębab ver. 2.1 Spis treści:

Wstęp Działanie aplikacji Skrypt SQL Uwagi do kodu Do pobrania

Wstęp

Głównym założeniem projektu była centralizacja logów zbieranych z różnych systemów MS Windows z dzienników evenlog oraz innych (za pośrednictwem protokołu syslog) w jednej darmowej bazie SQL. Z powodu wymagań co do wydajności bazy, objętości gromadzonych dzienników oraz faktu iż baza ma być darmowa, sql'owa i ma być bazą (a nie programem do wyświetlania tabelek takim jak "mójsql" ;-) a ponadto koniecznym "połączeniem" do bazy w postaci komponentu .NET 2.0 na placu boju pozostał PostgreSQL...

Początkowo założyłem, iż aplikacja zbierająca logi z maszyn MS Windows będzie rezydować na jednej z maszyn i zasysać dzienniki z pozostałych - wstawiając rekordy do bazy SQL. Tak też zostało to zrealizowane. W trakcie testowania okazało się że wąskim gardłem jest sam protokół zasysający dane z dzienników. Wydajność tegoż protokołu - jak sądzę bazującego na RPC - była żenująca - zaledwie 30-40 rekordów na sekundę dlatego też dorobiłem możliwość działania aplikacji na każdej maszynie z której pobierane są rekordy dzienników i wstawiania ich zdalnie do bazy PostgreSQL. Tutaj wydajność po zasosowaniu paczkowania rekordów w większej transakcji (po kilkaset insertów) oraz zastosowaniu "prepared statement" wzrosła do 300-400 rekordów/sek (baza stojąca na zwyczajnym, średniej wydajności pececie).

W dalszym etapie rozwoju aplikacji planowane jest dołożenie interfejsu wyszukiwawczo-raportującego pozwalającego na zautomatyzowanie wyszukiwania pewnych podejrzanych zdarzeń w logach, tworzenie syntetycznych i analitycznych raportów, backupowanie i kasowanie starych rekord ów z bazy, daemon/usługa syslogd (jako odrębny projekt pgsyslogd).

Całość napisałem zgodnie z obowiązującą "modą" w środowisku .NET 2005 (NetFramework 2.0). Jako że nie przepadam za pisaniem aplikacji w C# czy C++ na NET2005 postanowiłem z wrodzonego twórczego lenistwa i ku wygodzie własnej i ewentualnych użytkowników napisać całość w darmowym VisualBasic 2005 Express Edition przy użyciu komponentu Npgsql dla dostępu do bazy PostgreSQL.

Działanie aplikacji:

Aplikacja pgeventcollector może być uruchomiona na dwa sposoby. Pierwszy - zwykły tryb interakcyjny - dostępne menu, konfiguracja, podgląd postepu wczytywania logów itp. wodotryski. Drugi - tryb wsadowy z linii poleceń lub harmonogramu zadań - przydatny do kolejnych cyklicznych automatycznych importów logów do bazy.

Aplikacja pgsyslogd może byc uruchomiona jako usługa (nt service) systemowa nasłuchująca na porcie zgodnym z protokołem syslog i odbierająca dane przesyłane protokołem UDP w tym formacie (w planach także TCP).

Aplikacja rejestruje w rejestrze systemu ostatnia pozycje rekordu dziennika na którym zakończone zostało importowanie w poprzednim przebiegu. Wpisy pojawiają się po pierwszym wczytywaniu rekordów w gałęzi [HKLM]/Software/pgeventlogger/[nazwa maszyny]/...

Wymagania

W pierwszym etapie wdrożenia należało utworzyć odpowiednią bazę danych, tabelę na gromadzone logi, ewentualne indeksy przyśpieszające wyszukiwanie itp. Poniższy skrypt SQL utworzy nam bazę w kodowaniu UNICODE (utf-8), tabelę log i sekwencję autonumerowania. Ewentualne indeksy i użytkownika na którym będzie realizowane połączenie z bazą należy założyć sobie samemu. Instalacji i konfiguracji bazy PostgreSQL (na MS Windows lub na BSD/UNIX/Linux) nie będę tu opisywać - to przedstawia dokumentacja PostgreSQL. Ja zainstalowałem PostgreSQL w wersji 8.1.3 (taka wersja była najnowsza na moment wdrożenia). Do wykonania skryptu można zastosować interfejs zarządzania bazą PostgreSQL instalowany wraz z bazą (lub odrębnie) PgAdminIII. W celu zwiększenia bezpieczeństwa należało by utworzyć dedykowaną rolę (grupę), nadać prawa wstawiania rekordów w tabeli log dla tej roli + użycia sekwencji seqlogid; utworzyć dedykowanego użytkownika którym było by realizowane połączenie aplikacji z bazą a dziedziczącego uprawnienia po tej dedykowanej roli grupowej. Aplikacja wymaga aby dzienniki miały skonfigurowaną odpowiednią wielkość tak by mogły pomieścić wszystkie rekordy pomiędzy kolejnymi przebiegami importowania. Należy koniecznie zablokować resetowanie dzienników i nigdy ich nie resetować - nawet ręcznie, dzienniki powinny być ustawione w tryb automatycznego zastępowania najstarszych rekordów w razie potrzeby - stąd konieczne zaplanowanie ich odpowiedniego rozmiaru. Przy zresetowaniu dziennika następuje wyzerowanie wewnętrznej numeracji rekordów dzienników - ten właśnie numer rekordu jest wykorzystywany do zapamiętywania w rejestrze pozycji na której w poprzednim przebiegu aplikacja zakończyła import zatem wyzerowanie tej numeracji zablokuje importowanie logów - koniecznym będzie ręczne wyzerowanie liczników aplikacji w rejestrze.

Skrypt SQL

-- SET default_with_oids = false; -- Database: slog CREATE DATABASE slog WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default; -- Sequence: seqlogid CREATE SEQUENCE seqlogid; ALTER TABLE seqlogid OWNER TO postgres; -- Table: log CREATE TABLE log ( id int8 NOT NULL DEFAULT nextval('seqlogid'), -- id rekordu kto varchar(15) NOT NULL DEFAULT "current_user"(), -- kto zmodyfikowal rekord kiedy timestamptz NOT NULL DEFAULT now(), -- kiedy zmodyfikowano rekord eventlog varchar DEFAULT '', -- z jakiego dziennika pochodzi wpis entrytype varchar DEFAULT '', -- typ wpisu category varchar DEFAULT '', -- kategoria wpisu source varchar DEFAULT '', -- zrodlo wpisu eventid int4 DEFAULT 0, -- kod eventu machine varchar DEFAULT '', -- z jakiej maszyny username varchar DEFAULT '', -- jaki uzytkownik timegenerated timestamp DEFAULT now(), -- kiedy zaistnialo zdarzenie timewritten timestamp DEFAULT now(), -- kiedy zarejestrowano zdarzenie w dzienniku message text DEFAULT '', -- komunikat CONSTRAINT idlog_pk PRIMARY KEY (id) ) WITHOUT OIDS; ALTER TABLE log OWNER TO postgres; COMMENT ON TABLE log IS 'event log table'; COMMENT ON COLUMN log.id IS 'id rekordu'; COMMENT ON COLUMN log.kto IS 'kto zmodyfikowal rekord'; COMMENT ON COLUMN log.kiedy IS 'kiedy zmodyfikowano rekord'; COMMENT ON COLUMN log.eventlog IS 'z jakiego dziennika pochodzi wpis'; COMMENT ON COLUMN log.entrytype IS 'typ wpisu'; COMMENT ON COLUMN log.category IS 'kategoria wpisu'; COMMENT ON COLUMN log.source IS 'zrodlo wpisu'; COMMENT ON COLUMN log.eventid IS 'kod eventu'; COMMENT ON COLUMN log.machine IS 'z jakiej maszyny'; COMMENT ON COLUMN log.username IS 'jaki uzytkownik'; COMMENT ON COLUMN log.timegenerated IS 'kiedy zaistnialo zdarzenie'; COMMENT ON COLUMN log.timewritten IS 'kiedy zarejestrowano zdarzenie w dzienniku'; COMMENT ON COLUMN log.message IS 'komunikat'; -- Indexes: CREATE INDEX idxcategory ON log USING btree (category varchar_pattern_ops); CREATE INDEX idxentrytype ON log USING btree (entrytype varchar_pattern_ops); CREATE INDEX idxeventid ON log USING btree (eventid); CREATE INDEX idxeventlog ON log USING btree (eventlog varchar_pattern_ops); CREATE INDEX idxmachine ON log USING btree (machine varchar_pattern_ops); CREATE INDEX idxsource ON log USING btree (source varchar_pattern_ops); CREATE INDEX idxusername ON log USING btree (username varchar_pattern_ops); --

Instalacja

NetFramework 2.0

Standartowo aplikacje napisane w MS Visual Studio 2005 wymagają zainstalowania NetFramework 2.0. Do pobrania ze stron producenta lub z pakietu instalacyjnego MS Visual Studio 2005 Express.

Baza danych PostgreSQL

Standartowa instalacja PostgreSQL (u mnie wersja 8.1.3 tak na MS Windows jak i na *nix).

Instalacja aplikacji

Instalacja aplikacji jest prosta. Pierwsze ręczne uruchomienie powoduje zainstalowanie aplikacji i utworzenie odpowiednich pozycji w "Menu Start" systemu oraz automatyczne pierwsze uruchomienie aplikacji. W tym momencie należy wejść w menu "Tools->Options" i wprowadzić swoje odpowiednie parametry konfiguracyjne połaczenia z bazą. Po zatwierdzeniu konfiguracji możliwe jest uruchomienie interakcyjne lub tez w trybie wsadowym z liniii poleceń lub harmonogramu zadań. Aktualnie obsługiwany jest jedynie przełącznik "/start" wyzwalający natychmiastowy "produkcyjny" przebieg zaimportowania logów do bazy przy użyciu wcześniej ustawionej konfiguracji. Okienko konfiguracyjne domyślnie zawiera domyślny wpis postaci "." - odpowiednik "localhost" symbolizujący iż domyślnie importowane sa logi jedynie z bieżącej maszyny na której została uruchomiona aplikacja. Ewentualne kolejne maszyny należy podawać w kolejnych liniach w tradycyjnej postaci FQDN lub notacji adresu IP. Podczas wczytywania logów w trybie interakcyjnym aplikacja sygnalizuje paskiem postępu aktualny etap importowania, ponadto w lini statusu aplikacji mogą pojawiać się statusy typu "Idle" - bezczynna, "Running..." - importowanie rekordów, "Skipping..." - pomijanie rekordów wcześniej wczytanych i przeskoczenie do miejsca ostatniego zakończenia wczytywania.

Kod źródłowy i wersja binarna

Aplikacja dostępna jest jako spakowana paczka projektu Visual Basic 2005 a także jako skompilowana wykonywalna działająca wersja binarna z niezbędnymi bibliotekami Npgsql. Kod źródłowy szeroko komentowałem tak aby był łatwy do zrozumienia i ewentualnej rozbudowy lub dopasowania do własnych potrzeb. Od czasu do czasu będę publikował nowsze wersje źródeł i binariów - w miarę jak będa postępowac ewentualne dalsze prace rozwojowe. Licencja kodu aplikacji - standartowa nowa licencja BSD - inne komponenty moga mieć inną - proszę sobie sprawdzić własnoręcznie jaką (np. Npgsql czy MS Visual Studio 2005 Express).

Uwagi do kodu źródłowego

Aplikacja jest napisana "as is" - nie najgorzej ale i mogło być lepiej - jak będe miał chęci i czas to może popoprawiam conieco w wyglądzie tak kodu jak i samej aplikacji - narazie jak to mówią "feel free to do it yourself" ;-) Ręczna rekompilacja projektu wymaga "podpięcia" a właściwie wskazania lokalizacji komponentu Npgsql i biblioteki npgsql.dll oraz ewentualnego wygenerowania klucza tymczasowego do podpisania projektu. Spakowane binaria skompilowanej aplikacji już zawierają bibliotekę npgsql.dll.

Features

- tryb interakcyjny oraz wsadowy - pasek postępu wczytywania logów - zakładka z błedami i ostrzeżeniami - statystyki przetwarzania logów - rejestrowanie w dzienniku aplikacji statystyk z przetwarzania - predefiniowana modyfikowalna konfiguracja - statystyki ilości wpisów w dziennikach - możliwość zasysania logów z wielu maszyn - ...

ToDo

- dorobienie rejestrowania w eventlogu statystyki po każdym przetworzonym logu - dalsze modyfikacje okna konfuguracyjnego - wielojęzykowość aplikacji - wielowątkowość aplikacji - oblokowanie menu aplikacji przy pracy interakcyjnej - automatyczne rozpoznanie zresetowania logów - automatyczne cykliczne uruchamianie aplikacji wg wewnętrznego timera - dołożenie automatycznego utworzenia bazy i tabeli przy instalacji (na żądanie) - dołożenie współpracy z innymi bazami SQL - dołożenie modułu raportowania, wyszukiwania, analiz i statystyk - dokończenie i opublikowanie modułu pgsyslogd współpracującego z protokołem syslog - ...

Screenshoots

- okno główne aplikacji - okno konfiguracji aplikacji - postęp wczytywania w trybie interakcyjnym - wpisy liczników w rejestrze

Do pobrania

Spakowane kody źródłowe aplikacji w postaci projektu MS Visual Studio 2005 Express: - aktualna wersja źródeł z dnia 2006-04-18 to 1.0.1.2 Spakowana działająca wersja binarna palikacji: - aktualna wersja binarna z dnia 2006-04-18 to 1.0.1.2

Przydatne linki

- baza danych PostgreSQL http://www.postgresql.org - aktualna dokumentacja PostgreSQL http://www.postgresql.org/docs/manuals/ - MS Visual Studio 2005 Express http://msdn.microsoft.com/vstudio/express/default.aspx - MS NET Framework 2.0 http://msdn.microsoft.com/netframework/downloads/updates/default.aspx - komponent Npgsql http://npgsql.projects.postgresql.org/docs/manual/UserManual.htm - dokumentacja API komponentu Npgsql http://npgsql.projects.postgresql.org/docs/api/

Konfiguracja serwera pppoe we FreeBSD

© 2006-01-26 Bartłomiej Siębab ver. 1.1

Wstęp

W systemie FreeBSD instalacja serwera pppoe (ppp over ethernet) jest dość prosta i niezbyt skomplikowana o ile zawczasu przygotujemy sobie koncepcję działania naszego środowiska. Artykuł powstał na skutek inspiracji działającym rozwiązaniem projektu WARTA. Sama koncepcja działania projektu jest słuszna jednakże wiele rzeczy należało zmienić i dostosować do wymagań klienta. Opierając się na przemyśleniach jakie zostały opisane w projekcie WARTA postanowiłem zbudować własne środowisko odpowiednio poprawione i rozbudowane. Z powodu problemów z netgraph'em które pojawiły się przy próbie konfiguracji środowiska we FreeBSD 6.0 całość instalacji przeprowadzono na wersji FreeBSD 4.11. Poniższy opis należy traktować jako "work in progress" bowiem konfiguracja będzie wkrótce zmodyfikowana i przetestowana.

Wymagania

W pierwszym etapie wdrożenia założono iż nie będzie wykorzystywany serwer RADIUS jednakże dalsza rozbudowa środowiska nie wyklucza jego użycia w przyszłości. Każdy klient podłączający się do serwera powinien mieć zlimitowaną przepustowość (full duplex lub half duplex) zgodnie z wykupionym pasmem. Klienci muszą być odseparowani od siebie. Połączenie musi być autoryzowane protokołem MSChapV2 a sam transfer danych musi być szyfrowany.

Instalacja

Kernel

Przygotowanie kernela do kompilacji jest proste. Wystarczy skopiować kernel GENERIC na własną nazwę i uzupełnić o wymagane składniki, jednocześnie pozbywając się niepotrzebnych:

$>cd /sys/i386/conf $>cp GENERIC MYKERNEL

Usunięcie zbędnych rzeczy z kernela pozostawiam Twojemu rozsądkowi. To co dodatkowo powinno się znaleźć w kernelu przedstawia poniższy listing:

# IPDIVERT enables the divert IP sockets, used by ``ipfw divert'' options IPDIVERT #divert sockets # DUMMYNET enables the "dummynet" bandwidth limiter. You need # IPFIREWALL as well. See the dummynet(4) and ipfw(8) manpages for more info. # When you run DUMMYNET it is advisable to also have "options HZ=1000" options DUMMYNET options HZ=1000

options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #enable logging to syslogd(8) options IPFIREWALL_FORWARD #enable transparent proxy support options IPFIREWALL_VERBOSE_LIMIT=1000 #limit verbosity #options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default options IPFW2 #see ipfw(8) howto make ipfw2

Osobiście wolę kompilować kernel "starym" sposobem a zatem:

$>config -r MYKERNEL $>cd ../../compile/MYKERNEL $>make depend && make && make install $>shutdown -r now

Trzeba pamiętać że od tego momentu po restarcie maszyny zadziała firewall (w zależności od wpisów w /etc/rc.conf) co może skutkować odcięciem się od maszyny o ile robimy instalację zdalnie. Jeśli jest potrzeba filtracji pakietów w drugiej warstwie OSI to możemy skompilować kernel tak aby ipfw zawierał tą funkcjonalność (ipfw2) lecz nie będę opisywać tego co opisuje manual w temacie skompilowania ipfw2.

Skrypty startowe

/etc/rc.conf

Konfiguracja kernela zawiera już niezbędne elementy jak divert, ipfw, dummynet zatem możemy przystąpić do konfiguracji naszego firewalla. Przygotujemy własny skrypt ładujący regułki firewalla zatem należy w /etc/rc.conf wskazać go jako nasz firewall. Ponadto uruchomimy od razu NAT (natd). Poniżej interesujące nas fragmenty /etc/rc.conf:

ipv6_defaultrouter="NO" # Set to IPv6 default gateway (or NO). gateway_enable="YES" # Set to YES if this host will be a gateway. ### Basic network and firewall/security options: ### firewall_enable="YES" # Set to YES to enable firewall functionality firewall_script="/etc/regulki" # Which script to run to set up the firewall firewall_type="simple" # Firewall type (see /etc/rc.firewall) firewall_quiet="NO" # Set to YES to suppress rule display firewall_logging="YES" # Set to YES to enable events logging firewall_flags="" # Flags passed to ipfw when type is a file # natd natd_program="/sbin/natd" # path to natd, if you want a different one. natd_enable="YES" # Enable natd (if firewall_enable == YES). natd_interface="fxp2" # Public interface or IPaddress to use. natd_flags="-f /etc/natd.conf" # Additional flags for natd. # named. It may be possible to run named in a sandbox, man security for named_enable="YES" # Run named, the DNS server (or NO). named_program="/usr/sbin/named" # path to named, if you want a different one. named_flags="-u bind -g bind" # Flags for named named_pidfile="/var/run/named/pid" # Must set this in named.conf as well # pppoed server pppoed_enable="STANDALONE" # STANDALONE = run from /usr/local/etc/rc.d/pppoed.sh . pppoed_provider="*" # Provider and ppp(8) config file entry. pppoed_flags="-a isp -l default -P /var/run/pppoed.pid" # Flags to pppoed (if enabled). #pppoed_flags="-d -a isp -l default -P /var/run/pppoed.pid" # Flags with pppoed debug pppoed_interface="fxp1" # The interface that pppoed runs on.

/usr/local/etc/rc.d/pppoed.sh

Wyjaśnienia wymaga ustawienie zmiennej pppoed_enable="STANDALONE". Skrypt startujący pppoed we FreeBSd 4.x jest bardzo prymitywny dlatego napisałem własny który obsługuje start, stop oraz restart daemona, zatem aby oryginalny skrypt "odczepił się" i nie startował nam pppoed ustawiłem tą zmienną jako STANDALONE a w rzeczywistości pppoed jest uruchamiany z /usr/local/etc/rc.d/pppoed.sh. Daemon pppoed samoczynnie przy pierwszym uruchomieniu załaduje odpowiednie moduły netgraph do kernela. Poniżej kod źródłowy tego skryptu. Należy pamiętać o ustawieniu prawa wykonywania na tym skrypcie tak aby przy starcie maszyny został nim uruchomiony pppoed:

#!/bin/sh # Suck in the configuration variables. if [ -z "${source_rc_confs_defined}" ]; then if [ -r /etc/defaults/rc.conf ]; then . /etc/defaults/rc.conf source_rc_confs elif [ -r /etc/rc.conf ]; then . /etc/rc.conf fi fi case ${pppoed_enable} in [Ss][Tt][Aa][Nn][Dd][Aa][Ll][Oo][Nn][Ee]) case $1 in [Ss][Tt][Aa][Rr][Tt]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; _opts=$-; set -f /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} set +f; set -${_opts} ;; [Rr][Ee][Ss][Tt][Aa][Rr][Tt]) killall -9 pppoed rm -f /var/run/pppoed.pid /usr/local/etc/rc.d/pppoed.sh start ;; [Ss][Tt][Oo][Pp]) killall -9 pppoed rm -f /var/run/pppoed.pid ;; esac ;; esac

/etc/natd.conf

Poniżej bardzo prosty plik konfigiguracji /etc/natd.conf:

use_sockets same_ports unregistered_only

/etc/regulki

Poniżej skrypt startujący firewall przygotowany w taki sposób aby połączenie klienta poprzez ppp wstawiało nam w odpowiednich pozycjach dodatkowe regułki zezwalające na ruch do/z klienta oraz limitujące jego transfer:

# # Setup system for firewall service. # ############ # Set quiet mode if requested # fwcmd="/sbin/ipfw -q" # fwcmd="/sbin/ipfw" # Suck in the configuration variables. if [ -z "${source_rc_confs_defined}" ]; then if [ -r /etc/defaults/rc.conf ]; then . /etc/defaults/rc.conf source_rc_confs elif [ -r /etc/rc.conf ]; then . /etc/rc.conf fi fi setup_loopback () { ############ # Only in rare cases do you want to change these rules # ${fwcmd} add 100 pass all from any to any via lo0 ${fwcmd} add 200 deny log all from any to 127.0.0.0/8 ${fwcmd} add 300 deny log ip from 127.0.0.0/8 to any } ####################################### # Flush out the list before we begin. # # flushing rules ${fwcmd} -f flush # flushing pipes ${fwcmd} -f pipe flush # flushing queues ${fwcmd} -f queue flush ####################################### # firewall interfaces # wan przez dsl oif="fxp2" onet="83.x.y.z" omask="255.255.255.248" oip="83.x.y.v" # lan iif="fxp1" inet="10.0.0.0" imask="255.255.255.0" iip="10.0.0.1" ###################################################################### # init loopback rules setup_loopback # Stop spoofing ${fwcmd} add deny log all from ${inet}:${imask} to any in via ${oif} ${fwcmd} add deny log all from ${onet}:${omask} to any in via ${iif} # Stop RFC1918 nets on the outside interface #${fwcmd} add deny log all from any to 10.0.0.0/8 via ${oif} ${fwcmd} add deny log all from any to 172.16.0.0/12 via ${oif} ${fwcmd} add deny log all from any to 192.168.0.0/16 via ${oif} # Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes RESERVED-1, # DHCP auto-configuration, NET-TEST, MULTICAST (class D), and class E) # on the outside interface ${fwcmd} add deny log all from any to 0.0.0.0/8 via ${oif} ${fwcmd} add deny log all from any to 169.254.0.0/16 via ${oif} ${fwcmd} add deny log all from any to 192.0.2.0/24 via ${oif} ${fwcmd} add deny log all from any to 224.0.0.0/4 via ${oif} ${fwcmd} add deny log all from any to 240.0.0.0/4 via ${oif} # wycinka sieci windows przez serwer ${fwcmd} add deny ip from any to any 135-139,445 ${fwcmd} add deny ip from any 135-139,445 to any ###################################################################### # NAT in regulka zmodyfikowana na przychodzacy ze swiata # zamienić na: out xmit ${oif} jeśli potrzeba case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then ${fwcmd} add divert natd all from any to any via ${oif} fi ;; esac ###################################################################### # # limitowanie ruchu # # wyjatek na icmp ${fwcmd} add pass icmp from any to any ${fwcmd} add pass igmp from any to any # ruch do/z maszyny ${fwcmd} add pass all from me to any ${fwcmd} add pass all from any to me # jesli open to nie blokowac case ${firewall_type} in [Oo][Pp][Ee][Nn]) if [ -n "${natd_interface}" ]; then ${fwcmd} add skipto 50000 all from any to any fi ;; esac # przepuszczamy wszystko co w podsieci dsla ${fwcmd} add 11200 skipto 50001 ip from any to ${onet}:${omask} in recv ${oif} ${fwcmd} add 11300 skipto 50001 ip from ${onet}:${omask} to any out xmit ${oif} # przepuszczamy pytania do dhcpd ${fwcmd} add 11380 skipto 50001 udp from ${iip} 67 to ${inet}:${imask} 68 ${fwcmd} add 11390 skipto 50001 udp from ${inet}:${imask} 68 to 255.255.255.255 67 ${fwcmd} add 11400 skipto 50001 all from 0.0.0.0 to 255.255.255.255 ${fwcmd} add 11500 skipto 50001 all from ${iip} to 255.255.255.255 # puszczamy zapytania do lokalnego dns ${fwcmd} add 11600 skipto 50001 udp from ${inet}:${imask} to me 53 ${fwcmd} add 11700 skipto 50001 udp from me 53 to any #################### reszta ################################## ${fwcmd} add 39999 deny log ip from ${inet}:${imask} to ${inet}:${imask} ${fwcmd} add 40000 deny log ip from any to any ${fwcmd} add 50001 pass all from any to any ############################################################## ############################################################## # NAT out regulka zmodyfikowana na ruch wychodzacy w swiat # zamienić gdy potrzeba na: in recv ${oif} case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then ${fwcmd} add 50005 divert natd all from any to any via ${oif} fi ;; esac ############################################################# # Stop RFC1918 nets on the outside interface #${fwcmd} add deny log all from 10.0.0.0/8 to any via ${oif} ${fwcmd} add deny log all from 172.16.0.0/12 to any via ${oif} ${fwcmd} add deny log all from 192.168.0.0/16 to any via ${oif} # Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes RESERVED-1, # DHCP auto-configuration, NET-TEST, MULTICAST (class D), and class E) # on the outside interface ${fwcmd} add deny log all from any to 0.0.0.0/8 via ${oif} ${fwcmd} add deny log all from any to 169.254.0.0/16 via ${oif} ${fwcmd} add deny log all from any to 192.0.2.0/24 via ${oif} ${fwcmd} add deny log all from any to 224.0.0.0/4 via ${oif} ${fwcmd} add deny log all from any to 240.0.0.0/4 via ${oif} # puszczamy pingi jak leci ${fwcmd} add 50100 pass icmp from any to any # ruch do/z maszyny ${fwcmd} add pass all from me to any ${fwcmd} add pass all from any to me # everything is accepted via server ${fwcmd} add 65000 pass all from any to any ${fwcmd} add 65500 deny log logamount 10000 all from any to any # end of rules

Pewne problemy może sprawiać wyłapanie ruchu który powinien być przenatowany jednakże dla moich potrzeb takie regułki divert zadziałały i narazie takie pozostawiłem do czasu dalszych zmian.

/etc/sysctl.conf

Poniżej konfiguracja pożądanych sysctl'i:

#net.inet.ip.redirect=0

#net.inet.icmp.log_redirect=1 #net.inet.icmp.drop_redirect=1 # for dummynet 1-disable reinjecting 0-enable reinjecting net.inet.ip.fw.one_pass=0 # for layer2 filtering 1-enable 0-disable net.link.ether.ipfw=0 # blackhole antiscan #net.inet.tcp.blackhole=2 #net.inet.udp.blackhole=1 # log in vain #net.inet.tcp.log_in_vain=2 #net.inet.udp.log_in_vain=2

/etc/ppp.conf

Poniższa konfiguracja ppp zezwala na podłączanie klientów wyłącznie autoryzujących się MSChapv2 oraz wymusza szyfrowanie. Jeśli pożądane jest podłączanie się różnych sprzętowych routerków (przykładowo firma ma jedno pasmo i che być odseparowana swoim routerkiem od reszty sieci, na routerku ustawia konfiiigurację klienta pppoe, firewall, nat itp. itd.) to zapewne koniecznym będzie dopuszczenie zwykłej autoryzacji typu chap (proszę pamiętać że polecenia konfiguracji mają się zaczynać od drugiej kolumny czyli na początku polecenia jest jedna spacja):

################################################################# # # See /usr/share/examples/ppp/ for some examples # ################################################################# default: set device /usr/libexec/pppoed # set log Phase Chat LCP IPCP CCP tun command set log Phase Chat ident user-ppp VERSION (built COMPILATIONDATE) allow mode direct set mru 1400 set mtu 1400 set dns 10.0.0.1 10.0.0.1 accept dns resolv readonly set timeout 3600 set speed sync allow users disable pap deny pap #enable chap #accept chap disable chap deny chap disable LANMan deny LANMan enable mppe allow mppe disable MSChap deny MSChap enable MSChapv2 allow MSChapv2 # if needed enable proxy-arp enable proxy disable ipv6cp enable lqr # disable deflate deflate24 pred1 acfcomp protocomp # deny deflate deflate24 pred1 acfcomp protocomp disable deflate pred1 deny deflate pred1 set ifaddr 10.0.0.1 10.0.0.21-10.0.0.254

/dev/tunX

Zestawienie połączenia ppp powoduje podniesienie interfejsu tun0...tunX a ponieważ domyśłnie jest utworzone tylko tylko cztery takie urządzenia to musimy utworzyć ich dostateczną ilość w /dev:

$>cd /dev $>sh MAKEDEV tun250

/etc/ppp/ppp.secret

Plik z listą użytkowników loginy oraz przydzielone im hasła:

# # PLEASE USE UNIQUE LOGINS AND STRONG RANDOM PASSWORDS !!! # login password jasfasola h4sl0j4s14

/etc/ppp/ppp.linkup

Moduł ppp po zestawieniu i zautoryzowaniu połączenia przy podniesieniu interfejsu tunX uzytkownika wykonuje polecenia zawarte w pliku /etc/ppp/ppp.linkup i z tego poziomu uruchamiamy nasz skrypt generujący i wstawiający odpowiednie regułki do firewalla:

default: !bg /etc/ppp/addclient.sh USER connect HISADDR INTERFACE

/etc/ppp/ppp.linkdown

Analogicznie po rozłączeniu się użytkownika wywoływany jest /etc/ppp/ppp.linkdown z którego uruchomimy skrypt usuwający regułki danego użytkownika z firewalla:

default: !bg /etc/ppp/removeclient.sh USER disconnect HISADDR INTERFACE

/etc/ppp/addclient.sh

Skrypt wyliczający pewne parametry niezbędne do wstawienia regułek do firewalla na odpowiednich miejscach a także logujący parametry połaczenia do ewentualnych dalszych analiz i oględzin:

#!/bin/sh # grab parametres from commandline user=$1 type=$2 clientip=$3 int=$4 fwcmd="/sbin/ipfw" baza="/etc/ppp/ppp.klienci" usernum=`echo ${clientip} | cut -d "." -f 4` download=`grep ^${user} ${baza} | awk '{FS="[ \t]+"}{print $2}'` upload=`grep ^${user} ${baza} | awk '{FS="[ \t]+"}{print $3}'` if [ -z ${download} ]; then download=0 fi if [ -z ${upload} ]; then upload=0 fi pid=`cat /var/run/${int}.pid` # log this via syslogd message=`echo ppplinkup, ppppid ${pid}, ${user}, ${usernum}, ${download}, ${upload}, ${type}, ${clientip}, ${int}` logger -p local7.info $message pipedown=`echo "20000 + ${usernum} * 10" | /usr/bin/bc` pipeup=`expr ${pipedown} + 1` fwruledown=`expr ${pipedown} + 2` fwruleup=`expr ${pipedown} + 3` fwalldown=`expr ${pipedown} + 4` fwallup=`expr ${pipedown} + 5` ${fwcmd} pipe ${pipedown} config bw ${download}Kbit/s queue 16Kbytes ${fwcmd} pipe ${pipeup} config bw ${upload}Kbit/s queue 16Kbytes ${fwcmd} add ${fwruledown} pipe ${pipedown} all from any to ${clientip} in ${fwcmd} add ${fwruleup} pipe ${pipeup} all from ${clientip} to any out ${fwcmd} add ${fwalldown} pass all from any to ${clientip} ${fwcmd} add ${fwallup} pass all from ${clientip} to any

W powyższym skrypcie można by zmodyfikowac regułki tak aby ruch nie był traktowany niezależnie na przychodzący i wychodzący co pozwoliłoby na ustawienie jednej przepustowaości klientowi i przepuszczanie prze ztaką rurę ruchu w obu kierunkach a zatem klient dysponował by sumarycznie przepustowością obejmująca ruch do/z (asynchornicznie jak na SDI). Ponadto można by wymienić regułki zbierające ruch w rurki na poniższe lub ich wariacje z in recv/out xmit:

${fwcmd} add ${fwruledown} pipe ${pipedown} all from any to any in via ${int} ${fwcmd} add ${fwruledown} pipe ${pipeup} all from any to any out via ${int}

/etc/ppp/removeclient.sh

Analogicznie poniższy skrypt "sprząta" gdy klient się rozłączy:

#!/bin/sh # grab parameters from commandline user=$1 type=$2 clientip=$3 int=$4 fwcmd="/sbin/ipfw" baza="/etc/ppp/ppp.klienci" usernum=`echo ${clientip} | cut -d "." -f 4` download=`grep ^${user} ${baza} | awk '{FS="[ \t]+"}{print $2}'` upload=`grep ^${user} ${baza} | awk '{FS="[ \t]+"}{print $3}'` if [ -z ${download} ]; then download=0 fi if [ -z ${upload} ]; then upload=0 fi message=`echo ppplinkdown, ${user}, ${usernum}, ${download}, ${upload}, ${type}, ${clientip}, ${int}` logger -p local7.info ${message} pipedown=`echo "20000 + ${usernum} * 10" | /usr/bin/bc` pipeup=`expr ${pipedown} + 1` fwruledown=`expr ${pipedown} + 2` fwruleup=`expr ${pipedown} + 3` fwalldown=`expr ${pipedown} + 4` fwallup=`expr ${pipedown} + 5` ${fwcmd} delete ${fwallup} ${fwcmd} delete ${fwalldown} ${fwcmd} delete ${fwruleup} ${fwcmd} delete ${fwruledown} ${fwcmd} pipe delete ${pipeup} ${fwcmd} pipe delete ${pipedown}

/etc/ppp/ppp.klienci

Należy wyjaśnić że w powyższych skryptak wykorzystany jest plik tekstowy z parametrami przepustowości przyznanej użytkownikowi do wygenerowania odpowiednich rurek. Plik /etc/ppp/ppp.klienci ma prostą budowę skłądającą się z trzech kolumn. Zapewne dalsze rozwinięcie tego projektu zastąpi ten plik RADIUS'em:

# # UWAGA! zadnych pustych linii w tym pliku! # dozwolone komentarze od znaku # na poczatku linii # # login down up jasfasola 256 64

/etc/syslog.conf

Skrypty addclient.sh oraz removeclient.sh wysyłają do daemona syslog pozycje do zalogowania z facility local7.info także daemon pppoed, ppp i named loguje różne komunikaty. Należy sobie dopisać w /etc/syslog.conf poniższe pozycje i odpowiednio w /etc/newsyslog.conf opisać ich rotowanie i przycinanie:

local7.info /var/log/connection.log !ppp *.* /var/log/ppp.log !named *.* /var/log/named.log !pppoed *.* /var/log/pppoed.log

/etc/namedb/named.conf

Na naszym lokalnym serwerze będziemy logowć zapytania do dns. Klienci otrzymują jako adres serwera dns adres ip drugiego końca linku ppp i na tym adresie nasłuchuje named zatem wszelkie zapytania kierowane do niego możemy zalogować. Zapytania kierowane z pominięciem lokalnego dns mogą świadczyć o wirusie u klienta lub o celowej zmianie konfiguracji dns przez klienta jednakże możemy takie zapytania zablokować na firewallu. Poniższe wpisy włączają logowanie w bindzie:

logging { category default { default_syslog; default_debug; }; category panic { default_syslog; default_stderr; }; category packet { default_debug; }; category eventlib { default_debug; }; category queries { default_syslog; }; category statistics { default_syslog; }; category xfer-in { default_syslog; }; category xfer-out { default_syslog; }; };

Konfiguracja klienta

Nowe systemy typu Windows XP/2003 posiadają wbudowany moduł połączeń pppoe. Starsze systemy typu Windows 9x niestety wymagają zainstalowania klienta pppoe (np. raspppoe). Wspomnieć jednak należy o tym iz u klienta (Windows XP/2003) powinniśmy pozostawić jedynie "gołą" kartę sieciową, bez jakichkolwiek usług i protokołów (w szczególności sieci windows) i włączyć klientowi firewall. Raspppoe natomiast dodaje swój własny protokół do danej sieciówki i jest on niezbędny do poprawnego działania.

Instalacja połączenia z Internetem przy użyciu protokołu pppoe dla Windows XP/2000 (zakładamy że karta sieciowa jest zainstalowana):

Menu Start -> Panel sterowania -> Połączenia sieciowe:

Prawym myszką klikamy na karcie sieciowej właściwości:

Sprawdzamy i odznaczamy lub odinstalowujemy wszelkie usługi i protokoły sieciowe (tcpip, klienta sieci MS Networks, Udostępnianie plików i drukarek, Harmonogram pakietów QoS, i inne) zatwierdzamy zmiany i zamykamy formatkę:

W okienku Połączenia sieciowe klikamy kreatora: Utwórz nowe połączenie:

i dalej

Wybieramy: Połącz z Internetem:

Wybieramy: Konfiguruj moje połączenie ręcznie:

Wybieramy: Połącz używając połączenia szerokopasmowego… (poppe):

W polu nazwa usługodawcy internetowego wpisujemy małymi literami: isp

Wprowadzamy nazwę użytkownika (login) i hasło, zaznaczamy obie opcje dla zezwolenia wszystkim lokalnym użytkownikom komputera na podłączanie do Internetu oraz ustawiamy to połączenie jako domyślne:

Zaznaczamy utworzenie skrótu na pulpicie:

Gdy wyskoczy okienko „Łączenie z isp” zanim połączymy się z internetem należy jeszcze zmienić parametry połączenia zatem klikamy przycisk właściwości:

W okienku „isp właściwości” KONIECZNIE zmieniamy na zakładce zabezpieczenia Opcje zabezpieczeń zaznaczając opcje zaawansowane i klikając przycisk ustawienia:

W oknie „Zaawansowane ustawienia zabezpieczeń” ustawiamy Najmocniejsze szyfrowanie (odłącz, jeśli serwer odmawia) oraz Zezwalaj na użycie protokołów: wyłącznie MS CHAP wersja 2:

Po zatwierdzeniu przyciskiem OK. przechodzimy na zakładkę Sieć:

Klikamy przycisk Ustawienia, zaznaczamy wszystkie trzy opcje i zatwierdzamy OK:

Jeżeli komputer ma zainstalowany pakiet zabezpieczeń Service Pack 2 dla Windows XP to przechodzimy na zakładkę Zaawansowane:

W oknie „Zapora systemu Windows” klikamy przycisk Ustawienia i w opcjach Zapory włączamy zaporę ale opcję Nie zezwalaj na wyjątki pozostawiamy nie zaznaczoną:

Przechodzimy na zakładkę zaawansowane i w ramce Protokół ICMP klikamy przycisk Ustawienia

W oknie „Ustawienia protokołu ICMP” należy KONIECZNIE zezwolić na wszystkie (chyba że się dokładnie wie które chcemy wyblokować i jaki to może mieć skutek) typy pakietów ICMP (niezbędna dla poprawnego rozpoznawania PMTU) i zatwierdzić to OK:

Okienko „Zapora systemu Windows” akceptujemy przyciskiem OK, a następnie także akceptujemy okienko właściwości połączenia „isp właściwości”. Po zatwierdzeniu już możemy podłączyć się do Internetu klikając przycisk Połącz. Proszę zwrócić uwagę aby była zaznaczona opcja Zapisz tę nazwę użytkownika… dla Dowolny użytkownik tego komputera:

Takie ustawienie opcji połączenia jest bardzo ważne bowiem zapewni nam bezpieczeństwo i poufność przesyłanego loginu i hasła użytkownika a także całej transmisji po sieci lokalnej do routera internetowego realizującego połączenie użytkownika z Internetem. Zabezpiecza to przed podsłuchaniem przez innych użytkowników danych przesyłanych po sieci lokalnej, jednakże pomiędzy routerem internetowym a innymi serwerami w Internecie dane mogą nie być szyfrowane bowiem to już zależy od konkretnych potrzeb użytkowanych aplikacji. Zwykle szyfrowane połączenia są zestawiane przez przeglądarkę internetową przy operacjach w bankowości internetowej, czy też przy dostępie do poczty internetowej u niektórych usługodawców itp.

Konfiguracja systemu pocztowego we FreeBSD na bazie qmaila

© 2003-10-02 Bartłomiej Siębab ver. 1.6

WSTĘP

Czym jest qmail? qmail to bezpieczny i wydajny serwer poczty internetowej posługujący sie protokołem SMTP. Został zaprojektowany dla typowych serwerów UNIX i charakteryzuje się doskonałą wydajnością w działaniu pod bardzo dużym obciążeniem przy ogromnych ilościach przetwarzanej poczty. Potrafi obsługiwać wirtualne skrzynki pocztowe bez konieczności zakładania tradycyjnych kont. Jego autorem jest profesor D.J.Bernstein. Architektura qmaila (w przeciwieństwie do Sendmaila) została opracowana w oparciu o wiele małych, sprawnych i dedykowanych programów zajmujących sie konkretnymi zadaniami serwera pocztowego. Każdy z nich wykonuje swoje zadania efektywnie i bezpiecznie. Każdy posiada minimalne uprawnienia niezbędne do wykonywania czynności jedynie jemu przeznaczonych i niczego ponadto. W tym artykule opiszę proces przygotowania qmaila do pracy ze skrzynkami pocztowymi w formacie Maildir, które charakteryzują się przechowywaniem każdego emaila w osobnym pliku.

INSTALACJA

W systemie FreeBSD 4.x instalacja qmaila 1.3 jest niezwykle prosta ze względu na mechanizm "/usr/ports". Każdy kto kiedyś "ręcznie" pierwszy raz instalował qmaila bez użycia "ports" ze względu na jego "specyficzną" filozofię zapewne spędził nad dokumentacją wiele godzin ;-). Teraz jednak wystarczy wykonać poniższe czynności a system zostanie po samoczynnym ściągnięciu źródeł z internetu automatycznie skompilowany, wstępnie skonfigurowany i zainstalowany:
$/> cd /usr/ports/mail/qmail
$/usr/ports/mail/qmail> make install clean
Pamiętajmy że domyślnym MTA we FreeBSD jest "fabrycznie" sendmail tak więc instalacja qmaila zmieni parametry w /etc/mail/mailer.conf na poniższe (co zresztą warto sprawdzić):
$/etc/mail> cat mailer.conf

# Configuration for mailwrapper is kept in /etc/mail/mailer.conf.
# Replace that file with this one to enable qmail under a sendmail
# disguise. Very useful.
#
sendmail        /var/qmail/bin/sendmail
send-mail       /var/qmail/bin/sendmail
mailq           /var/qmail/bin/qmail-qread
newaliases      /var/qmail/bin/newaliases
Jak zainstalować qmaila w Slackware Linux można przeczytać tutaj: http://www.linuxstar.pl/qmail.htm Wyłączenie sendmaila Teraz wyłączamy w /etc/rc.conf automatyczne uruchamianie sendmaila na rzecz qmaila, który będzie startował poprzez skrypty w /usr/local/etc/rc.d gdzie jego start podzielimy na trzy niezależne funkcjonalnie podsystemy:
$/etc>grep sendmail rc.conf
# autostartowy skrypt MTA (można tu też podpiąć od razu qmaila)
mta_start_script="/etc/rc.sendmail"
# Settings for /etc/rc.sendmail:
sendmail_enable="NONE"               # Run the sendmail inbound daemon (YES/NO/NONE).
                              # If NONE, don't start any sendmail processes.
sendmail_flags="-L sm-mta -bd -q30m" # Flags to sendmail (as a server)
sendmail_submit_enable="NO"          # Start a localhost-only MTA for mail submission
sendmail_submit_flags="-L sm-mta -bd -q30m -ODaemonPortOptions=Addr=localhost"
sendmail_outbound_enable="NO"                        # Dequeue stuck mail (YES/NO).
sendmail_outbound_flags="-L sm-queue -q30m"          # Flags to sendmail (outbound only)
sendmail_msp_queue_enable="NO"                       # Dequeue stuck clientmqueue mail (YES/NO).
sendmail_msp_queue_flags="-L sm-msp-queue -Ac -q30m" # Flags for sendmail_msp_queue daemon.
To ustawienie gwarantuje nieuruchamianie żadnego z procesów sendmaila. Skrypty startowe Utworzymy skrypty startowe qmail' w /usr/local/etc/rc.d poprzez podlinkowanie symboliczne:
$/usr/local/etc/rc.d> ls -l | grep qmail

lrwx------  1 root  wheel   19 14 Wrz 15:32 pop3d.sh -> /var/qmail/pop3d.rc
lrwx------  1 root  wheel   22 14 Wrz 15:32 reciving.sh -> /var/qmail/reciving.rc
lrwx------  1 root  wheel   21 14 Wrz 15:32 sending.sh -> /var/qmail/sending.rc

$/usr/local/etc/rc.d> cd /var/qmail ; ls -l *.rc

-r-xr-xr-x  1 root  qmail  385 Aug 24  1999 pop3d.rc
-r-xr-xr-x  1 root  qmail  842 Nov 24  1999 reciving.rc
-r-xr-xr-x  1 root  qmail  311 Aug 24  1999 sending.rc

$/var/qmail> cat pop3d.rc

#!/bin/sh
# Using splogger to send the log through syslog.
# Using qmail-local to deliver messages to Maildir format by default
#
# uruchamianie uslugi pop (odbior poczty ze skrzynek)
pathtmp=$PATH
PATH=/var/qmail/bin:$PATH
/usr/local/bin/tcpserver 0 pop3 /var/qmail/bin/qmail-popup twojhost.jakasdomena.pl \
/bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir &

$/var/qmail> cat reciving.rc

#!/bin/sh
#
# Using splogger to send the log through syslog.
# Using qmail-local to deliver messages to Maildir format by default
#
# uruchamianie uslug smtpd (przyjmowanie poczty przez serwer)
pathtmp=$PATH
PATH=/var/qmail/bin:$PATH
# wywolanie z plikiem adresow relay oraz po wdrozeniu spamcontrol
/usr/local/bin/tcpserver -v -x /etc/tcp.smtp.cdb -u 82 -g 81 0 smtp \
/var/qmail/bin/qmail-smtpd 2>&1 | /var/qmail/bin/splogger smtpd &

$/var/qmail> cat sending.rc

#!/bin/sh
#
# Using splogger to send the log through syslog.
# Using qmail-local to deliver messages to Maildir format by default
#
# uruchamianie procesow wysylki poczty przez serwer
pathtmp=$PATH
PATH=/var/qmail/bin:$PATH
/var/qmail/bin/qmail-start ./Maildir/ splogger qmail &
qmail może być uruchamiany także poprzez inetd (odpowiednie wpisy w /etc/inetd.conf), jednak ja zdecydowałem sie na wykorzystanie pakietu ucspi-tcp tego samego autora. Program tcpserver z tego pakietu umożliwia nam ustawianie wielu specyficznych dla qmaila parametrów startowych. Kompilacja ze źródeł i instalacja tego pakietu jest niezwykle prosta, może być także we FreeBSD wykonana poprzez mechanizm "ports". Dodatkowym pakietem niezbędnym do autoryzacji usługi pop jest pakiet checkpassword tego samego autora. Jego instalacja jest równie banalna jak w poprzednim przypadku. Tak zainstalowany w podstawowej konfiguracji qmail wraz z dodatkowymi modułami jest już prawie gotowy do działania. Czas dokonać niezbędnych wpisów w DNS oraz w plikach sterujących działaniem qmaila. W przytoczonych powyżej skryptach startowych użyłem dodatkowego modułu spamcontrol którego opis konfiguracji i instalacji przedstawiam w kolejnych rozdziałach. Start serwera automatycznie powoduje uruchomienie skryptów startowych i tym samym rozpoczęcie działania przez qmaila. Oczywiście możemy także te skrypty uruchomić "ręcznie". Rozdzielenie funkcji na trzy oddzielne skrypty pozwala na "dłubanie" przy qmail'u bez konieczności zatrzymywania całego serwera poczty. Przykładowo zmieniając coś przy części odbiorczej możemy jedynie zatrzymać odbieranie przesyłek podczas gdy wysyłka poczty z kolejki pocztowej nadal działa. Inną metodą jest uruchamianie poprzez tzw. "svc" z pakietu daemontools co opisuje dokumentacja qmaila. Jeśli oprócz usługi pop3 chcemy także udostępnić możliwość "katalogowego" czytania poczty poprzez usługi imap to możemy zainstalować i skonfigurować pakiet courier-imap, który dedykowany jest właśnie do współpracy ze skrzynkami pocztowymi typu Maildir.

DNS

Działanie serwera pocztowego wymaga ustawienia w opisie strefy dns odpowiednich wpisów zapewniających przyjmowanie i obsługę poczty dla całej domeny. Poniżej przedstawiam taką strefę (przykład dla bind'a) wraz z rekordem MX (Mail eXchanger):
$>cd /etc/namedb/s ; head -12 jakasdomena.pl

@       IN      SOA     twojhost.jakasdomena.pl. hostmaster.jakasdomena.pl.  (
                         200210081235
                         8H              ; Refresh
                         2H              ; Retry
                         1W              ; Expire
                         1D )            ; Minimum
;
         NS      twoj.primary.dns.jakasdomena.pl.
         NS      twoj.secondary.dns.innadomena.pl.
         MX      10 twojhost
;
W przykładowej strefie domeny vt.pl rekord MX wskazuje, że cała poczta kierowana do tej domeny jest obsługiwana przez serwer voyager.vt.pl i jest to warunek konieczny dla działania wysyłki poczty "po domenie". Nie będę przedstawiać tu szczegółowych opisów konfiguracji serwera usługi dns bowiem nie to jest celem tego artykułu. Zainteresowanych odsyłam do dokumentacji ich serwera dns czy to bind'a czy djb-dns. Pamiętajmy, że każda zmiana w pliku strefy wymaga zwiększenia nr seryjnego i restart dns'a.

KONFIGURACJA

Pliki konfiguracyjne qmaila znajdują się w katalogu /var/qmail/control i mają różnoraki wpływ na jego działanie i zachowanie. Poniższy listing przedstawia pliki po wdrożeniu modułu spamcontrol oraz PolSpam:
$/var/qmail/control> ls -l
-rw-rw-r--  1 root  wheel        0 Nov 11 13:14 badmailfrom
-rw-r--r--  1 root  qmail        4 Nov 11 11:47 badmailpatterns
-rw-r--r--  1 root  qmail        4 Nov 11 11:48 badrcptpatterns
-rw-r--r--  1 root  qmail       44 Nov 15 09:17 badrcptto
-rw-r--r--  1 root  qmail  1053293 Nov 17 13:31 blackholedsender
-rw-r--r--  1 root  qmail        0 Nov 11 12:21 databytes
-rw-r--r--  1 root  qmail        6 Nov 11 11:37 defaultdomain
-rw-r--r--  1 root  qmail        6 Aug 19  1999 defaulthost
-rw-r--r--  1 root  qmail       60 Nov 11 11:41 locals
-rw-r--r--  1 root  qmail        0 Nov 11 11:04 maxrecipients
-rw-r--r--  1 root  qmail       14 Nov 11 11:37 me
-rw-r--r--  1 root  qmail        0 Nov 11 11:03 nodnscheck
-rw-r--r--  1 root  qmail        6 Nov 11 11:37 plusdomain
-rw-r--r--  1 root  qmail       50 Nov 11 11:42 rcpthosts
-rw-r--r--  1 root  qmail        0 Nov 11 11:02 relayclients
-rw-r--r--  1 root  qmail        6 Nov 11 11:49 relaydomains
-rw-r--r--  1 root  qmail       11 Nov 11 12:17 relaymailfrom
-rw-r--r--  1 root  qmail  9441280 Nov 17 13:31 spammers.db
-rw-r--r--  1 root  qmail        3 Nov 11 12:32 tarpitcount
-rw-r--r--  1 root  qmail        2 Nov 11 12:03 tarpitdelay
-rw-r--r--  1 root  qmail      277 Nov 11 11:45 uwaga.txt
-rw-r--r--  1 root  qmail       20 Aug 19  1999 virtualdomains
Omówienie ważniejszych plików
  • badmailfrom adresy lub domeny, od których serwer nie przyjmie i zwróci pocztę kierowaną do niego
  • badmailpatterns wyrażenia regularne (regexp) ogólnie opisujące wzorzec adresów lub domen nadawcy, od których serwer nie przyjmie i zwróci pocztę kierowaną do niego
  • badrcptpatterns wyrażenia regularne (regexp) ogólnie opisujące wzorzec adresów lub domen odbiorcy, do których serwer nie przyjmie i zwróci pocztę kierowaną do niego
  • blackholedsender nazwy hostów lub domen, od których przychodzące połączenia do serwera poczty w ogóle nie będą przyjmowane, do tego pliku trafia baza spamerów aktualizowana z serwisu PolSpam
  • nodnscheck tu znajdują się nazwy hostów lub domen, z których przy przyjmowaniu poczty serwer nie będzie sprawdzał zgodności z revdns
  • rcpthosts nazwy hostów, dla których serwer przyjmuje pocztę
  • relaydomains nazwy domen, od których serwer przyjmuje i przetwarza pocztę do dalszej wysyłki
  • relaymailfrom adresy email które mają zezwolenie na przyjmowanie poczty do dalszej wysyłki
  • maxrecipients maksymalna liczba jednoczesnych odbiorców w pojedynczym mailu
  • tarpitcount liczba jednoczesnych odbiorców w pojedynczym mailu po której zostanie aktywowane opóźnienie przyjmowania poczty
  • tarpitdelay czas opóźnienia przyjmowania poczty tzw. "tarpiting"
  • databytes maksymalny rozmiar (w bajtach) maila
  • virtualdomains nazwy domen wirtualnych, dla których serwer przyjmuje pocztę
Relaying qmail jest systemem pocztowym, w którym należy określić z jakich adresów IP lub domen lub adresów email dozwolone jest przyjęcie poczty do dalszej wysyłki czyli tzw. relaying. Jest kilka metod na odpowiednie skonfigurowanie tego mechanizmu. Nie wolno otwierać relayowania poczty na cały świat bo bardzo łatwo można trafic do antyspamerskich baz typu ORBs tym samym blokując sobie serwer, bowiem nagle okazuje się że inne serwery poczty nie chcą przyjmować od nas poczty ze względu na naszą otwartość dla spamerów. Mechanizm ten zapewnia udostępnia nam moduł tcpserver. Odpowienie wywołanie w skrypcie startowym reciving.sh pozwala na korzystanie przez tcpserver z dodatkowego pliku /etc/tcp.smtp.cdb bazy adresów IP, od których dozwolone jest przyjęcie poczty w celu jej relayowania. W tym celu tworzymy tekstowy plik ze spisem tych adresów IP:
$/etc> head -3 tcp.smtp

127.:allow,RELAYCLIENT=""
192.168.100.1-255:allow,RELAYCLIENT=""
10.1.0.:allow,RELAYCLIENT=""
Następnie konwertujemy go do bazy cdb z której korzysta tcpserver:
$/etc> tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp 
Teraz do dalszego przekazania zostanie przyjęta jedynie poczta z wyspecyfikowanych adresów IP hostów. Dodatkowo przy wykorzystaniu modułu spamcontrol możemy zezwolić na relayowanie poczty na podstawie domeny czy adresu nadawcy (pliki relaydomains i relaymailfrom).

SKRZYNKI

Maildir Natywnym formatem skrzynek pocztowych qmaila jest format Maildir, który ze względu na przechowywanie przesyłek w odrębnych plikach jest szczególnie odporny na różne rodzaje awarii systemu plików serwera, bowiem w razie np. awarii zasilania (gdy nie mamy ups'a) podczas zapisu poczty do skrzynki, utracić można jedynie jeden email, w przeciwieństwie do formatu mailbox gdzie wszystkie przesyłki są w jednym pliku, co grozi całkowitą utratą całej poczty w tej hipotetycznej sytuacji. Do obsługi poczty w trybie terminalowym polecam program mutt, który potrafi obsłużyć skrzynki pocztowe zarówno typu mailbox jak i Maildir. Quota Każdy z użytkowników poczty powinien mieć założoną skrzynkę pocztową. Skrzynki są zakładane w katalogu domowym użytkownika i oczywiście podlegają restrykcji zarówno względem ilości miejsca jak i ilości plików/przesyłek. Dba o to mechanizm quoty i obejmuje w tym przypadku zarówno pocztę jak i pozostałe pliki użytkownika. Poczta jest przechowywana z prawami użytkownika i dlatego można mu limitować jej objętość:
$> quota jkowalski

Disk quotas for user jkowalski (uid 9999):
Filesystem   usage   quota   limit   grace   files   quota   limit   grace
   /home      24   20000   20000              14    1000    1000
Założenie skrzynki Jednorazowe założenie skrzynki polega na założeniu określonej struktury katalogów w $HOME (katalogu domowym) użytkownika. Do tego celu służy polecenie maildirmake wywoływane w następujący sposób:
$> umask
022

$> cd /home/jkowalski
$/home/jkowalski> maildirmake Maildir
$/home/jkowalski> chown -R jkowalski:jkowalski Maildir ; chmod -R g-rwx,o-rwx Maildir
$/home/jkowalski> ls -lR Maildir

total 3
drwx------  2 jkowalski  jkowalski  512 Mar 31  2000 cur
drwx------  2 jkowalski  jkowalski  512 Oct 25 19:02 new
drwx------  2 jkowalski  jkowalski  512 Oct 25 15:10 tmp

Maildir/cur:

Maildir/new:

Maildir/tmp:
Szablon Możemy wymusić automatyczne zakładanie Maildir'a każdemu nowo tworzonemu użytkownikowi poprzez założenie takiej struktury jako szablonu w /usr/share/skel i wtedy gdy zakładamy użytkownika np. poleceniem adduser jkowalski to system automatycznie skopiuje nam także Maildir'a wraz z innymi plikami typu dot.profile itp. Jedyną różnicą jest właściciel i grupa pliku która zostanie automatycznie zmieniona na użytkownika i jego grupe po tej operacji:
$/usr/share/skel> ls -lR Maildir
total 3
drwx------  2 root  wheel  512 Jan  9  2002 cur
drwx------  2 root  wheel  512 Jan  9  2002 new
drwx------  2 root  wheel  512 Jan  9  2002 tmp

Maildir/cur:

Maildir/new:

Maildir/tmp:
Wpis do bazy skrzynek pocztowych Czas na dopisanie skrzynki użytkownika do bazy skrzynek qmaila. W celu zwiększenia wydajności qmail używa specjalnych plików baz danych cdb. Tak jak w przypadku bazy hostów relayowanych, dopisanie skrzynki polega na dodaniu odpowiedniego wpisu "ulubionym edytorem" do pliku tekstowego a następnie jego konwersję do pliku bazy cdb. Przykładowy wpis:
$> cd /var/qmail/users
$/var/qmail/users> cat assign

=jan.kowalski:jkowalski:9999:9999:/home/jkowalski:::
+jk-:jkowalski:9999:9999:/home/jkowalski:-::
.

$/var/qmail/users> qmail-newu
Pamiętajmy o niezbędnej kropce na końcu pliku. Dlaczego jest niezbędna? To znajdziecie oczywiście w dokumentacji qmaila ;-). Jak widzimy w powyższym przykładzie użytkownik otrzymał od nas skrzynkę postaci jan.kowalski@jakasdomena.pl oraz jk@jakasdomena.pl jego uid/gid to 9999 (taki jak w rzeczywistości posiada) a położenie skrzynki jest w jego katalogu domowym. Użytkownik ma mozliwość korzystania z plików typu .qmail-costam co pozwala mu na samodzielne założenie np. kilku aliasów pocztowych np. jk-praca@jakasdomena.pl poprzez utworzenie pliku .qmail-praca w swoim katalogu domowym. Na koniec wykonujemy konwersję do bazy cdb poleceniem qmail-newu. Możliwe jest hurtowe wygenerowanie skrzynek na podstawie pliku passwd i oczywiście jest to opisane w dokumentacji qmaila.

WALKA ZE SPAMEM

SpamControl W celu większej funkcjonalności związanej z kontrolą spamu zainstalowałem moduł SPAMCONTROL, który udostępnia kontrolę wielu aspektów, o których już wcześniej wspominałem przy opisie konfiguracji. Co potrafi ten moduł? Oczywiście jest to dokładnie opisane na stronie domowej projektu SpamControl. Schematycznie jego działanie przedstawione jest na załączonym rysunku w formacie pdf. Instalacja Instalacja modułu polega na spaczowaniu źródeł qmaila, ponownej kompilacji i podmianie kilku oryginalnych plików qmaila na nowo utworzone. Najprościej można to wykonać poprzez zapaczowanie w "ports" już skompilowanego qmaila i jego rekompilację z reinstalacją. Koniecznie i na wszelki wypadek należy zabezpieczyć sobie aktualne pliki konfiguracyjne qmaila, skrypty startowe, bazę użytkowników i relayowania, tak aby instalacja nie "przykryła" nam naszych cennych oryginałów tymi dystrybucyjnymi. Po zabezpieczeniu tych plików ja zrobiłem to tak:
$> cd /usr/ports/mail/qmail
$/usr/ports/mail/qmail> make
Tutaj wykonuje się ściągnięcie źródeł qmaila (o ile ich nie ma w systemie) i jego kompilacja, usuwamy także znacznik zakończenia kompilacji i następnie paczujemy źródła modułem SpamControl, sprawdzamy czy wszystko przebiegło poprawnie, instalujemy qmaila:
$/usr/ports/mail/qmail> cd work
$/usr/ports/mail/qmail/work> ls -al .[bi]*_done.qmail-1.03_1

-rw-r--r--  1 root  wheel  0 Nov 11 11:22 .build_done.qmail-1.03_1
-rw-r--r--  1 root  wheel  0 Nov 11 11:37 .install_done.qmail-1.03_1

$/usr/ports/mail/qmail/work> rm .[bi]*_done.qmail-1.03_1
$/usr/ports/mail/qmail/work> cd qmail-1.03
$/usr/ports/mail/qmail/work/qmail-1.03> fetch http://www.fehcom.de/qmail/spamcontrol_180_tgz.bin
$/usr/ports/mail/qmail/work/qmail-1.03> tar -zxvf spamcontrol_180_tgz.bin
$/usr/ports/mail/qmail/work/qmail-1.03> ./spamcontrol.sh
$/usr/ports/mail/qmail/work/qmail-1.03> cat spamcontrol.log

Running spamcontrol.sh INSTALLATION at Mon Nov 11 11:20:04 CET 2002 for Revision 180 <<< --> Makefile copied to Makefile.180
--> qmail-smtpd.c copied to qmail-smtpd.c.180
--> qmail-smtpd.8 copied to qmail-smtpd.8.180
--> qmail-showctl.c copied to qmail-showctl.c.180
--> qmail-control.9 copied to qmail-control.9.180
--> qmail-log.5 copied to qmail-log.5.180
--> ipme.c copied to ipme.c.180

$/usr/ports/mail/qmail/work/qmail-1.03> cd ../..
$/usr/ports/mail/qmail> make install clean
Na koniec przywracamy oryginały naszych plików konfiguracyjnych które zostały zastąpione dystrybucyjnymi z oryginałów w źródłach qmaila. Całą operację wykonujemy po zatrzymaniu procesów wysyłki i odbioru poczty qmaila. Po poprawnej instalacji standardowo możemy uruchomić serwer pocztowy naszymi skryptami startowymi. Należy "zająć się" nowymi plikami konfiguracyjnymi qmaila i w zależności od potrzeb je utworzyć (z właściwymi prawami). Od tego momentu dostepne są także zaktualizowane manuale do qmail-smtpd oraz qmail-control a także qmail-log. Nową funkcjonalność qmaila wykorzystamy do lepszej ochrony antyspamowej poprzez wykorzystanie baz spamerów z serwisu PolSpam. Nie zapominajmy o możliwości filtrowania poczty przy pomocy pakietu maildrop, który moim zdaniem jest dużo łatwiejszy w konfigurowaniu regułek. MailDrop Pakiet ten możemy standardowo zainstalować przy pomocy mechanizmu "ports". Znajdziemy go poprzez tradycyjne przeszukanie bazy ports:
$/usr/ports> make search key=maildrop

Port:   maildrop-1.3.8
Path:   /usr/ports/mail/maildrop
Info:   Replacement local mail delivery agent, similar to procmail
Maint:  petef@FreeBSD.org
Index:  mail
B-deps: gdbm-1.8.0
R-deps: gdbm-1.8.0

$/usr/ports> cd mail/maildrop ; make install clean
Każdy użytkownik może przy jego pomocy filtrować pocztę dostarczaną do skrzynki pocztowej. Oto prosty przykład odfiltrowania Koreańskiego spamu po kodowaniu zawartym w nagłówku poczty:
jkowalski@jakishost> cd
jkowalski@jakishost:~> cat .qmail

| preline /usr/local/bin/maildrop

jkowalski@jakishost:~> head -20 .mailfilter

# filtrowanie wedlug kodowania i won do folderu SPAM
if ( /^Content-Type: text\/html; charset="ISO-8859-11"/ )
{
exit
}
if ( /^Content-Type: text\/html; charset="ks_c_5601-1987"/ )
{
exit
}
if ( /^Content-Type: text\/html; charset="euc-kr"/ )
{
exit
}
if ( /^Content-Type: text\/html; charset="EUC-KR"/ )
{
exit
}
# a reszta dostarczana normalnie
to "$HOME/Maildir/"

PolSpam

Do funkcjonalności modułu SpamControl warto dodać synchronizację z bazami adresów spamerów. Jest to bardzo proste i błyskawiczne do wykonania. Najlepszym krajowym serwisem tego typu jest PolSpam i stamtąd właśnie będziemy pobierać bazę spamerów. Można to robić albo poprzez pocztę albo poprzez cykliczne pobieranie aktualizacji baz protokołem http i ja tak właśnie zrobiłem. Skrypty Cytując autorów: Na potrzeby cyklicznej synchronizacji autorzy udostępnili dwa skrypty w Perlu, które automatyzują to zadanie. Skrypt sync_web.pl dokonuje synchronizacji lokalnej bazy adresów poprzez połączenie się z serwerem WWW PolSpamu, natomiast skrypt sync_mail.pl umożliwia przetworzenie listy zmian wysyłanych przez PolSpam w formie wiadomości z listy mailingowej. Obydwa skrypty aktualizują lokalną bazę adresów w pliku o formacie .db, która może być wykorzystana do blokowania spamu przez serwery obsługujące bazy w takim formacie (np. sendmail). Dla oprogramowania wymagającego baz w formacie tekstowym istnieje możliwość, aby skrypt po każdej aktualizacji wygenerował plik tekstowy zawierający adresy z bazy w jednym z formatów: plain, sendmail, qmail, exim czy też procmail. Kod źródłowy skryptów oraz dokumentacja zawarta jest w pliku polspam.tgz. Skrypty udostępnione są na zasadach licencji BSD - można je używać jak i modyfikować bez żadnych ograniczeń. Pobieramy skrypty synchronizujące i po drobnych modyfikacjach typu eksportu do pliku tekstowego oraz jego położenia które to należy poprawić w pierwszych kilkunastu liniach w skrypcie sync_web.pl, zaprzęgamy go do pracy:
$> cd /var/qmail/bin
$/var/qmail/bin> fetch http://www.polspam.info/scripts/polspam.tgz && tar -zxvf polspam.tgz
$/var/qmail/bin> chmod a+rx sync_web.pl
$/var/qmail/bin> grep ^my sync_web.pl | head -3

my $db   = "/var/qmail/control/spammers";               # Path to .db file [required]
my $type = "qmail";                                     # Type out output file [optional]
my $file = "/var/qmail/control/blackholedsender";       # Path to output file [optional]
Synchronizacja Ustawiłem typ eksportu jako plik dla qmaila (prosty plik tekstowy) na /var/qmail/control/blackholedsender co zabroni przyjmowania połączeń ze spamerskich hostów oraz przechowywanie bazy spamerów /var/qmail/control/spammers. Być może perl będzie wymagał modułu LWP, który już tradycyjną metodą zainstalujemy z "/usr/ports/www/p5-libwww". Teraz nasz skrypt jest gotowy do użycia. Pierwszy raz kontrolnie uruchamiamy go "z ręki" i sprawdzamy czy wszystko poszło dobrze. Pierwsze ściągnięcie kompletnej bazy spamerów "trochę" trwa ale każda kolejna synchronizacja "dociąga" juz jedynie same zmiany:
$> cd /var/qmail/control
$/var/qmail/control> /var/qmail/bin/sync_web.pl

$/var/qmail/control> ls -l spammers.db

-rw-r--r--  1 root  qmail  9453568 15 Lis 16:47 spammers.db

$/var/qmail/control> ls -l black*

-rw-r--r--  1 root  qmail  1054418 15 Lis 16:48 blackholedsender
Skoro wszystko działa poprawnie to możemy dodać cykliczne (np. co godzinę) uruchamianie synchronizacji z PolSpam do /etc/crontab:
$> grep qmail /etc/crontab

*  */1  *  *  *  root  (/var/qmail/bin/sync_web.pl 2>&1) >/dev/null

AUTORYZACJA SMTP

Wstęp Autoryzacja SMTP jest jedną z metod ochrony przed nieuprawnionym korzystaniem z bramki pocztowej. Pozwala to na regulowanie kto może wysyłać poczte przez nasz serwer pocztowy. Uzupełnia to metodę wcześniej opisaną w podrozdziale "Relaying" o dodatkowe możliwości z zastosowaniem autoryzacji użytkownika przed wysyłką poczty. Procedurę tę opisuje dokument RFC_2554. Wprowadza ona do protokołu SMTP dodatkowe polecenie "AUTH", jednak nie będę tu tego szczegółowo opisywać bowiem jest to wystarczająco prosto zaprezentowane w cytowanym dokumencie RFC_2554. Implementacja Do wykonania autoryzacji SMTP można użyć modułu qmail-smtpd-auth. Oczywiście jest on wykonany jako patch do qmail-smtpd i udostępnia nową funkcjonalność autoryzacji SMTP. Mozna także przygotować zmodyfikowany moduł cmd5checkpw pozwalający dodatkowo na autoryzację hasłami typu CRAM-MD5 o ile potrzebujemy tego typu autoryzacji oprócz LOGIN czy PLAIN. Konieczne jest wtedy także założenie dodatkowej bazy użytkowników z odpowiadającymi im hasłami. Postępowanie przy paczowaniu qmaila jest analogiczne jak w przypadku SpamControl. Należy także zmodyfikować skrypt startujący odbiór poczty "reciving.sh" poprzez dodanie dodatkowo wywołania /bin/checkpassword analogicznie jak w skrypcie pop3d.rc uruchamiającym usługę pop3 z autoryzacją. Wymuszenie autoryzacji W celu wymuszenia autoryzacji klienta przed zaakceptowaniem przyjmowania od niego przesyłek, można wykorzystać dodatkowy moduł qmail-smtpd-requireauth, który nakładamy na źródła qmail'a po wcześniejszym zapaczowaniu modułem qmail-smtpd-auth. Moduł ten sprawdza ustawienie zmiennej środowiskowej REQUIREAUTH w regułkach tcpserver'a oraz na tej podstawie decyduje czy przyjąć pocztę od klienta _bez_ czy wyłącznie _po_ wykonaniu wcześniejszej poprawnej autoryzacji. Szczególnie jest to przydatne gdy udostępniamy konta dial-up'owe i chcemy przyjmować (relay) pocztę do dalszej wysyłki z adresów tej wdzwanianki, jednak dopiero gdy użytkownik się zautoryzuje. Zabezpiecza to przed nieuprawnionym wykorzystaniem otwartego dla tej wdzwanianki relay'a do nadużyć. Informacje dodatkowe Autoryzacja SMTPD odbywa sie przy aktywnym współudziale zarówno serwera poczty jak i klienta poczty. Różne serwery pocztowe wspierają różne rodzaje autoryzacji po stronie serwera SMTP. Odpowiednio oprogramowanie klienckie musi posługiwać się tą samą metodą autoryzacji po stronie klienta co serwer pocztowy do którego wykonywane jest autoryzowane połączenie.

OCHRONA ANTYWIRUSOWA

Qmail Scanner W celu uruchomienia ochrony antywirusowej na bramce pocztowej (qmail) można zastosować rozwiązanie polegające na podmianie wywołania w qmail'u podprogramu obsługującego kolejke pocztową (qmail-queue) na qmail-scanner-queue.pl. Qmail-Scanner jest napisany w perl'u przez Jason'a Haar'a. Eleganckim rozwiązaniem jest patch Bruce Guenter'a QMAILQUEUE. Dzięki niemu qmail-send otrzymuje dodatkową funkcjonalność - rozpoznawanie zmiennej środowiskowej QMAILQUEUE. Zmienna ta powinna zawierać pełna ścieżkę z nazwą programu obsługującego kolejkę. Możemy ją ustawiać w zależności od potrzeb przy pomocy tcpserver'a - np. w regułkach relayingu:
$/etc> head -2 tcp.smtp
127.:allow,RELAYCLIENT="",QMAILQUEUE="/var/qmail/bin/qmail-queue"
192.168.0.1-255:allow,RELAYCLIENT="",QMAILQUEUE="/var/qmail/bin/qmail-scanner-queue.pl"
Skrypty startujące qmail za pośrednictwem tcpserver'a odpowiednio wykorzystują ustawianie zmiennych środowiskowych - tu możemy różnicować ścieżkę do oryginalnego qmail-queue bądź do qmail-scanner-queue.pl w zależności od adresu z jakiego przychodzi połączenie. W powyższym przykładzie przy wysyłaniu poczy przez użytkowników lokalnych serwera nie będzie wykonywane skanowanie poczty, natomiast wysyłka poczty z sieci lokalnej będzie podlegać skanowaniu. Instalacja sprowadza się do nałożenia patch'a na źródła qmaila, analogicznie jak w przypadku SpamControl, kompilacji i instalacji qmaila. Poprawność implementacji zmiennej QMAILQUEUE w programie qmail-send możemy zweryfikować poleceniem:
$/var/qmail/bin> strings qmail-send | grep QMAIL
QMAILQUEUE
Przed instalacją warto zainstalować narzędzie napisane przez Marka SImpson'a (tnef) służące do rozpakowywania poczty wysyłanej w outlookowym formacie Microsoft's Transport Neutral Encapsulaton Format (oczywiście dostępne w portach). W przykładowej instalacji zdecydowałem sie nie rozpakowywać załączników pocztowych oraz nie używać zewnętrznego skanera antywirusowego. Wykorzystana jest w tym przypadku jedynie funkcjonalność blokowania poczty z potencjalnie niebezpiecznymi załącznikami. Przykładowa instalacja Qmail-Scanner'a odbywa się następująco:
$~> tar -zxvf qmail-scanner-1.20rc3.tgz && cd qmail-scanner-1.20rc3
$~/qmail-scanner-1.20rc3> ./configure --spooldir /home/qmail/qmailscan \
--admin antiviradmin --notify "sender,admin" --lang "en_PL" --scanners "none" \
--unzip no --log-details yes --bindir /var/qmail/bin

Building Qmail-Scanner 1.20rc3...

This script will search your system for the virus scanners it knows
about, and will ensure that all external programs
qmail-scanner-queue.pl uses are explicitly pathed for performance
reasons.


It will then generate qmail-scanner-queue.pl - it is up to you to install it
correctly.

Continue? ([Y]/N)y

/usr/bin/uudecode works as expected on system...

Found tnef on your system! That means we'll be able to decode stupid
M$ attachments :-)

The following binaries and scanners were found on your system:

mimeunpacker=/usr/local/bin/reformime
uudecode=/usr/bin/uudecode
unzip=/usr/local/bin/unzip
tnef=/usr/local/bin/tnef

Content/Virus Scanners installed on your System

Qmail-Scanner details.

log-details=mailstats.csv
fix-mime=1
debug=1
notify=sender
redundant-scanning=no
virus-admin=antiviradmin@maszyna.gdzies.w.pl
local-domains='maszyna.gdzies.w.pl'
silent-viruses='klez','bugbear','hybris','yaha','braid','nimda','tanatos','sobig
','winevar','palyh','fizzer'
scanners=

If that looks correct, I will now generate qmail-scanner-queue.pl
for your system...

Continue? ([Y]/N)y

Finished. Please read README(.html) and then go over the script to
check paths/etc, and then install as you see fit.

Remember to copy quarantine-attachments.txt to /home/qmail/qmailscan and then
run "qmail-scanner-queue.pl -g" to generate DB version.


########################################################################
##
#

NOTE: No content/virus scanner was found on your system - so only the
internal perlscaner will be available for you to use.

Hope that's what you expected :-)

#
##
########################################################################



       ****** FINAL TEST ******

Please log into an unpriviledged account and run
/var/qmail/bin/qmail-scanner-queue.pl -g

If you see the error "Can't do setuid", or "Permission denied", then
refer to the FAQ.

(e.g.  "setuidgid qmaild /var/qmail/bin/qmail-scanner-queue.pl -g")


That's it! To report success:

% (echo 'First M. Last'; cat SYSDEF)|mail jhaar-s4vstats@crom.trimble.co.nz
Replace First M. Last with your name.
W tym miejscu zdecydowałem, iż najlepiej będzie kontynuowac dalszą instalację ręcznie. Założyłem w systemie uzytkownika (i grupę) na którym będzie wykonywany qmail-scanner-queue.pl. Utworzyłem katalog w którym odbywa się cały proces skanowania oraz gdzie znajdują się pliki konfiguracyjne. Wszystko to opisuje ta strona z dokumentacji. Należy stworzyć odpowiednią strukturę katalogów, nadac im właściwe prawa dla użytkownika (i grupy) na którym będzie uruchamiany qmail-scanner-queue.pl, stworzyć alias pocztowy antiviradmin do którego będą kierowane maile z informacjami o przechwyconych wirusach. Z uwagi na dziwne zachowanie qmail-scanner-queue.pl polegające na pomijaniu sprawdzania niektórych maili postanowiłem zbadać sprawę. Okazało się że nie zawsze jest wywoływany qmail-scanner-queue.pl a czasem qmail-queue co może wynikać z mojej nietypowej konfiguracji z anti-spam'em i innymi modułami. Postanowiłem podmienić ręcznie odpowiednie pliki i tak:
qmail-queue -> qmail-scanner-queue.pl
qmail-queue-orig
qmail-scanner-queue.pl
W qmail-scanner-queue.pl ręcznie (lub poprzez odpowiednie wywołanie w confugure) zmodyfikowałem wskazanie z qmail-queue na binarkę qmail-queue-orig która powstała poprzez zmianę nazwy oryginalnej qmail'owej qmail-queue. Takie ustawienie definitywnie rozwiązało problem. Po udanych testach i sprawnym działaniu ostateczna wersja konfiguracji qmail-scanner'a przyjęła postac skryptu jak na poniższym listingu:
#!/bin/sh
echo Przygotowanie qmail-scanner-queue.pl ...
#
./configure --spooldir /home/qmail/qmailscan \
--admin qscan --notify "sender,admin" --lang "en_PL" --scanners "clamscan" \
--unzip no --log-details yes --bindir /var/qmail/bin \
--skip-text-msgs no --no-QQ-check --debug no \
--qmail-queue-binary /var/qmail/bin/qmail-queue-orig
#
echo Kopiowanie do /var/qmail/bin/ ...
cp qmail-scanner-queue.pl /var/qmail/bin/
Podstawowym plikiem konfiguracyjnym sterującym działaniem skanera jest quarantine-attachments.txt Po każdej wykonanej zmianie w zawartości pliku należy wykonać aktualizację bazy poleceniem:
$>/var/qmail/bin/qmail-scanner-queue.pl -g
perlscanner: generate new DB file from /home/qmail/qmailscan/quarantine-attachments.txt
perlscanner: total of 42 entries.
Przykładowa zawartość tego pliku może wyglądać jak w poniższym przykładzie:
# skanowanie po temacie maila Subject:
MS.*Corporation* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
ms.*network*  Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
MS.*Net*  Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
*Microsoft*  Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
*Network.Security.* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
*Network.Critical.* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
*.Internet.Update* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
*.Internet.Pack* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
*Critical.Upgrade* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
*Critical.Patch* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim
Use.this.patch.* Virus-Subject:  Falszywy pakiet aktualizacji z koniem trojanskim

# skanowanie po znanych mime:
EICAR.COM   69 EICAR Test Virus
Happy99.exe   10000 Happy99 Trojan
zipped_files.exe  120495  W32/ExploreZip.worm.pak virus
ILOVEYOU   Virus-Subject:  Love Letter Virus/Trojan
message/partial.*  Virus-Content-Type: Message/partial MIME attachments blocked by policy
application/x-msdownload* Virus-Content-Type:     application/x-msdownload MIME attachments blocked by policy

# skanowanie po załącznikach niebezpiecznych:
# .EXE,*.COM,*.BAT,*.CMD,*.VBS,*.PL,*.BAS,*.JS,*.JAVA,
# *.REG,*.SHS,*.PIF,*.SCR,*.DLL,*.SSH,*.CHM,*.HLP,*.LNK

.vbs 0 pliki .vbs moga byc niebezpieczne i sa niedozwolone w poczcie
.lnk 0 pliki .lnk moga byc niebezpieczne i sa niedozwolone w poczcie
.scr 0 pliki .scr moga byc niebezpieczne i sa niedozwolone w poczcie
.wsh 0 pliki .vsh moga byc niebezpieczne i sa niedozwolone w poczcie
.hta 0 pliki .hta moga byc niebezpieczne i sa niedozwolone w poczcie
.pif 0 pliki .pif moga byc niebezpieczne i sa niedozwolone w poczcie
.com 0 pliki .com moga byc niebezpieczne i sa niedozwolone w poczcie
.exe 0 pliki .exe moga byc niebezpieczne i sa niedozwolone w poczcie
.bat 0 pliki .bat moga byc niebezpieczne i sa niedozwolone w poczcie
.cmd 0 pliki .cmd moga byc niebezpieczne i sa niedozwolone w poczcie
.pl 0 pliki .pl moga byc niebezpieczne i sa niedozwolone w poczcie
.bas 0 pliki .bas moga byc niebezpieczne i sa niedozwolone w poczcie
.js 0 pliki .js moga byc niebezpieczne i sa niedozwolone w poczcie
.java 0 pliki .java moga byc niebezpieczne i sa niedozwolone w poczcie
.reg 0 pliki .reg moga byc niebezpieczne i sa niedozwolone w poczcie
.shs 0 pliki .shs moga byc niebezpieczne i sa niedozwolone w poczcie
.dll 0 pliki .dll moga byc niebezpieczne i sa niedozwolone w poczcie
.ssh 0 pliki .ssh moga byc niebezpieczne i sa niedozwolone w poczcie
.chm 0 pliki .chm moga byc niebezpieczne i sa niedozwolone w poczcie
.hlp 0 pliki .hlp moga byc niebezpieczne i sa niedozwolone w poczcie
Należy pamiętać że poszczególne kolumny (pola) są oddzielane znakiem tabulacji. Po całej procedurze instalacji należy zrestartować qmail'a oraz przetestować wysyłkę poczty z serwera oraz z sieci, z załącznikami i bez, z dozwolonymi i nie. Clam Antivirus Poprawne działanie qmail-scanner'a umożliwiło dodanie pełnej kontroli antywirusowej przy użyciu darmowego Clam AntiVirus'a. Instalację najłatwiej wykonać przy użyciu port'u /usr/ports/security/clamav wykonując polecenie: cd /usr/ports/security/clamav ; make install clean Szczegółowy i oryginalny opis instalacji na FreeBSD jest dostępny tutaj. System port'ów FreeBSD znakomicie ułatwia całą procedurę. Pozostaje jedynie wykonać ręcznie polecenie: freshclam --verbose. W kolejnym kroku należy sporządzić skrypt startujący daemona freshclam (/usr/local/etc/rc.d/clamav.sh) tak aby automatycznie kilka razy na dobę aktualizował naszą bazę sygnatur wirusów:
#!/bin/sh
#
# Startup / shutdown script for Clam Antivirus
case "$1" in
start)
 /usr/local/bin/freshclam -d -c 6 -l /var/log/freshclam.log
 echo -n ' freshclam'
 ;;

stop)
 /usr/bin/killall freshclam > /dev/null 2>&1 \
 && echo -n ' freshclam'
 ;;

*)
 echo ""
 echo "Usage: ^Basename $0 { start | stop }"
 echo ""
 exit 64
 ;;
esac
Mks_Vir opracowanie w toku...
Dokumentacja jest umieszczona na stronie domowej autora qmaila http://cr.yp.to a także na stronie głównej projektu http://www.qmail.org manuale dostępne w systemie po zainstalowaniu oprogramowania. Na stronie głównej projektu jest także dostępne FAQ oraz różne dodatki do qmaila. Polecam także lekturę Life with qmail. Podziękowania dla Adama Liberackiego za cenne uwagi i korektę, Marka Zbrocha za info o requireauth i pacze do Qmail Scanner'a (obsługa Mks_Vir'a) oraz wszystkich z pl.comp.os.freebsd za "konstruktywną krytykę".

Konfiguracja szyfrowanego i kompresowanego tunelu vpn we FreeBSD na bazie vtund

© 2002-01-23 Bartłomiej Siębab ver. 1.3

WSTĘP

Czym jest vpn? VPN (virtual private network - wirtualna sieć prywatna) - to w największym uproszczeniu sieć rozciągnięta pomiędzy wieloma zdalnymi i oddalonymi sieciami LAN, przebiegająca poprzez łącza publiczne, które z natury są mało bezpieczne i nie zapewniają poufności dla przesyłanych danych. Chcąc zapewnić bezpieczeństwo przesyłanym danym stosuje się różnego rodzaju szyfrowanie i uwierzytelnianie, na bazie różnych systemów zarówno komercyjnych jak i OpenSource, opartych na różnych metodach i protokołach. Najpoważniejszym jest IPSec czy SUN Skip, czasami jednak nie ma potrzeby wytaczać armaty wielkiego kalibru na coś co można ustrzelić z procy. Z pomocą przyjdzie nam program Virtual Tunnel (vtund) dostępny pod adresem http://vtun.sourceforge.net a także w systemie paczek i portsów we FreeBSD (/usr/ports/net/vtun) czy dla innych systemów BSD czy też Linux'a. W przykładowej konfiguracji kompresja tunelu pozwoliła na łączu his/sdi (115200bit/sek - standartowo max 11KB/sek) "wycisnąć" podczas transmisji ftp pliku tekstowego ponad 32KB/sek. Oczywiście stopień kompresji zależy od samych przesyłanych zbiorów, JPG lub MP3 czy film już niewiele da się skompresować...

INSTALACJA

Instalację przeprowadzimy standardowym trybem, czyli:
$>cd /usr/ports/net/vtun
$>make install clean
Plik konfiguracyjny /usr/local/etc/vtund.conf powinien zawierać niezbędne parametry wymagane do zestawienia naszego tunelu pomiędzy dwiema sieciami. W celu przygotowania naszego środowiska systemu, niezbędne jest wykonanie konfiguracji firewalla (o ile go stosujemy). W przykładowej instalacji zestawiono tunel - szyfrowany i kompresowany - pomiędzy dwiema lokalnymi sieciami osiedlowymi (łącze SDI/HIS) po którym przebiega sieć Windows bazująca między innymi na Sambie. Specyfika tworzenia takiego tunelu wymusza ustalenie różnych klas adresów podsieci w łączonych sieciach, choć można także przy pomocy translacji adresów (natd czy ipnat) łączyć sieci o takich samych adresach, jednak nie jest to zalecane bowiem znacznie utrudnia późniejsze wykorzystanie sieci Windows itp. W przykładowej instalacji, obydwie sieci użytkują adresy 10.0.0.0/24 oraz 10.1.0.0/24. Końce zestawionego tunelu otrzymały adresy z podsieci 192.168.1.0/30. Vtund działa wykorzystując urządzenie systemowe /dev/tunX i dlatego musi być ono wkompilowane w nasz kernel (pseudo-device tun 4 # Packet tunnel). W systemie centralnym, vtund działa w trybie serwera obsługującego przychodzące połączenia. W systemach klienckich w trybie klienta łączącego się do systemu centralnego. W uproszczeniu odzwierciedla to poniższy schemat topologii:
LAN1------System Centralny------(.... WAN ....)------System klientowski------LAN2
           \                                              /
            \_________________tunel vpn__________________/
Konfiguracja translacji adresów systemów centralnego i klienckiego Musimy odpowiednio skonfigurować nasz firewall (ipfw) tak aby translacja adresów dotyczyła wyłącznie ruchu kierowanego w świat a nie do naszej wirtualnej sieci. Można to zlecić samemu vtund poprzez odpowiednie wpisy w jego konfiguracji, jednak tutaj wykonane to zostało w /etc/rc.firewall. Niezbędna jest modyfikacja regułek analogiczna do niżej przedstawionej (/etc/rc.firewall sekcja simple):
case ${natd_enable} in
[Yy][Ee][Ss])
if [ -n "${natd_interface}" ]; then

#wyłączamy standartowy tryb translacji wszystkiego
#${fwcmd} add divert natd all from any to any via ${natd_interface}

#będziemy maskować tylko ruch w świat
${fwcmd} add divert natd all from ${inet}:${imask} to any via ${natd_interface}
${fwcmd} add divert natd all from any to ${oip} via ${natd_interface}
fi
;;
esac
Konfiguracja firewall'a w systemie centralnym W celu przepuszczania ruchu pakietów pomiędzy naszymi systemami, w tym nawiązania połączenia systemów klienckich do naszego systemu centralnego (na port 5000) dodajemy poniższe regułki. W uproszczeniu, abstrachując od konkretnego przypadku, otrzymają one postać:
# Stop spoofing
# ...

# vpn połączenie klienta do serwera na port 5000
# tu należy wstawić publiczny adres IP systemu klienckiego
${fwcmd} add pass tcp from ${ipzdalnegohisa} to ${oip} 5000

# cały ruch pomiędzy sieciami LAN1 i LAN2 po interfejsie tunelu
${fwcmd} add pass ip from any to any via tun1

# Stop RFC1918 nets on the outside interface
# ...
Konfiguracja firewall'a w systemie klienckim W celu przepuszczania ruchu pakietów pomiędzy naszymi systemami dodajemy poniższe regułki. W uproszczeniu, abstrachując od konkretnego przypadku, otrzymają one postać:
# Stop spoofing
# ...

# cały ruch pomiędzy sieciami LAN1 i LAN2 po interfejsie tunelu
${fwcmd} add pass ip from any to any via tun1

# Stop RFC1918 nets on the outside interface
# ...
Konfiguracja vtund w systemie centralnym W pliku konfiguracyjnym vtund (/usr/local/etc/vtund.conf) umieszczamy poniższą konfigurację:
options {
# Przyjmowanie połączenia na porcie 5000
port 5000;

# Syslog facility
syslog        daemon;

# Scieżki do programów
ifconfig      /sbin/ifconfig;
route         /sbin/route;
}

# Domyślne parametry sesji
default {
compress yes;         # Włączenie kompresji
speed 0;              # Przepustowość maksymalna bez limitowania
}
# vpn do systemu klienckiego
vpn1 {
pass  mojetajnehaslo; # Password
type  tun;            # IP tunnel
proto tcp;            # TCP protocol
comp  zlib:9;         # LZO compression level 9
encr  yes;            # Encryption
keepalive yes;        # Keep connection alive
stat  yes;            # statistics in /var/log/vtund/

# co zrobić przy zestawieniu łącza
up {
   # Connection is Up
   # 192.168.1.1 - local, 192.168.1.2 - remote
   ifconfig "%% 192.168.1.1 192.168.1.2 netmask 255.255.255.252 mtu 1450";
   route "add -net 10.0.0.1/24 192.168.1.2";
};
# co zrobić przy zrzuceniu łącza
down {
   # Connection is down
   # 192.168.1.1 - local, 192.168.1.2 - remote
   ifconfig "%% down";
   ifconfig "%% delete";
   route "delete -net 10.0.0.0/24";
};
}
Konfiguracja vtund w systemie klienckim W pliku konfiguracyjnym vtund (/usr/local/etc/vtund.conf) umieszczamy poniższą konfigurację:
options {
# Przyjmowanie połączenia na porcie 5000
port 5000;

# Syslog facility
syslog        daemon;

# Scieżki do programów
ifconfig      /sbin/ifconfig;
route         /sbin/route;
}

# Domyślne parametry sesji
default {
compress yes;         # Włączenie kompresji
speed 0;              # Przepustowość maksymalna bez limitowania
}

# vpn do systemu klienckiego
vpn1 {
pass  mojetajnehaslo; # Password
type  tun;            # IP tunnel
proto tcp;            # TCP protocol
comp  zlib:9;         # LZO compression level 9
encr  yes;            # Encryption
keepalive yes;        # Keep connection alive
stat  yes;            # statistics

# co zrobić przy zestawieniu łącza
up {
   # Connection is Up
   # 192.168.1.2 - local, 192.168.1.1 - remote
   ifconfig "%% 192.168.1.2 192.168.1.1 netmask 255.255.255.252 mtu 1450";
   route "add -net 10.1.0.1/24 192.168.1.1";
};

# co zrobić przy zrzuceniu łącza
down {
   # Connection is down
   # 192.168.1.2 - local, 192.168.1.1 - remote
   ifconfig "%% down";
   ifconfig "%% delete";
   route "delete -net 10.1.0.0/24";
};
}
Uruchomienie vtund w systemie centralnym W systemie centralnym, vtund musi działać w trybie serwera i dlatego należy go uruchamiać w sposób typowy dla samodzielnych daemonów np. z /usr/local/etc/rc.d/ przykładowo:
$/usr/local/etc/rc.d>ls -l vpn*
-rwxr-x---  1 root  wheel  206 16 Sty 11:48 vpn-server.sh

$/usr/local/etc/rc.d>cat vpn-server.sh
#!/bin/sh
vpn=/usr/local/sbin/vtund

# start
if [ "x$1" = "x" -o "x$1" = "xstart" ]; then
   if [ -f $vpn ]; then
           echo -n ' vpn'
           $vpn -s vpn1
   fi
# stop
elif [ "x$1" = "xstop" ]; then
   killall vtund
fi
Uruchomienie vtund w systemie klienckim W systemie klienckim, vtund musi działać w trybie klienta nawiązującego i uprzymującego połączenie z systemem centralnym. Należy go uruchamiać w sposób typowy dla samodzielnych daemonów np. z /usr/local/etc/rc.d/ przykładowo:
$/usr/local/etc/rc.d>ls -l vpn*
-rwxr-x---  1 root  wheel  322 Jan 16 11:49 vpn-client.sh

$/usr/local/etc/rc.d>cat vpn-client.sh
#!/bin/sh
vpn=/usr/local/sbin/vtund

# start
if [ "x$1" = "x" -o "x$1" = "xstart" ]; then
   if [ -f $vpn ]; then
           echo -n ' vpn'
# tu należy wstawić publiczny adres IP systemu centralnego
$vpn -p vpn1 ${iphisacentralnego}
   fi

# stop
elif [ "x$1" = "xstop" ]; then
   killall vtund
fi
"5, 4, 3, ..." Odpalamy! Czas to wszystko uruchomić, bądź "z palca", bądź poprzez restart systemów. Testowo można "popingować" przeciwległe końce tunelu oraz hosty w zdalnej sieci. Jeśli wszystko działa jak należy, możemy się zabrać za szlifowanie regułek firewalli, rzeźbienie sieci Windows i Samby (jeden wspólny serwer wins niezbędny). Nie jest prostym zadaniem poprawne "wyrzeźbienie" regułek tak aby wszystko działało idealnie w konkretnym środowisku, stąd proponuję rozpocząć od cytowanych ustawień firewalla. Z pewnością napotkacie specyficzne problemy nad którymi przyjdzie wam spędzić wiele czasu ;-)
Dokumentacja jest umieszczona na stronie domowej Virtual Tunnel (vtund) http://vtun.sourceforge.net manuale dostępne w systemie po zainstalowaniu oprogramowania (man vtund). Na stronie domowej projektu jest także dostępne FAQ oraz archiwum grupy dyskusyjnej.