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ą:
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
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ę:
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 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.
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
.
Zakres numerów portów jest podzielony na porty [RFC6335]:
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
.
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
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
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]
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.
Powszechnie do zapewnienia poufności i integralności komunikacji używa się protokołów (D)TLS.
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>
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.)
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
.
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
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ść).
Poglądowe minimalistyczne komendy i komunikaty potrzebne do wysłania i odebrania wiadomości e-mail.
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'>
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