|
wersja 0.9 |
|
Spis treści |
Wstęp. 1) Instalacja 2) defaults 3) service a) INTERNAL b) RPC c) ZWYKŁE Posłowie |
| Wstęp |
Na początek krótkie przypomnienie... Serwery różnych usług są uruchamiane pod Linuxem na dwa sposoby. Pierwszym z nich jest praca jako "demon": oznacza to, że serwer pracuje w systemie cały czas - bez względu na fakt, czy ma klienta do obsłużenia. Plusem takiej pracy jest to, że klient, który coś chce, nie musi czekać, aż serwer zostanie uruchomiony, przeczyta swoje pliki konfiguracyjne, wypije piwo i dopiero zacznie kontaktować. Minusem są oczywiście zajmowane cały czas zasoby systemowe (procek, pamięć itp.). Bardzo często jako demony pracują takie usługi jak serwer www (Apache), serwer smb (Samba) czy serwer baz danych (MySQL) czyli takie, które co chwilę obsługują klientów. Istnieją jednak usługi, które uruchamiane są stosunkowo rzadko i nie ma sensu, żeby cały czas siedziały w pamięci. Przykładami najczęściej spotykanymi są telnet, ftp czy pop3. Ważne jest także to, że gotowość do pracy osiągają bardzo szybko od chwili pojawienia się żądania. Skoro jednak są one wyłączone, to skąd mają wiedzieć, że ktoś chce coś od nich? Ano stąd, że zamiast tych kilku(nastu) usług działa jedna a na imię jej inetd - Internet "super server" daemon. To czy demon ten jest super, jest kwestią gustu, ważne jest to, że nasłuchuje on na odpowiednich portach i gdy przychodzi żądanie jakiejś usługi dopiero inetd ją uruchamia. W skrócie: zamiast n demonów w pamięci działa sobie inetd, który odbiera połączenie od klienta, uruchamia odpowiednią usługę a następnie do niej przekazuje klienta. Gdy ten kończy działanie, po prostu przestaje działać. Uruchamia go znowu inetd gdy zgłasza się kolejny klient. Ponieważ wstęp, który czytasz robi się zbyt długi i nudny, a pewnie i tak wiesz o co chodzi, przejdę do rzeczy. Aaa.. plikiem konfiguracyjnym inetd jest (przeważnie) /etc/inetd.conf. Nie będę tu opisywał jego składni, bo tak zajmiemy się xinetd. A skoro już o nim wspomniałem powiem jeszcze, że uważany jest on na następcę inetd, ulepszonego inetd. Ciekawsze ulepszenia to: definiowany czas, w którym dana usługa jest dostępna, ograniczenia co do ilości uruchamianych jednocześnie usług danego typu, rozszerzone logowanie i wiele innych. |
| 1. Instalacja |
Kod źródłowy xinetd można pobrać spod adresu: www.xinetd.org Gdy powstaje ta praca, aktualną wersją jest numer 2.3.9. Czas na instalację: najpierw należy rozpakować plik a następnie wejść do katalogu z kodem źródłowym. Jeśli ktoś potrafi, może to zrobić w odwrotnej kolejności :) Następnie wydajemy polecenia: ./configure --with-libwrap make make install Opcja --with-libwrap umożliwi kontrolowanie do usług także przez pliki /etc/hosts.allow i /etc/hosts.deny i z pewnością się przyda. Polecenia "make" i "make install" odpowiednio kompilują program oraz go instalują. Oczywiście to drugie należy robić jako (mój ulubiony użytkownik) root. Jeśli masz skonfigurowany /etc/inetd.conf, który właśnie przechodzi do historii, możesz wydać polecenie: xinetd/xconv.pl < /etc/inetd.conf > /etc/xinetd.conf Na podstawie tego pierwszego zostanie wygenerowany działający plik konfiguracyjny xinetd: /etc/xinetd.conf z analogicznymi wpisami. Osobiście radzę zmienić jego nazwę na xinetd.conf.old i utworzyć go samemu od podstaw - gwarantuję, że to się opłaci i nie będziesz potem w panice szukał co znaczy która opcja. Dobra, zakładam że nie istnieje /etc/xinetd.conf. Nie ma jak to robótka ręczna :). Ostatnim etapem ku pomyślnej instalacji xinetd jest usunięcie z plików startowych systemu wywołania inetd i zastąpienie go ścieżką do xinetd. Pliki startowe są sprawą Twoją i Twojego systemu, więc wspomnę tylko, że w Slacku 8.0 jest to plik /etc/rc.d/rc.inet2. No i jeszcze bardzo ważna rzecz: xinetd znajduje się po instalacji w katalogu /usr/local/sbin/. W skrócie (znowu zamieszałem): wywalamy z plików startowych wywołanie w stylu /ścieżka/do/inetd i zamieniamy ją na /usr/local/sbin/xinetd. Jeszcze dwa słowa do ojca prowadzącego: plik xinetd.conf możemy podzielić na dwie sekcje: defaults - definiuje ona ogólną konfigurację xinetd - oraz service - ta część, a właściwie części, konfigurują odpowiednie usługi. Poloneza czas zacząć - bierzemy się za /etc/xinetd.conf. |
| 2) defaults |
Jak wspomniałem przed chwilą, sekcja defaults definiuje ogólne ustawienia demona xinetd oraz default'owe ustawienia dla poszczególnych usług. Na początek umieśćmy w xinetd.conf następującą treść: defaults { instances = 50 per_source = 5 log_type = FILE /var/log/xinetd.log 500K 600K log_on_success = HOST PID DURATION log_on_failure = HOST RECORD # To jest komentarz, linia ta nie jest brana pod uwagę # only_from = 192.168.1.2 # no_access = 192.168.1.3 # disabled = telnet # bind = 192.168.1.1 # interface = 192.168.2.1 } Na początek wystarczy... zaczynamy: instances - maksymalna liczba połączeń dla pojedyńczej usługi: określa ilu klientów (maksymalnie) pojedyncza usługa może obsługiwać "na raz". Jest to podstawa zabezpieczenia przed atakiem typu DDoS. Dopuszczalna jest również wartość UNLIMITED (bez ograniczeń). per_source - maksymalna liczba połączeń z jednego adresu IP do pojedyńczej, określonej usługi. O ile 3 połączenia np. telnetu z jednego IP są normalne, o tyle 345 takich połączeń może być próbą ataku typu DoS. Możliwa także wartość UNLIMITED (bez ograniczeń). log_type - określa sposób logowania zdarzeń związanych z dostępem do poszczególnych usług. Możliwe są dwie wartości: FILE nazwa_pliku [soft [hard]] logi z xinetd trafią do określonego pliku (zalecane) soft oraz hard definiują max. wielkość pliku z logami. Po przekroczeniu soft do sysloga (jako alert) trafia ostrzeżenie, po przekroczeniu hard xinetd przestaje logować. Domyślne wartości to 5K i 20K dlatego dobrze jest je zmienić np. na 500K i 600K. SYSLOG funkcja [poziom] gdzie funkcja to daemon | auth | authpriv | user | local0-7 a poziom to emerg | alert | crit | err | warning | notice | info | debug Domyślnym poziomem jest info, logi trafiają zgodnie ze swoją funkcją.poziomem do odpowiedniego pliku z logami. log_on_success - definiuje dane nt. klienta, które mają być zalogowane w przypadku udanego połączenia, skorzystania z usługi: HOST loguje adres IP klienta. PID loguje PID procesu - serwera, który obsłużył klienta. DURATION loguje długość trwania połączenia z serwerem. USERID loguje UID użytkownika, który łączy się z serwerem jeśli komputer klienta udostępnia "identd". Rzadko spotykane. EXIT loguje status serwera po obsłużenia klienta, najczęściej będzie to 0, więc szkoda czasu. log_on_failure - definiuje dane, jakie o kliencie korzystającym z usług należy logować w przypadku nieudanego połączenia. Czyli wówczas, gdy usługa nie może wystartować, nie pozwalają na to prawa (za dużo połączeń, nie ten IP) itp. HOST oraz USERID znaczenie takie, jak w przypadku log_on_success. ATTEMPT loguje fakt, że nastąpiła próba połączenia. Jest to automatycznie logowane także wówczas, gdy inna wartość została wpisana. RECORD zapisuje ile się da, na temat klienta. W praktyce będzie tego niewiele... only_from - określa komputery, którym można się łączyć z usługą/ami. Pozostałe hosty nie zostaną dopuszczone do niczego. Klienta wskazuje pojedynczy adres IP, ich zakres (np. 192.168.1.0/24) lub notacja kropkowa (np: .dupa.pl) no_access - określa komputery, które nie mogą łączyć się z usługą/ami. Pozostałe hosty zostają dopuszczone. Klienta wskazuje pojedynczy adres IP, ich zakres (np. 192.168.1.0/24) lub notacja kropkowa (np: .dupsko.pl) Dobra, przejdźmy o poziom wyżej. Usługi, na potrzeby xinetd, są podzielone na trzy główne grupy: INTERNAL: echo, time, daytime, chargen, discard są obsługiwane wewnętrznie, bez udziału konkretnych programów - serwerów. Normalnie i tak nie są używane... ZWYKŁE: telnet, ftp, finger itd. to zwykłe programy, które posiadają konkretny program - serwer obsługujący klienta. To nimi głównie będziemy się zajmować. RPC: rstatd, rquotad, rusersd, mountd itd. można powiedzieć, że są to "inne" programy, wykorzystywane raczej w większych sieciach. Ich zestawienie znajduje się w pliku /etc/rpc. O ile konkretna usługa nie jest jawnie zdefiniowana w /etc/xinetd.conf, nie jest ona udostępniona klientom. Czyli całkiem sensowne - to czego nie ma w pliku, nie ma dla klientów. Gdy jednak dana usługa jest udostępniona, a my chcemy (np. na chwilę) wyłączyć usługę, wystarczy, że w sekcji defaults dopiszemy: disabled = telnet Oczywiście po przeładowaniu xinetd usługa przestanie być dostępna. Dopóki nie usuniemy tej linijki. Kolejnym zastosowaniem disabled jest możliwość zrobienia wrażenia na kolegach. Czyli usługi których i tak nie mamy zdefiniowanych, czyli udostępnionych, wrzucamy do sekcji defaults: # INTERNAL disabled = echo, time, daytime, chargen, discard # RPC disabled = rstatd, rquotad, rusersd, mountd Yeahhh... To robi wrażenie. I jest dobre dla tych, którzy nie wierzą, że usługa niezdefiniowana nie jest udostępniona. Na zakończenie sekcji default ciekawy parametr. Nazywa się on bind (jego synonimem jest interface) i znajduje zastosowanie wówczas, gdy komputer pełni funkcje bramki, routera, ma połączenie z kilkoma sieciami. Umieszczony w sekcji defaults pozwala określić, dla której karty sieciowej (konkretnie: adresu IP) są zdefiniowane usługi. Inaczej: pozwala na udostępnienie usług dla wybranych (nie dla wszystkich) sieci. Przykład: komputer z SDI i siecią LAN chce udostępnić swoje usługi tylko sieci lokalnej. Wówczas, zakładając że lokalny IP to 192.168.1.1, wpis: interface = 192.168.1.1 lub równoważny jemu bind = 192.168.1.1 spowoduje, że usługi dostępne będą tylko dla sieci lokalnej a nie bydła z Inetu. Prawdę mówiąc parametr ten zaczyna nabierać większego sensu, gdy jest używany dla poszczególnych usług a nie dla wszystkich, ale o tym zaraz. Podsumowanie: ta część była omówieniem sekcji defaults pliku xinetd.conf. Zdefiniowane tam rzeczy dotyczą ogólnie wszystkich udostępnionych przez xinetd usług. Parametry te nadpisane mogą zostać, unieważniając te w sekcji defaults, przez analogiczne wpisy w części poświeconej konkretnym usługom. Tak więc...jedziemy dalej! |
| 3) service |
Czas na omówienie konfiguracji poszczególnych usług. Ponieważ sprawy trochę się w tym miejscu komplikują, pozwoliłem sobie jeszcze raz podzilić usługi na trzy grupy: INTERNAL, ZWYKŁE, RPC. Oczywiście nacisk zostanie położony na sekcję ZWYKŁE. a) INTERNAL Jak wcześniej wspomniałem są to: echo, time, daytime, chargen oraz discard. Co więcej, prawdopodobnie nigdy nie będziesz chciał ich uruchomić. Tutaj zostaną one opisane jako wprowadzenie do zwykłych usług. Jeśli spojrzysz do pliku /etc/services przekonasz się, że ww. usługi działają zarówno z protokołem UDP jak i TCP. Do naszych celów użyjemy usługi echo: działa ona w ten sposób, że odsyła do klienta wszystko to, co klient wysłał do niej. Może niewiele polotu jest w tej usłudze, ale kiedyś wykorzystywana ona była do sprawdzania, czy w sieci nie ma przekłamań, czy stan połączenia jest dobry :) Jakiś czas potem znalazła inne zastosowanie: była wykorzystywana do ataków na serwery wraz z usługą chargen Wracamy do echo. Aby zaczęła ona funkcjonować, wystarczy do xinetd.conf, po sekcji defaults umieścić taki wpis: service echo { # id = echo-tcp type = INTERNAL user = root socket_type = stream wait = no # disable = no } Dobra, sprawy wyglądają tak: service type - typ usługi, najczęściej stosowane to INTERNAL i RPC user - użytkownik, z którego przywilejami będzie wykonywana usługa. (użytkownik ten musi istnieć w /etc/passwd). socket_type - typ socketu, najczęściej używane to stream (dla TCP) oraz dgram (dla UDP). wait - wartość logiczna (yes - no), określa czy usługa potrafi obsługiwać kilku użytkowników na raz. W zdecydowanej wiekszości będzie ustawiona na no, co oznacza (dla zmyłki :), że potrafi, nie musi czekać aż inna jej kopia skończy obsługiwać swojego klienta. Po przeładowaniu xinetd czas sprawdzić, czy usługa działa: - wydaj polecenie netstat -a | more i zobacz czy jest tam echo (powinno być) - wydaj polecenie telnet localhost 7 (7 to nr portu echo) i pobaw się trochę. Jeśli działa - idziemy dalej, jeśli nie - spójrz w logi (pewnie zrobiłeś literówkę lub nie przeładowałeś xinetd). Jeśli chcesz udostępnić echo także dla UDP, dopisujesz do xinetd.conf to samo (tylko niżej), zmieniając stream na dgram. Sprawdź netstatem, czy jest git. Dobra. Mamy udostępnione echo dla TCP i UDP. Jeśli chcesz czasowo wyłączyć któreś z nich, w części dotyczącej odpowiedniej usługi dopisujesz: disable = yes Po przeładowaniu xinetd usługa przestanie być dostępna. Dobra - powiesz - w sekcji default napisałeś, że aby wyłączyć wybraną usługę nie trzeba jej szukać i wpisywać tam disable. Ponoć wystarczy w sekcji defaults wpisać disabled = nazwa_usługi. Jak to w końcu jest ? Ano jest i tak i tak. Tyle że udostępniając dwie usługi echo (na TCP i na UDP), po wpisaniu disabled = echo w części defaults spowodujesz, że ani jedna ani druga nie będzie dostępna. Jeśli chcesz usunąć tylko jedną, z dwóch o tej samej nazwie możesz: albo napisać w odpowiednim miejscu disable = yes albo... Drugą możliwością jest nadanie dodatkowej nazwy każdej usłudze. W tym przypadku byłoby to odpowiednio (w sekcjach service): id = echo-tcp oraz id = echo-udp w drugiej części. Wówczas w sekcji defaults można napisać np. disabled = echo-tcp i w ten sposób wyłączyć jedną z dwóch o tej samej nazwie. Dobra, pozostałe usługi typu INTERNAL: time, daytime, chargen, discard konfiguruje się identycznie, zmieniając tylko nazwe usługi (ew. także jej id). Jako ciekawostę dodam, że w sekcji service, dla poszczególnych usług możesz definiować komputery które mają do nich dostęp - przy pomocy opcji only_from oraz no_access identycznie, jak w sekcji defaults. Jak zapewne się domyślasz, dostęp ten będzie dotyczył tylko konkretnej usługi. Dobra, tyle na temat usług INTERNAL. Choć nie będziesz ich używał (a może ?), zapoznałeś się z podstawową składnią części service definiującej poszczególne usługi. Dla zwykłych usług zasada działania jest bardzo podobna, tyle że dochodzi trochę więcej parametrów... b) RPC Tutaj sprawę załatwię krótko: w chwili obecnej (wersja 2.3.9) xinetd nie jest zalecany do kontrolowania usług typu RPC. Nawet autor xinetda proponuje używać starego, dobrego inetda do tych celów. Wszędzie, czytając na temat xinetd spotykałem wzmianki w stylu "poor support", "isn't great" itp. Nie pozostaje mi nic innego, jak odłożyć kontrolowanie usług RPC na jakiś czas. Oczywiście trudno powiedzieć, ile to może potrwać. c) ZWYKŁE W tym miejscu zaczynam najważniejszą część pracy. Spróbuję opisać typowe zastosowanie xinetd oraz całe dobrodziejstwo inwentarza, które z sobą wnosi. Na początek konfiguracja podstawowa. Konfigurje ona dostęp do serwera FTP (tutaj: ProFTPD). Nie wnosi ona nic, czego nie ma inetd... service ftp { flags = NAMEINARGS socket_type = stream protocol = tcp wait = no user = root server = /usr/sbin/tcpd server_args = /usr/local/sbin/proftpd disable = no } Można powiedzieć, że wpis ten niewiele się różni od pliku inetd.conf. Takie rzeczy jak socket_type, protocol, wait, user nie wymagają wyjaśnienia i dla większości usług będą wyglądały identycznie. Pole flags może posiadać wiele wartości (vide: man xinetd.conf), jednak najczęściej (90%) będzie stosowane NAMEINARGS. Oznacza to, że w polu server definiuje się pomocniczy, dodatkowy program potrzebny do prawidłowego działania serwera a dopiero w polu serwer_args definiuje się właściwy serwer. Teraz powoli: xinetd (z ./configure --with-libwrap) domyślnie sprawdza pliki hosts.allow oraz hosts.deny czy klientowi należy się dostęp do usługi. Niektóre usługi mogą jednak się nie uruchomić lub nie działać prawidłowo, jeśli nie wywoła się przed nimi tcpd. Dlatego też zaleca się większość usług konfigurować przy pomocy takiej składni: flags = NAMEINARGS ... ... ... server = /ścieżka/do/tcpd server_args = /ścieżka/do/właściwego/serwera Innym wskazaniem server może być np. /ścieżka/do/chroot jeśli któraś z naszych usług jest chrootowana. Innym wskazaniem flags może być NOLIBWRAP i wówczas pliki hosts.access i hosts.deny nie są sprawdzane (wówczas server powinien bezpośrednio wskazywać serwer usługi). Każdą usługę należy sprawdzić: czy działa i czy działa prawidłowo. Na przykład niektóre usługi mogą być wywołane bezpośrednio: bez pola flags, server_args oraz z server wskazującym bezpośrednio na serwer usługi. Opcja disable mówi, że usługa jest dostępna. W inetd.conf wpisywało się # przed wyłączoną usługą, w xinetd.conf należy wpisać disable = yes aby daną usługę wyłączyć (lub disabled = ftp w części defaults). Na koniec dodam rzecz oczywistą: wpis proftpd: 192.168.1.2 w pliku hosts.deny uniemożliwi wskazanemu komputerowi dostęp do serwera FTP. Teraz wersja exclusive pliku xinetd.conf, która pokazuje bajery jakie wnosi xinetd. Jako przykład posłuży serwer TELNET (in.telnetd). service telnet { flags = NAMEINARGS socket_type = stream protocol = tcp wait = no user = root server = /usr/sbin/tcpd server_args = /usr/sbin/in.telnetd disable = no # tu się zaczyna: instances = 30 per_source = 3 interface = 192.168.2.1 only_from = 192.168.2.2 # no_access = 192.168.2.5 access_times = 8:00-16:00 banner = /etc/xinetd/baner.txt banner_fail = /etc/xinetd/baner_syf.txt banner_success = /etc/xinetd/baner_ok.txt cps = 3 20 nice = 15 } Okej, widzimy te same opcje, co w sekcji defaults. Co to znaczy ? To znaczy, że wartości tych samych parametrów w sekcji danej usługi (tutaj: telnet) "nadpisują" wartości sekcji defaults. Przykładowo w defaults mamy per_source = 5 a tutaj per_source = 3. Oznacza to, że z serwerem telnetu może połączyć się maksymalnie trzech klientów z jednego adresu IP. Czyli kolega może pracować na naszym kompie w maksymalnie trzech okienkach. Przedstawione tu opcje oznaczają dokładnie to samo, co w sekcji defaults a także nadpisują tamte. Hmmm....pojawił się access_times - zdziwiony ? Definiuje on godziny, w których dana usługa jest dostępna. Zakres dla godzin to 0-23, dla minut natomiast 0-59. Jak pewnie się domyślasz, istnieje też parametr o nazwie deny_time. Teraz czas na banner...: definiuje on plik tekstowy, który zostanie wyświetlony, gdy: banner - klient połączy się z usługą (bez względu na to, czy z powodzeniem). banner_fail - klient połączy się z usługą ale nie zostanie do niej dopuszczony. banner_success - klient połączy się z usługą i ma prawa do korzystania z niej. Teksty te można wykorzystać aby użytkowników przywitać podając nazwę serwera (banner), udzielając wskazówek (banner_success) lub odstraszając (banner_fail). Wszystko zależy od Ciebie, adminie... Jedziemy dalej: cps - pobiera dwa argumenty. Pierwszym z nich, tym ważniejszym, jest maksymalna ilość połączeń jaką w ciągu sekundy serwer ma obsłużyć. Oznacza to, że w ciągu sekundy nie może być otworzonych więcej sesji, niż określa to pierwszy argument (w przykładzie: 3). Oczywiście usługa będzie obsługiwać więcej klientów na raz (zależy od instances oraz per_source) ale w ciągu sekundy więcej niż ten parametr klientów nie może na raz nawiązać połączenia. Jeśli się tak zdarzy, usługa jest zawieszana na drugi parametr (tu: 20) sekund zanim znowu będzie dostępna. Dobre zabezpieczenie przed programami typu "port fucker". Kolejnym parametrem jest nice. Określa on priorytet, z jakim usługa będzie wykonywana. Normalnie programy uruchamine są z priorytetem równym 10, maksymalna liczba = 20 mówi "olej tą usługę, jak nie masz co robić, to się nią zajmij" więc przypisanie tutaj wartości 15 trochę zlewa telnet. Więcej informacji na temat nice dostępne jest jako "man nice" w Twoim systemie. Uważaj, żeby nie przesadzić.. Teraz przedstawię jeszcze jedną możliwość xinetd: ciekawą i niebezpieczną. service ftp { socket_type = stream protocol = tcp wait = no user = root redirect = 192.168.2.5 21 } Choć to wszystko wygląda biednie, kryje coś niespotykanego: redirect. Argumentami są adres IP (lub nazwa komputera) i numer portu. Pewnie się domyśliłeś, że chodzi tu o przekierowanie portu twojego serwera na inny komputer. Cała siła xinetd polega na tym, że komputer docelowy może schowany być za maskaradą(NAT) w Twojej sieci. Jest to potężna i niebezpieczna możliwość xinetd. Na koniec przedstawię udostępnienie SSH przez xinetd. Należy zwrócić uwagę na dwie rzeczy: 1. portu, na którym działa serwer (22) nie ma w /etc/services 2. sshd wymaga opcji -i, gdy jest wywoływany z inetd. Plus tego rozwiązania jest taki, że wszystkie opcje odnośnie dostępu do SSH na naszym kompie można uwzględnić także tutaj... service ssh { socket_type = stream wait = no user = root server = /usr/local/sbin/sshd port = 22 server_args = -i } Powinieneś wszystko już wiedzieć.... Przypomnę jeszcze, że w sekcji services, dla poszczególnych usług można definiować przy pomocy bind interfejs, kartę sieciową na której dana usługa nadsłuchuje (sprawdza się, gdy mamy np. modem i SDI). Zachęcam także do zapoznania się z "man xinetd.conf", nie tylko w przypadku problemów... |
| Posłowie |
Jest to pierwsza wersja tego dokumentu i zawiera pewnie jakieś błędy/niedoróbki/potknięcia itp. Będę bardzo wdzięczny za wszelkie uwagi, komentarze, poprawki, wyrazy wdzięczności. Z góry przepraszam za powyższe i mam nadzieję, że będziecie mnie informować w których miejscach coś nie gra. Jako (częściowe) wytłumaczenie przedstawiam fakt, że większość tej pracy powstawała w późnych godzinach nocnych. Ostatnia wersja tego dokumentu znajduje się pod niżej wymienionym adresem. Kontakt ze mną: linio@terramail.pl Wesprzyj finansowo autora - kliknij tutaj |
|
=============================== Henryk Liniowski, Poznań 2002 http://linio.terramail.pl =============================== |