Table of Contents
Warstwa transportowa
Warstwa sieci zapewnia komunikację między dowolnymi urządzeniami.
Odpowiednie pole pakietu IP wskazuje jaki protokół warstwy transportowej jest używany.
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
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, DCCP, MPTCP
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.
Klient-serwer
Programy sieciowe zwykle 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).
Program może jednocześnie pełnić rolę serwera i klienta.
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.
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
jest utrzymywana
przez organizację IANA.
W Linuksie dodatkowo taka lista jest tradycyjnie dostępna w pliku /etc/services.
Zakresy numerów portów
Zakres numerów portów jest podzielony na porty [RFC6335]:
- uprzywilejowane (system / well-known / privileged) – 1÷1023
jako lokalne porty mogą być używane tylko przez uprzywilejowanego użytkownika (root / administrator), - zarejestrowane 1) (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.
netstat {|-a|-l} [-t] [-u] [-p] [-n](np.netstat -atupn)ss {|-a|-l} [-t] [-u] [-p] [-n](np.ss -atupn)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 kolumny Więcej: netstat -h / ss -h
/proc/net/(tcp|udp|…)(np.cat /proc/net/tcp)
# 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
Testowanie łączności na warstwie aplikacji
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
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 |
Zamiast STDIO można podać - (dodatkowo w większości dystrybucji można też skorzystać z 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]
Powyżej warstwy transportowej
Rola systemu operacyjnego kończy się na zapewnieniu łączności między procesami na wskazanych urządzeniach – na warstwie transportowej. Cała reszta jest w rękach twórcy programu.
Połączenia szyfrowane
Powszechnie do zapewnienia poufności i integralności komunikacji używa się protokołów (D)TLS.
Testowanie szyfrowanych połączeń z opessl
Narzędzie openssl dostarczane z biblioteką OpenSSL
pozwala testować połączenia szyfrowane.
W najprostszej wersji nawiązanie połączenia TLS odbywa się komendą:
openssl s_client <host>:<port>
Do uruchomienia serwera potrzeby jest klucz prywatny i certyfikat (klucz
publiczny z podpisem zaufanego urzędu certyfikacji).
Na podstawie certyfikatu otrzymanego od serwera klient sprawdza czy ufa
serwerowi; jeżeli klient nie zna podpisującego certyfikat, serwer uzna za
niezaufany.
Do wygenerowania dla ćwiczeń klucza prywatnego i certyfikatu możesz użyć komendy:
openssl req -x509 -newkey rsa:1024 -days 1 -nodes -keyout key.pem -out cert.pem
W najprostszej wersji stworzenie serwera odbywa się komendą:
openssl s_server -key key.pem -cert cert.pem -accept <port>
Testowanie szyfrowanych połączeń z socat
Program socat również pozwala na nawiązanie połączeń z użyciem TLS.
W najprostszej wersji nawiązanie połączenia TLS odbywa się komendą:
socat openssl:<host>:<port> STDIO
lub, bez sprawdzania poprawności certyfikatu:
socat openssl:<host>:<port>,verify=0 STDIO
W najprostszej wersji stworzenie serwera odbywa się komendą:
socat openssl-listen:<port>,key=key.pem,cert=cert.pem,verify=0 -
(W serwerze verify=0 wyłącza wymaganie i sprawdzanie certyfikatu klienta.)
Przykładowe aplikacje
Zapytania do serwerów stron internetowych
Protokół HTTP definiuje różne metody, z których przeglądarki używają głównie GET i POST.
Wersje HTTP do 2.0 włącznie używają protokołu tekstowego.
W protokole HTTP każde żądanie (i odpowiedź) składa się z linii żądania
(statusu) i nagłówków (każdy w osobnej linii), po których następuje pusta linia
("\r\n\r\n") i, jeżeli jest, treść żądania (bądź odpowiedzi).
Długość treści żądania/odpowiedzi (jeśli jest obecna) zwykle wskazuje nagłówek
Content-Length.
Ręcznie
Treść minimalnego zapytania HTTP w wersji 1.1:
GET / HTTP/1.1 Host: <docelowa nazwa domenowa>
Np. żeby pobrać zasób
https://bip.put.poznan.pl/artykuly/status-politechniki-poznanskiej-2020-2024,
można połączyć się z szyfrowaniem TLS pod adres bip.put.poznan.pl i port 443
(domyślny dla https://) i wysłać zapytanie:
GET /artykuly/status-politechniki-poznanskiej-2020-2024 HTTP/1.0 Host: bip.put.poznan.pl
wget / curl
Narzędzia wget i curl pozwalają automatycznie wysłać żądanie HTTP.
wget domyślnie podąża za przekierowaniami i zapisuje odpowiedź do pliku.
curl domyślnie nie podąża za przekierowaniami i wypisuje odpowiedź na
standardowe wyjście.
Odpowiednimi przełącznikami można zmieniać zachowanie programów,
np. curl -v <url> wyświetli pełną treść wysłanego żądania z nagłówkami
pełną odpowiedź (a nie tylko jej treść).
[ekstra] Rozmowa z serwerem pocztowym
Poglądowe minimalistyczne komendy i komunikaty potrzebne do wysłania i odebrania wiadomości e-mail.
SMTP – wysyłanie maili
Komendy do połączenia z serwerem SMTP (do wyboru):
socat tcp:<adres_serwera>:25,crlf stdio openssl s_client -crlf -starttls smtp <adres_serwera>:25 openssl s_client -crlf <adres_serwera>:465
Kolejne linie potrzebne do wysłania maila:
helo <twoja nazwa domenowa> mail from: <nadawca> rcpt to: <odbiorca> data Date: <data we właściwym formacie - wykonaj komendę 'date --rfc-email'> From: <nadawca> To: <odbiorca> Subject: <temat> <tresc> . quit
Dodanie poniższych linii po
helo (bądź ehlo) uwierzytelni użytkownika:
auth plain <wynik komendy 'printf "\0<użytkownik>\0<hasło>" | base64'>
IMAP – odbieranie maili
Komendy do szyfrowanego połączenia z serwerem IMAP (do wyboru):
openssl s_client -crlf -starttls imap <adres_serwera>:143 openssl s_client -crlf <adres_serwera>:993
Kolejne linie do pobrania (kawałka) maila:
A login <użytkownik> <hasło> B select inbox C search unseen D fetch <id> BODY.PEEK[HEADER.FIELDS (SUBJECT DATE FROM)] QUIT