===== Klient-serwer ===== Programy sieciowe mogą pełnić rolę serwera lub klienta. Serwer to program który czeka (nasłuchuje) na nowe połączenia (lub żądania/wiadomości) od klientów. Klient to program który łączy się do serwera (lub wysyła do niego żądania/wiadomości). Program może jednocześnie pełnić rolę serwera i klienta. \\ Program używający połączeń może naraz czekać na połączenia od klientów i samemu nawiązywać połączenia do innych serwerów, jednak w każdym z połączeń program pełni rolę albo serwera, albo klienta. ===== Warstwa transportowa ===== Warstwa **sieci** zapewnia komunikację między dowolnymi **urządzeniami**. Warstwa **transportowa** zapewnia komunikację między **procesami** działającymi na wskazanych urządzeniach. Protokoły warstwy transportowej mogą: * tworzyć połączenia albo przesyłać datagramy (porównaj z połączeniami telefonicznymi i wiadomościami SMS) * przesyłać dane jako strumień bajtów albo jako wiadomości * gwarantować (lub nie) odebranie danych w tej samej kolejności w jakiej były nadane * zapewniać że dane dotrą, a w razie gdyby jakiś pakiet nie dotarł, automatycznie wysłać go ponownie * dostosowywać prędkość wysyłania do możliwości łącza Odpowiednie pole pakietu IP wskazuje jaki protokół warstwy transportowej jest używany. W internecie używa się głównie protokołów TCP i UDP. \\ Poza TCP i UDP jest w użyciu jeszcze kilka protokołów warstwy transportu, np. SCTP, UDP-Lite, DCCP, MPTCP. Są one jednak sporadycznie używane, co wynika z braku wsparcia ich przez system MS Windows, wynikającego z ich sporadycznego użycia. ==== Adresacja na warstwie transportowej ==== Protokoły warstwy transportowej spójnie używają 16-bitowej liczby jako adres. \\ Adres warstwy transportowej nazywa się **numerem portu**. System operacyjny po otrzymaniu wiadomości biorąc pod uwagę: * adresu warstwy sieci (np. IP) źródłowy (zdalny), * adresu warstwy sieci (np. IP) docelowy (lokalny), * użyty protokół warstwy transportowej, * adresu warstwy transportowej (np. port) źródłowy (zdalny), * adresu warstwy transportowej (np. port) docelowy (lokalny),
sprawdza: * czy wiadomość należy do już istniejącego połączenia (i wtedy dostarcza dane do tego połączenia), a jeśli nie, to * czy jakiś program czeka na nowe połączenie / wiadomości pod docelowym adresem IP i docelowym portem użytego protokołu warstwy transportowej. Programy pełniące rolę serwera muszą wskazać użyty protokół warstwy transportu i poinformować system operacyjny na jakich adresach IP i numerach portów oczekują połączeń/wiadomości. Program który chce połączyć lub wysłać wiadomość musi podać jaki protokół warstwy transportu ma zostać użyty i podać docelowy adres IP i docelowy numer portu dla połączenia/wiadomości. \\ Program może też wskazać z jakiego źródłowego adresu IP i źródłowego numeru portu ma zostać nawiązane połączenie lub wysłana wiadomość. Jeżeli tego nie zrobi, system operacyjny sam je wybierze. ==== Znane numery portów ==== Konkretne numery portów są zwyczajowo używane do adresowania konkretnych programów. \\ Np. port 80 i 443 jest używany przez serwery stron internetowych, a porty 25, 465 lub 587 przez serwery poczty internetowej (e-mail). Lista takich numery portów, wraz z przypisanymi do nich słownymi nazwami i informacją do czego są (albo były w przeszłości) używane [[http://www.iana.org/assignments/service-names-port-numbers|jest utrzymywana]] przez organizację IANA. W Linuksie dodatkowo taka lista jest tradycyjnie dostępna w pliku ''/etc/services''. Zwyczajowo twórcy programów pozwalają użytkownikowi używać nazw portów zamiast ich numerów oraz często wyświetlając informacje o użytych portach wyświetlają nazwy zamiast numerów (o ile dany numer portu ma nazwę). ==== Zakresy numerów portów ==== Zakres numerów portów jest podzielony na porty [[https://tools.ietf.org/html/rfc6335#section-6|[RFC6335]]]: * uprzywilejowane (system / well-known / privileged) – 1÷1023 \\ jako lokalne porty mogą być używane tylko przez uprzywilejowanego użytkownika (root / administrator), * //zarejestrowane//((czy ktoś zna jakieś lepsze tłumaczenie na polski nazwy "user ports" lub "registered ports"?)) (user / registered) – 1024÷49151 \\ mogą zostać zarejestrowane (tzn. przypisane do konkretnego zastosowania w rejestrze utrzymywanym przez IANA), * efemeryczne (dynamic / private / ephemeral) – 49152÷65535 \\ używane kiedy program nie potrzebuje stałego numeru portu (czyli zwykle kiedy program nawiązuje połączenie). W implementacjach systemów operacyjnych zwykle granica między user ports a ephemeral jest niższa, np. w Linuksie zakres portów efemerycznych można odczytać wykonując jedną z komend: ''sysctl net.ipv4.ip_local_port_range'' / ''cat /proc/sys/net/ipv4/ip_local_port_range''. ===== Monitorowanie bieżących połączeń ===== Polecenia ''netstat'' i ''ss'' wyświetlają listę połączeń (nie tylko sieciowych) których stroną jest ten komputer oraz (po podaniu odpowiedniej opcji) informacje na jakich adresach IP i portach programy na tym komputerze czekają na połączenia bądź wiadomości. \\ Pliki ''/proc/net/(tcp|udp|…)'' zawierają informacje o połączeniach w formacie przystępnym dla maszynowego przetwarzania.Wybrane przełączniki dla netstat / ss: ┌ (domyślnie) tylko już nawiązane połączenia │ -l nasłuchujące porty (programy czekające aż ktoś do nich się połączy) └ -a nasłuchujące porty + nawiązane połączenia ┌ (domyślnie) wszystkie wspierane protokoły sieciowe │ -t połączenia protokołu TCP └ -u połączenia protokołu UDP ┌ -4 wybiera IPv4 └ -6 wybiera IPv6 -p nazwa i pid programu do którego należy połączenie -n pokazywanie wszystkich wartości numerycznie, np. '22' zamiast 'ssh' -W [tylko netstat] wyłącza przycinanie adresów IP / nazw domenowych do szerokości kolumnyDodatkowo ''ss'' pozwala filtrować wyniki między innymi po adresach ip (''src'' i ''dst'') oraz numerach portów (''sport'' i ''dport''), np: \\ ''ss -t dport 443'' ''ss -aut src 127.0.0.1 or src 150.254.0.0/24'' \\ Więcej opcji znajdziesz w pomocy wbudowanej (''netstat -h'' / ''ss -h'') i podręczniku systemowym (''man netstat'' / ''man ss''). Przykładowy wynik polecenia ''netstat'':
# netstat -atunp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 13830/sshd tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 28693/exim4 tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 26745/cupsd tcp 0 780 10.0.1.1:22 150.254.33.66:38126 ESTABLISHED 19424/sshd: usernam tcp 0 0 10.0.1.1:38596 150.254.30.199:443 ESTABLISHED 19481/weechat tcp6 0 0 :::22 :::* LISTEN 13830/sshd udp 0 0 0.0.0.0:68 0.0.0.0:* 14541/dhclient udp 0 0 10.0.1.1:53 0.0.0.0:* 22173/named udp 768 0 0.0.0.0:35722 0.0.0.0:* 21533/snmpwalk==== Zadania ==== ~~Zadanie.#~~ Wyświetl wszystkie połączenia na swoim komputerze. ~~Zadanie.#~~ Wejdź w przeglądarce na stronę //%%put.poznan.pl%%// i jednocześnie wyświetl wszystkie połączenia na swoim komputerze. Jakie nowe połączenia się pojawiły? ~~Zadanie.#~~ Uruchom w terminalu polecenie ''ss -E'' (lub ''ss -nE''), a następnie wejdź w przeglądarce na wybraną wcześniej nie odwiedzaną stronę. Z jakich numerów portów korzysta wyświetlna przez ''ss'' aktywność sieciowa? ~~Zadanie.#~~ Jakie programy czekają na połączenia/wiadomości na twoim komputerze? Sprawdź czy wykonując polecenie ''netstat'' / ''ss'' z roota zamiast zwykłego użytkownika wyświetlane jest więcej informacji na ten temat. ===== Testowanie łączności ===== ==== netcat ==== ''[[https://en.wikipedia.org/wiki/Netcat|netcat]]'' (czasami dostępny jako ''nc'') to szeroko rozpowszechnione narzędzie potrafiące nawiązać proste połączenia sieciowe bądź stworzyć prosty serwer (używając protokołu TCP bądź UDP). \\ Uwaga: netcat ma wiele wersji różniących się możliwościami, przełącznikami i zachowaniem! ^ ^ Serwer ^ Klient ^ | TCP|''nc -l -p //12345//'' |''nc //10.0.0.1// //12345//'' | | UDP|''nc -u -l -p //12345//'' |''nc -u //10.0.0.1// //12345//'' | ==== socat ==== ''[[http://www.dest-unreach.org/socat/|socat]]'' to rozbudowany i wciąż rozwijany program pozwalający testować rozmaite "połączenia" sieciowe. **''socat'' zawsze przyjmuje dwie opcje** – dwa "strumienie" które ze sobą połączy, np. standardowe wejście/wyjście z połączeniem sieciowym. \\ Można też łączyć np. jedno połączenie sieciowe z drugim, czy połączenie sieciowe z programem. ^ ^ Serwer ^ Klient ^ | TCP|''socat TCP-LISTEN:12345 STDIO'' |''socat STDIO TCP:10.0.0.1:12345'' | | UDP (pseudo-połączeniowe)|''socat UDP-LISTEN:12345 STDIO'' |''socat STDIO UDP:10.0.0.1:12345'' | | UDP (zorientowane na wiadomość)|''socat UDP-RECV:12345 STDIO'' |''socat STDIO UDP-SENDTO:10.0.0.1:12345'' | | ::: |
socat UDP-DATAGRAM:10.0.0.1:12345,bind=0.0.0.0:12345 STDIO ||
''STDIO'' (zamiennie ''**-**'') oznacza standardowe wejście/wyjście. Dodatkowo
w większości dystrybucji można też skorzystać z ''readline'' opakowującej
standardowe wejście/wyjście w wygodną bibliotekę
[[https://en.wikipedia.org/wiki/GNU_Readline|readline]].
\\
Socat nie rozróżnia wielkości liter, pozwala na skróty – np.
''udp-l'' jako ''udp-listen'' czy ''tcp'' jako ''tcp-connect'' \\
Adresy IPv6 podaje się w nawiasach kwadratowych, np. [::1]
==== Zadania ====
~~Zadanie.#~~
Uruchom serwer TCP używając programu ''nc'' lub ''socat'' i nie wyłączając go
przejdź do kolejnych zadań.
~~Zadanie.#~~
Uruchom (w nowej konsoli) program ''netstat'' lub ''ss'' z opcjami które pozwolą
tobie zobaczyć informację o serwerze z poprzedniego zadania. Wśród informacji ma
pojawić się identyfikator procesu (//pid//) serwera.
~~Zadanie.#~~
Poproś osobę siedzącą obok o podłączenie się do twojego serwera, następnie
wyślijcie do siebie nawzajem kilka linii tekstu. Nie zamykajcie jeszcze
połączenia.
~~Zadanie.#~~
Ponownie uruchom program ''netstat'' lub ''ss'' tak żeby zobaczyć informację
o nawiązanym połączeniu. Jakie numery portów są wykorzystywane?
~~Zadanie.#~~
Czy możesz podłączyć dwóch klientów do jednego serwera TCP uruchomionego
poleceniami podanymi wcześniej w materiałach?
\\
Uruchom na wybranym porcie serwer TCP komedną:
''socat -dd tcp-listen:1500**,fork** shell:%%'stdbuf -o0 tr a-z A-Z'%%''
i poproś dwie osoby o podłączenie się do niego.
Następnie wyświetl programem ''netstat'' lub ''ss'' informacje o tych
połączeniach tak, żeby było widać //pid// procesu używającego połączenia.
Co obserwujesz?
~~Zadanie.#~~
Uruchom serwer TCP na wybranym (innym niż w poprzednich zadaniach) porcie
w jednym terminalu używając programu ''socat'', a następnie nie wyłączając
go spróbuj uruchomić w drugim terminalu kolejny serwer TCP programem
''socat'' na tym samym porcie. Jaki komunikat dostajesz?
~~Zadanie.#~~
Spróbuj uruchomić jako zwykły użytkownik serwer TCP na porcie z zakresu portów
systemowych. Jaki komunikat błędu jest wyświetlany?
~~Zadanie.#~~
Uruchom jako superużytkownik (''root'') serwer TCP używając programu ''nc'' lub
''socat'' na porcie 80 i podłącz się do niego z przeglądarki internetowej.
Wyślij przeglądarce odpowiedź i zamknij połączenie.
~~Zadanie.#~~
Uruchom serwer UDP w wersji zorientowanej na wiadomość używając programu
''socat'', a następnie w nowej konsoli uruchom program ''netstat'' lub ''ss'' z
opcjami które pozwolą tobie zobaczyć informację o tym serwerze.
~~Zadanie.#~~
Poproś dwie osoby siedzące obok o wysłanie wiadomości UDP do tego serwera.
Czy widzisz na ekranie wiadomość od obu osób?
~~Zadanie.#~~
Ponownie uruchom program ''netstat'' lub ''ss'' tak żeby zobaczyć informacje
o serwerze z poprzedniego zadania.
~~Zadanie.#~~
Uruchom serwer UDP w wersji pseudo-połączeniowej, a następnie wyświetl programem
''netstat'' lub ''ss'' informacje o nim.
Czy teraz widać jakąś różnicę w porównaniu do serwera w wersji zorientowanej na
wiadomość?
~~Zadanie.#~~
Poproś osobę siedzącą obok o uruchomienie klienta UDP w wersji
pseudo-połączeniowej i o wyświetlenie, przed wysłaniem pierwszej wiadomości,
informacji o tym kliencie programem ''netstat'' lub ''ss''.
Sprawdź czy zmieniło się to jak po stronie serwera ''netstat'' / ''ss''
wyświetla informacje.
\\
Następnie poproś osobę siedzącą obok o wysłanie tobie wiadomości i wykonajcie
na swoich komputerach komendę ''netstat'' lub ''ss'' wyświetlającą wszystkie
aktywności UDP. Czy serwer UDP jest prezentowany identycznie jak przed
otrzymaniem pierwszej wiadomości?
~~Zadanie.#~~
Twój komputer ma kilka adresów IPv4. Wyświetl je.
Używając komendy ''nc -l //