Wrocław University of Science and TechnologyDepartment of Fundamentals of Computer Science

Technologie sieciowe: listy zadań

Laboratorium · Polecenia, warunki eksperymentu i wyniki do oddania

Jak dokumentować eksperyment

Przed rozpoczęciem: przeczytaj cel, przygotuj środowisko i zapisz przewidywany wynik. Najpierw wykonaj jeden mały przykład ręcznie, potem zautomatyzuj kolejne próby. Polecenia w blokach Python uruchamiaj w interpreterze lub pliku .py, a polecenia instalacji i uruchomienia programów w terminalu.

Listy 1–5 obejmują pomiary, modele, ramkowanie i usługi. Listy 6–8 tworzą ścieżkę Scapy, lista 9 dotyczy TCP, a lista 10 kluczy i bezpiecznych połączeń. Zakres obowiązkowy i terminy określa prowadzący. Warianty dodatkowe i rozszerzenia są propozycjami, nie dodatkowymi wymaganiami zaliczenia.

  1. Warunki: podaj system, wersje programów, topologię, adresy, interfejs i punkt przechwytywania.
  2. Wejście: zapisz dokładne polecenie, parametry, plik wejściowy i przewidywany wynik.
  3. Wyjście: zachowaj wynik tekstowy, właściwy fragment PCAP lub tabelę pomiarów. Zrzut ekranu może uzupełniać, ale nie zastępuje danych.
  4. Interpretacja: oddziel to, co zaobserwowano, od tego, co tylko podejrzewasz. Opisz również wynik negatywny, błąd i ograniczenia pomiaru.

Dołącz źródła własnego programu oraz krótką instrukcję uruchomienia. Nie przesyłaj haseł, kluczy prywatnych, ciasteczek sesyjnych ani ruchu innych osób. Przechwycenia ogranicz do własnego eksperymentu. Możesz wykorzystać szablon raportu Markdown.

Eksperymenty aktywne wykonuj wyłącznie na własnych urządzeniach lub w środowisku wskazanym przez prowadzącego. Lista 8 wymaga odizolowanego wirtualnego przełącznika bez NAT i bez mostu do sieci uczelni, domu czy Internetu. Sam fakt użycia prywatnego adresu IP nie zapewnia izolacji. Skrót VM oznacza maszynę wirtualną, czyli odrębny system uruchomiony wewnątrz komputera gospodarza.

Lista 01Pomiar i obserwacja ruchu

Cel: rozróżnić RTT, widoczną trasę i ograniczenie rozmiaru pakietu. Potrzebujesz narzędzi ping, traceroute/tracert oraz Wiresharka i zgody na wskazane cele pomiarów.

  1. Wybierz własny host w sieci lokalnej i dwa dozwolone cele poza nią. Dla każdego wykonaj po 10 prób ping. Zapisz liczbę odpowiedzi oraz minimum, medianę i maksimum RTT. Brak odpowiedzi zapisz jako brak odpowiedzi, a nie jako zerowe RTT.
  2. Powtórz pomiar dla trzech długości danych ICMP, np. 32, 256 i 1200 B. Zachowaj te same cele i liczbę prób. Oddziel rozmiar danych od rozmiaru całego pakietu.
  3. Na własnej ścieżce IPv4 zbadaj największy rozmiar, który przechodzi z zakazem fragmentacji. Zacznij od małych wartości i użyj wyszukiwania binarnego. W Linuksie przykładem jest ping -4 -c 3 -M do -s 1400 ADRES; w Windows ping -4 -n 3 -f -l 1400 ADRES. W macOS sprawdź znaczenie -D i -s w man ping. Nie przenoś opcji bez sprawdzenia między systemami.
  4. W Wiresharku potwierdź IPv4, ustawienie DF, długość IP i ewentualny komunikat o konieczności fragmentacji. Bez opcji IPv4 całkowity rozmiar wynosi dane ping + 8 B ICMP + 20 B IPv4. Sam brak odpowiedzi w wyznaczonym czasie nie dowodzi przekroczenia MTU.
  5. Wykonaj traceroute lub tracert do tych samych celów. Podaj wariant próby (UDP, ICMP lub TCP), widoczne przeskoki i gwiazdki. Trasę powrotną badaj z drugiego końca tylko wtedy, gdy masz do niego dostęp. Nie zakładaj symetrii. Najdłuższa zaobserwowana droga nie jest średnicą Internetu.

Oddaj: tabelę pomiarów, polecenia, mały PCAP z opisanymi numerami pakietów i wnioski. Wyjaśnij przynajmniej jeden przypadek, w którym samo narzędzie nie pozwala jednoznacznie ustalić przyczyny wyniku. Wykład: ograniczenia obserwacji.

Lista 01 / Wireshark i programowanieProsty komunikator w danych ICMP Echo

Cel: zaimplementować nadawcę krótkiego tekstu i odbiornik, który rozpoznaje ten tekst w przechwyconym żądaniu Echo. W raporcie pokaż związek między wiadomością, bajtami i warstwami Ethernet → IPv4 → ICMP. Najpierw przeczytaj format ICMP i kapsułkowanie oraz IHL i długość IP.

Środowisko i zakres

Użyj dwóch własnych VM Linux A = 10.77.0.10/24 i B = 10.77.0.20/24, na wewnętrznym przełączniku bez bramy, NAT i bridge, zgodnie z konfiguracją listy 7. Przygotuj Python 3, Scapy, libpcap i Wireshark przed odłączeniem Internetu. Przechwytuj na odbiorcy B; zwykły trzeci host przy przełączniku nie musi widzieć unicastu A → B. Uprawnienia do surowych pakietów nadaj tylko procesowi wewnątrz testowej VM; nie instaluj pakietów pip jako root.

Przesyłamy wyłącznie jawny tekst demonstracyjny między A i B: do 64 B UTF-8 w wiadomości, najwyżej 5 wiadomości w serii, odstęp co najmniej 1 s. Odbiornik kończy pracę po maksymalnie 120 s. Bez fałszowania źródła, wysyłania plików, zdalnych poleceń, tunelowania, skanowania i obchodzenia filtrów. Jeśli nie masz potwierdzonej izolacji, wykonaj wariant offline.

Umowa między nadawcą a odbiorcą

Ćwiczenie ograniczone do dwóch własnych maszyn w izolowanej sieci. Odbiorca odczytuje dane żądania, a nie kopię w odpowiedzi Echo.
Przechwyt wykonujemy na B. Żądanie Echo niesie tekst ćwiczenia; odpowiedź systemowa nie oznacza nowej wiadomości od użytkownika.
Własny format NET1 w danych Echo, nie w polach id ani seq
PołożeniePoleWartość i interpretacja
IPv4Źródło, cel, fragmentacjaRzeczywiste adresy A i B; DF = 1, MF = 0, offset = 0. Nie potrzebujemy fragmentacji tak małych wiadomości.
Nagłówek ICMPType, Code, Identifier, Sequence8, 0, 0x4c4b (19531), seq = 1…5 dla jednej serii.
Dane Echo, bajty 0–3ZnacznikASCII NET1, czyli 4e 45 54 31.
Dane Echo, bajty 4–5Długość tekstuNieujemna liczba 16-bitowa, big-endian, w zakresie 1…64. Liczymy bajty UTF-8, nie znaki.
Dane Echo, od bajtu 6TreśćDokładnie zadeklarowana liczba bajtów poprawnego UTF-8. Bez dodatkowych bajtów w obrębie danych ICMP.

Identyfikator 0x4c4b i znacznik NET1 służą rozpoznaniu ćwiczenia, nie uwierzytelnieniu. W jednej serii trójka (adres źródła, id, seq) rozróżnia wiadomości. Zduplikowany numer zgłoś w logu, ale nie wyświetlaj tekstu drugi raz. Przed nową serią wyczyść stan odbiornika.

Najpierw budowa offline

import struct
from scapy.all import IP, ICMP, Raw, raw

text = "Cześć".encode("utf-8")
assert 1 <= len(text) <= 64
payload = b"NET1" + struct.pack("!H", len(text)) + text
packet = (IP(src="10.77.0.10", dst="10.77.0.20", flags="DF")
          / ICMP(type=8, code=0, id=0x4c4b, seq=1)
          / Raw(payload))
decoded = IP(raw(packet))  # serializacja oblicza długości i sumy
print(len(text), decoded.len, payload.hex())
# 7 41 4e4554310007437a65c59bc487

Ten fragment niczego nie wysyła. Scapy odpowiada za kodowanie nagłówków i sum, a Ty implementujesz reguły aplikacji. show2() prezentuje pola po złożeniu pakietu; odczyt z IP(raw(packet)) pozwala sprawdzić rzeczywiste bajty. Własny parser NET1 nie powinien zakładać, że wszystkie przechwycone ramki zawierają IP lub Echo.

Implementacja i eksperyment

  1. Nadawca. Wczytaj tekst, zakoduj UTF-8, sprawdź limit i zbuduj powyższy pakiet z kolejnym seq. Wysyłaj pojedyncze żądanie przez send() lub ograniczoną próbę sr1(..., timeout=2, retry=0). Wyjście na poziomie IP wynika z tablicy routingu, więc sprawdź ją przed próbą. Nie zastępuj adresu źródłowego adresem cudzej maszyny.
  2. Odbiornik. Uruchom na B przechwytywanie na właściwym interfejsie, np. przez sniff(). Filtr przechwytywania: icmp and src host 10.77.0.10 and dst host 10.77.0.20. Ustaw limit czasu przechwytywania 120 s. Funkcja obsługi sprawdza zewnętrzny IPv4, Protocol = 1, brak fragmentacji, ICMP 8/0, id, zakres seq, znacznik, długość i UTF-8. Sprawdź również sumę kontrolną całego ICMP, korzystając z funkcji bibliotecznej. Samo rozpoznanie warstwy przez Scapy nie potwierdza poprawności sumy; filtr przechwytywania BPF również nie zastępuje tych kontroli.
  3. Granice danych. Odczytuj dane ICMP w granicach Total Length i IHL, po jego 8-bajtowym nagłówku. Odrzuć ucięty pakiet. Nie dołączaj ethernetowego dopełnienia, FCS ani cytatu z błędu ICMP jako tekstu rozmówcy. Możesz użyć parsowania Scapy zamiast własnego rozbierania wszystkich nagłówków.
  4. Wireshark. Równolegle przechwytuj na B własną wymianę. Filtr wyświetlania icmp.type == 8 && icmp.ident == 19531 wybiera żądania ćwiczenia. Pokaż id, seq, sumę, dane w zapisie szesnastkowym i odtworzony tekst. Porównaj z Echo Reply przez icmp.type == 0. Nie myl tych filtrów z filtrem przechwytywania.
  5. Dwa kierunki. Zamień role A i B albo uruchom po obu stronach nadawcę i odbiornik z odwróconą parą adresów. Nowa wypowiedź rozmówcy jest nowym Echo Request. Automatyczne Echo Reply systemu jedynie zwraca dane, więc nie pokazuj go jako drugiej wiadomości użytkownika.
  6. Próby poprawne. Wyślij tekst ASCII, „Cześć” i tekst mieszczący się dokładnie w 64 B. Sprawdź, że nadawca odrzuca 65 B. Odróżnij wysłanie, otrzymanie Echo Reply i odczytanie przez aplikację; to trzy różne zdarzenia.
  7. Próby negatywne offline. Przygotuj syntetyczny PCAP: zły znacznik, niezgodna długość, błędne UTF-8, błędna suma kontrolna, powtórzony seq, Echo Reply oraz błąd ICMP cytujący Twoje Echo. Odbiornik ma odrzucić niepasujące dane i nie rozpakowywać zagnieżdżonego cytatu jako nowej wypowiedzi. Nie wysyłaj tych uszkodzonych przykładów do sieci.
  8. Ograniczenia. Opisz stratę, duplikaty, zmianę kolejności i brak uwierzytelnienia. Nie zapewniamy retransmisji ani niezawodnego czatu. Nie wyłączaj zapory, jeśli środowisko odrzuca Echo; odnotuj politykę i przejdź do wariantu offline albo uzgodnij przygotowaną konfigurację pracowni.

Wariant offline i raport

Bez uprawnień administratora generuj pakiety przez IP(raw(packet)), zapisuj je wrpcap(), odczytuj rdpcap() i przepuszczaj przez tę samą funkcję odbiornika. Zapis samych pakietów IP daje inny typ łącza PCAP niż Ethernet; sprawdź nagłówek przechwycenia. Nie dodawaj fikcyjnych stałych 14 B, jeśli plik nie zawiera ramek Ethernet.

Oddaj: źródła nadawcy i odbiornika, instrukcję, potwierdzenie izolacji albo oznaczenie „offline”, mały PCAP i tabelę: kierunek, id, seq, tekst, liczba znaków, liczba bajtów UTF-8, długość IP, wynik parsera. Dołącz testy negatywne oraz po jednym rozpisanym Echo Request i Echo Reply. Wyjaśnij, dlaczego dla „Cześć” jest 13 B danych Echo, 21 B ICMP i 41 B IPv4. Zatrzymaj przechwytywanie i procesy po ćwiczeniu.

API: Scapy: serializacja, wysyłanie i sniffing; pola analizy: Wireshark ICMP. Program jest demonstracją formatów, nie bezpiecznym kanałem komunikacji.

Lista 02Przepływ, opóźnienie i niezawodność modelu sieci

Cel: napisać symulator, którego wynik można odtworzyć i zinterpretować. Nie wykonujesz tutaj rzeczywistego ruchu sieciowego.

Dane i jednostki

Przyjmij model S=(G,H). Graf G=(V,E) ma 20 wierzchołków, mniej niż 30 krawędzi i jest spójny. Zbiór funkcji H opisuje parametry łączy: przepustowości c(e) oraz jednakowe dla krawędzi prawdopodobieństwo działania p. Macierz N=[n(i,j)] zawiera nieujemne natężenia ruchu w pakietach/s; na przekątnej wpisz zero. Suma jej elementów Λ musi być dodatnia.

ParametrZnaczenie i jednostka
c(e)Przepustowość krawędzi, bit/s.
a(e)Suma natężeń tras korzystających z krawędzi, pakiet/s. Wylicz ją z routingu i N, nie losuj niezależnie.
mŚrednia długość pakietu, bit.
pPrawdopodobieństwo działania każdej krawędzi w jednej niezależnej próbie.
TmaxPróg średniego opóźnienia, s.

W podstawowym wariancie krawędź jest nieskierowana i ma wspólny budżet przepustowości dla obu kierunków. Wyznacz po jednej najkrótszej trasie dla każdej pary z dodatnim ruchem, ze stałą regułą rozstrzygania remisów. Jest to uproszczenie, nie model pełnego dupleksu Ethernet.

Jedna próba symulacji

  1. Niezależnie wylosuj działanie każdej krawędzi z prawdopodobieństwem p. Losowanie dotyczy stanu w próbie, nie nieokreślonego „dowolnego czasu”.
  2. Jeśli graf jest niespójny, uznaj próbę za niepowodzenie. W przeciwnym razie wyznacz trasy od nowa i oblicz a(e).
  3. Jeśli dla choć jednej krawędzi a(e)c(e)/m, oznacz przeciążenie i nie podstawiaj danych do wzoru z zerowym lub ujemnym mianownikiem.
  4. Dla stabilnego modelu oblicz poniższe T i sprawdź, czy jest mniejsze od Tmax.
T=1Λ·eEa(e)c(e)/ma(e)

Wzór przyjmuje przybliżenie niezależnych kolejek M/M/1. Pomija m.in. propagację i zależności ruchu na kolejnych łączach. Sprawdź jednostki: składnik sumy jest bezwymiarowy, a dzielenie przez Λ daje sekundy.

Badanie i kontrola wyniku

  1. Uruchom co najmniej 1000 prób dla ustalonego zestawu danych. Podaj ziarno generatora i udział prób udanych. Osobno policz niespójność, przeciążenie i przekroczenie progu.
  2. Porównaj trzy eksperymenty: zwiększanie wszystkich natężeń N; zwiększanie przepustowości; dodawanie krawędzi o średniej początkowej przepustowości. W każdym zmieniaj tylko wybraną wielkość i nadal zachowaj mniej niż 30 krawędzi.
  3. Powtórz obliczenia dla kilku ziaren lub podaj przedział ufności dla udziału sukcesów. Nie interpretuj małych różnic Monte Carlo jako pewnego efektu.
  4. Dodaj testy skrajne p = 0 i p = 1, przeciążenie pojedynczej krawędzi oraz macierz o zerowej sumie, którą program powinien odrzucić.

Oddaj: kod, pliki konfiguracji, opis routingu, testy, trzy wykresy i interpretację przy założeniach modelu. Dodanie krawędzi może zmienić trasy; nie zakładaj wyniku przed wykonaniem eksperymentu.

Lista 03Ramkowanie, CRC i współdzielenie medium

A. Od strumienia do ramek i z powrotem

Napisz koder i dekoder. Plik Z zawiera wyłącznie znaki 0 i 1; możesz ignorować końce linii, ale odrzucaj inne znaki. Koder tworzy plik W, a dekoder odzyskuje dane tylko z poprawnych ramek. Poniższy profil ustala szczegóły potrzebne do zgodności obu programów.

  1. Dziel dane na fragmenty o długości do 128 bitów. Przed fragmentem umieść jego długość na 16 bitach, od bitu najbardziej znaczącego. Pusty plik daje pusty wynik.
  2. Oblicz 8-bitowe CRC nad polem długości i danymi. Użyj wielomianu x8+x2+x+1, rejestru początkowego zero, bez odbicia bitów i bez końcowego XOR. Matematycznie: reszta z dzielenia wiadomości z dopisanymi 8 zerami. Dołącz resztę od najbardziej znaczącego bitu.
  3. W całym ciągu długość + dane + CRC wstawiaj zero po każdych pięciu kolejnych jedynkach. Dopiero ten wynik otocz flagami 01111110. Flagi nie podlegają wstawianiu dodatkowych bitów (ang. bit stuffing).
  4. Dekoder odnajduje flagi, usuwa wstawione zera, sprawdza strukturę, deklarowaną długość i CRC. Odrzuca uszkodzoną ramkę, informując o jej numerze. Puste odcinki między sąsiednimi flagami nie zawierają danych.

Przetestuj pusty plik, dane krótsze niż 128 bitów, wiele ramek, długie serie jedynek i zmianę pojedynczego bitu. Sam algorytm CRC sprawdź na bitach bajtów ASCII 123456789: wynik ma być 11110100 (0xF4), bez pola długości z naszego formatu.

B. Symulacja CSMA/CD

Zaimplementuj tablicę modelującą wspólne medium. W każdym kroku sygnał przemieszcza się do sąsiedniej komórki. Ustal pozycje co najmniej trzech stacji, długość ramki, jednostkę czasu i regułę wykrycia nakładających się transmisji. Dodaj losowe ponawianie po kolizji z rosnącym zakresem oczekiwania oraz limit prób. Porównaj scenariusz bez kolizji, start jednoczesny i różne odległości stacji.

To dydaktyczny model historycznego, współdzielonego Ethernetu w trybie półdupleksowym (half-duplex). Nie przedstawiaj go jako sposobu działania współczesnego przełączanego Ethernetu w trybie pełnego dupleksu (full-duplex).

Oddaj: koder, dekoder, testy odtworzenia danych po kodowaniu i dekodowaniu oraz testy wykrywania uszkodzeń, a także czytelny ślad czasowy symulacji CSMA/CD. Opisz, które uproszczenia odróżniają symulację od standardu.

Lista 04Konfiguracja sieci IP w GNS3

Cel: zbudować trasy i odróżnić adresację lokalną od wyjścia poza laboratorium. Potrzebujesz GNS3, legalnie pozyskanych obrazów urządzeń lub dostępnych routerów linuksowych oraz własnych hostów testowych.

R5 łączy sieć zewnętrzną z R6. R6 łączy LAN1 z PC1 i router R2. R2 łączy LAN2 z PC2, PC3 i R3.
Wszystkie pokazane podsieci IPv4 mają w tym ćwiczeniu prefiks /24. R3 jest dodatkowym routerem w LAN2, nie bramą obowiązkowo używaną przez PC2.
  1. Przygotuj plan adresów dla podsieci 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24 i 192.168.4.0/24. W tych podsieciach /24 adres z końcówką .0 oznacza sieć, nie interfejs. Nadaj unikalne statyczne adresy wszystkim wewnętrznym interfejsom.
  2. Skonfiguruj trasy, w tym trasy powrotne. Sprawdź ping między każdą parą hostów oraz do wewnętrznych interfejsów routerów. Przy każdej awarii wskaż ostatni działający etap.
  3. Osobno podłącz interfejs zewnętrzny R5 do zatwierdzonej sieci testowej Cloud z DHCP. R5 ma otrzymać adres dynamicznie. Zakres 192.168.0.0/24 z diagramu jest przykładem: jeśli koliduje z rzeczywistą konfiguracją, uzgodnij inny i odnotuj zmianę. Nie mostkuj nieuzgodnionego laboratorium do sieci uczelni.
  4. Skonfiguruj wyjście i powrót do dozwolonego celu zewnętrznego. Potrzebna będzie albo trasa powrotna po stronie zewnętrznej, albo NAT na R5, zależnie od środowiska. Rozwiązanie opisz.
  5. Przechwyć jedną serię ping z PC2 jednocześnie w LAN2, na łączu R6–R5 i na zewnętrznym łączu R5. Porównaj IP źródła i celu, MAC-y, TTL i identyfikację komunikatów. Następnie powtórz próbę z nazwą DNS i oddziel rozwiązywanie nazwy od ICMP.

Oddaj: projekt GNS3, plan adresacji, tablice tras, macierz testów osiągalności i opis trzech punktów przechwycenia. Tej sieci z wyjściem zewnętrznym nie używaj do listy 8.

Lista 05Serwer HTTP i granice wiadomości

Punktem wyjścia jest dotychczasowy server3.pl. Wymaga Perla oraz modułów HTTP::Daemon i HTTP::Status. Nasłuchuje na 127.0.0.1:4322 i próbuje wysłać ./index.html z bieżącego katalogu. Przygotuj ten plik w osobnym katalogu laboratoryjnym.

  1. Uruchom serwer. Otwórz http://127.0.0.1:4322/ w przeglądarce i wywołaj curl -i http://127.0.0.1:4322/. Wskaż linię statusu, nagłówki i treść odpowiedzi.
  2. Zmień serwer albo napisz własny w wybranym języku tak, aby zwracał linię żądania i jego nagłówki jako tekst. Ustaw typ text/plain; nie interpretuj przesłanych wartości jako HTML.
  3. Obsłuż mały serwis kilku wzajemnie połączonych plików statycznych z jednego katalogu głównego. Zwracaj 404 dla brakującego pliku. Nie pozwól, aby ścieżka z .. lub jej zakodowany wariant umożliwiała odczyt spoza tego katalogu. Przetestuj to na własnym, niesekretnym pliku kontrolnym poza katalogiem serwisu.
  4. Przechwyć własną wymianę na interfejsie lokalnym komputera (loopback). Porównaj bajty żądania i odpowiedzi z widokiem przeglądarki. Wskaż CRLF, pustą linię i sposób określenia długości treści.
  5. Przetestuj tekst zawierający polskie znaki. Wyjaśnij różnicę między liczbą znaków a liczbą bajtów UTF-8. Własny parser powinien mieć limit długości żądania i limit czasu oczekiwania.

Oddaj: kod, pliki przykładowego serwisu, polecenia testowe, fragment PCAP oraz wyniki przypadków: poprawna strona, brak pliku, niedozwolona ścieżka i tekst UTF-8. Własny serwer pozostaje demonstracją lokalną, nie usługą do publicznego wdrożenia.

Lista 06 / ScapyTutorial offline: od obiektu do bajtów i PCAP

Cel: samodzielnie konstruować i analizować pakiety bez wysyłania ich do sieci. Wystarczy Python 3 i Scapy. Administrator ani przechwytywanie nie są potrzebne. Przykłady tego zestawu sprawdzono z Scapy 2.7.0.

Przygotowanie

python3 -m venv .venv
.venv/bin/python -m pip install scapy==2.7.0
.venv/bin/python -c "import scapy; print(scapy.__version__)"

W Windows utwórz środowisko przez py -3 -m venv .venv i zamiast .venv/bin/python używaj .venv\Scripts\python.exe. Instaluj zależności przed odłączeniem Internetu. Wymagania przechwytywania na różnych systemach są opisane w dokumentacji instalacji.

Pliki startowe

Pobierz generator przykładów offline i szablon raportu. Generator tworzy sześć syntetycznych ramek oraz opis JSON. Nie otwiera gniazda do wysyłania ani przechwytywania. Uruchom go, podając nowy katalog wynikowy:

.venv/bin/python scapy-tutorial.py --output wyniki-scapy

W poleceniu użyj nazwy pobranego pliku. Plik JSON to opis danych startowych, nie gotowy raport ani zapis rzeczywistej transmisji. Tutorial z dokumentacji Scapy traktuj jako objaśnienie API; nie wykonuj jego przykładów wysyłających pakiety do publicznych serwerów.

Ćwiczenia do wykonania krok po kroku

  1. Budowa. W interaktywnym Pythonie utwórz poniższą ramkę. Przed uruchomieniem wypisz, jakie warstwy i adresy powinna zawierać.
from scapy.all import Ether, IP, UDP, TCP, ICMP, ARP, Raw, raw, rdpcap, wrpcap

p = (Ether(src="02:00:00:00:00:01", dst="02:00:00:00:00:02")
     / IP(src="192.0.2.10", dst="192.0.2.20", ttl=64)
     / UDP(sport=40000, dport=9000)
     / Raw(b"LAB"))
p.show()
p.show2()
  1. Serializacja. Oblicz b = raw(p), następnie q = Ether(b). Zapisz b.hex(), len(b), q[IP].len i q[UDP].len. Wyjaśnij różnicę: Ethernet ma nagłówek 14 B, IP 20 B, UDP 8 B, a dane 3 B. Scapy nie dopisuje tu automatycznie ethernetowego dopełnienia ani FCS. Dlatego 45 B obiektu nie jest dowodem, że fizyczne łącze nada ramkę o takiej długości.
  2. Zmiana pola. Utwórz changed = q.copy(), ustaw changed[IP].ttl = 63 i usuń zapisaną sumę przez del changed[IP].chksum. Odczytaj wynik ponownej serializacji jako updated = Ether(raw(changed)). Oryginał q pozostaje bez zmian. Porównaj sumy IP oraz UDP. Następnie w kopii changed zmień przenoszone dane (payload) i przed serializacją usuń pola IP.len, IP.chksum, UDP.len i UDP.chksum. Wyjaśnij, dlaczego wartości odczytane z gotowych bajtów nie aktualizują się samoczynnie po każdej edycji.
  3. Analiza pliku. Odczytaj packets = rdpcap("wyniki-scapy/tutorial.pcap"). Dla każdej ramki wypisz numer, summary(), długość, protokół, adresy i porty, jeśli dana warstwa je ma. Nie zakładaj obecności IP w ARP.
  4. Relacje. Znajdź trzy syntetyczne komunikaty TCP. Odczytaj flagi, seq i ack. Wyjaśnij przyrost o 1 po SYN. Zidentyfikuj żądanie i odpowiedź ARP. To dane demonstracyjne, nie dowód nawiązania rzeczywistego połączenia.
  5. Własny przykład. Dodaj parę ICMP Echo Request/Reply z własnym krótkim napisem i spójnymi polami id oraz seq. Zapisz nowy PCAP przez wrpcap(), odczytaj go i sprawdź, czy przenoszone dane pozostały niezmienione. Nie wywołuj send, sendp ani sr1.

Oddaj: wypełniony raport dla wszystkich sześciu ćwiczeń, własny kod, PCAP, wartości wejściowe i rzeczywiste wyjścia. Zinterpretuj przynajmniej jedną zmianę sumy kontrolnej. Podstawy API: oficjalny tutorial Scapy.

Lista 07 / ScapyWłasna wymiana i punkt obserwacji

Wymagane środowisko i izolacja

Potrzebujesz dwóch maszyn wirtualnych Linux: A i B, na wspólnym wewnętrznym przełączniku wirtualnym. Dla listy 8 dodasz C. Możesz użyć VirtualBox, UTM/QEMU lub środowiska pracowni. Nie wybieraj trybu bridge ani NAT. Każda VM ma mieć tylko jeden aktywny adapter laboratoryjny; odłącz adapter użyty wcześniej do instalacji pakietów. Zrób migawkę maszyn.

MaszynaIPv4 / prefiksRola
A10.77.0.10/24Klient i punkt obserwacji
B10.77.0.20/24Własny serwer testowy
C10.77.0.30/24Generator kontrolowanego błędnego ARP, dopiero lista 8

Adresy ustaw w konfiguracji sieci VM, bez bramy domyślnej i bez DNS. W każdej VM sprawdź ip -br addr, ip route i ip -6 route. Poza loopback, trasą laboratoryjną i link-local nie może być drogi do sieci zewnętrznej. Potwierdź też brak dodatkowych adapterów w ustawieniach programu zarządzającego maszynami wirtualnymi (hiperwizora); sam nieudany ping do Internetu nie jest dowodem izolacji. Nie używaj tutaj topologii GNS3 z listy 4.

W Linuksie surowe pakiety i przechwytywanie wymagają uprawnień, a filtr BPF biblioteki libpcap. W Debianie/Ubuntu można ją przygotować przed izolacją przez sudo apt install libpcap-dev. Właściwy interfejs ustal z ip -br link, nie zakładaj, że nazywa się eth0. Uruchamiaj Python ze środowiska: sudo .venv/bin/python. Nie instaluj pakietów pip jako root.

Przygotowanie z wykładu: ARP i tablica sąsiadów, ICMP Echo i dane pakietu. Własny odbiornik tekstu rozwijasz w części programistycznej listy 1.

Eksperyment A: obserwacja ICMP

  1. Sprawdź trzy zwykłe ping z A do B. W raporcie zapisz nazwy interfejsów i oba MAC-y.
  2. Na A uruchom przechwycenie poniżej; w drugim terminalu A w ciągu 10 s wykonaj ping -c 3 10.77.0.20. Wpisz własną nazwę interfejsu w miejsce przykładowego enp0s3.
from scapy.all import sniff, wrpcap

capture = sniff(iface="enp0s3",
                filter="icmp and host 10.77.0.20",
                count=6, timeout=10, store=True)
print(capture.summary())
wrpcap("icmp-lab.pcap", capture)
  1. Dopasuj zapytania i odpowiedzi po id, seq i adresach. Wyjaśnij, co oznacza mniej niż sześć pakietów w tym oknie pomiaru. Zmień filtr na arp i sprawdź, dlaczego przy istniejącym wpisie sąsiada nowy ping nie musi generować nowego ARP.

Eksperyment B: pojedyncza próba Scapy

from scapy.all import IP, ICMP, sr1

answer = sr1(IP(dst="10.77.0.20") / ICMP(id=77, seq=1),
             timeout=2, retry=0, verbose=False)
print("Brak odpowiedzi w terminie" if answer is None else answer.summary())

sr1() oczekuje na jedną odpowiedź na poziomie IP; wybór wyjścia wynika z routingu. sendp() działa na poziomie ramki i wymaga jawnie wybranego interfejsu oraz poprawnych adresów łącza. Nie zamieniaj tych funkcji bez zmiany konstrukcji pakietu.

Eksperyment C: SYN i stan hosta

Na B, w pustym katalogu laboratoryjnym, uruchom python3 -m http.server 8000 --bind 10.77.0.20. Na A wyślij jeden SYN: sr1(IP(dst="10.77.0.20")/TCP(sport=41000, dport=8000, flags="S", seq=100), timeout=2, retry=0), po zaimportowaniu TCP. Przechwyć wymianę na A. Następnie zatrzymaj serwer i powtórz jedną próbę.

Rozróżnij SYN-ACK, RST i brak odpowiedzi. Stos systemowy A może wysłać RST, bo nie utworzył takiego połączenia swoim API gniazd. Nie wyłączaj zapory, aby „naprawić” ten wynik. Ręczny SYN nie jest pełnym klientem TCP.

Oddaj: dowody konfiguracji izolacji, polecenia, PCAP-y i tabelę obserwacji przed oraz po zatrzymaniu serwera. Nie skanuj zakresu adresów ani portów; cele i port są jawnie wskazane w zadaniu.

Lista 08 / Scapy · Laboratorium bezpieczeństwaFałszywe odwzorowanie ARP i jego ograniczenia

Cel: zbadać, czy konkretny system przyjmie nieprawdziwy wpis IP → MAC, oraz odróżnić brak uwierzytelniania od samej możliwości obserwacji ruchu. Nie przechwytujemy haseł, nie uruchamiamy przekazywania ruchu i nie prowadzimy ataku na cudzą sieć.

Wykonuj wyłącznie w trzech własnych VM z listy 7, na wewnętrznym przełączniku bez dostępu zewnętrznego, po uzgodnieniu z prowadzącym. Przed częścią aktywną ponownie sprawdź adaptery i trasy. Jeśli nie możesz potwierdzić izolacji, wykonaj tylko wariant offline poniżej.

Podstawa do analizy: format ARP, ogłoszenia adresów i spoofing. Wskaż, które konkretne pola są fałszowane i gdzie odbiorca zapisuje uzyskane odwzorowanie.

A. Najpierw wariant offline

Wygeneruj dwie syntetyczne odpowiedzi ARP dla tego samego IP, ale z różnymi MAC-ami. Zapisz je do PCAP. Napisz analizator sygnalizujący zmianę odwzorowania; wynik ma podawać IP, stare i nowe MAC oraz numery ramek. Wyjaśnij, dlaczego taki sygnał nie jest jeszcze dowodem ataku: legalna rekonfiguracja, failover albo konflikt adresów również mogą zmienić obserwację.

B. Kontrolowany eksperyment, najwyżej trzy ramki

  1. Na A wykonaj ping -c 1 10.77.0.20 i zapisz ip neigh show 10.77.0.20. Sprawdź, że wpis zawiera prawdziwy MAC B. Na A uruchom Wiresharka z filtrem przechwytywania arp or icmp.
  2. Na C sprawdź sysctl net.ipv4.ip_forward. Wartość ma wynosić 0. Jeśli jest inna, przerwij i uzgodnij konfigurację; nie używamy C jako pośrednika przekazującego ruch.
  3. W Pythonie uruchomionym jako administrator wewnątrz C przygotuj poniższe dane. Nazwę interfejsu i MAC A wpisz zgodnie z własnym laboratorium. Przed wysłaniem obejrzyj forged.show2().
from scapy.all import Ether, ARP, get_if_hwaddr, sendp

iface = "enp0s3"                   # interfejs izolowanego laboratorium C
mac_a = "WPISZ_RZECZYWISTY_MAC_A"  # z ip -br link na A
mac_c = get_if_hwaddr(iface)
forged = (Ether(src=mac_c, dst=mac_a)
          / ARP(op=2, psrc="10.77.0.20", hwsrc=mac_c,
                pdst="10.77.0.10", hwdst=mac_a))
forged.show2()
# Dopiero po sprawdzeniu izolacji i wszystkich pól:
sendp(forged, iface=iface, count=3, inter=1, verbose=False)
  1. Na A ponownie odczytaj wpis sąsiada i wykonaj jeden ping do B. Porównaj MAC docelowy ramki z MAC B oraz C. System może odrzucić lub później zastąpić wpis; taki wynik też jest prawidłowym przedmiotem raportu. Nie zwiększaj liczby wysyłanych ramek, aby wymusić powodzenie.
  2. Zakończ przechwytywanie. Na A usuń wyłącznie laboratoryjny wpis: sudo ip neigh del 10.77.0.20 dev enp0s3, z własną nazwą interfejsu. Brak wpisu jest dopuszczalny. Wykonaj pojedynczy ping i potwierdź powrót MAC B. Zatrzymaj serwer B i przywróć migawki VM.

C. Co udało się wykazać?

Porównaj stan przed próbą, po próbie i po odtworzeniu. Zmiana ARP nie dowodzi odczytania zaszyfrowanej aplikacji. Brak przekazywania w C może przerwać komunikację zamiast stworzyć działający MITM. TLS z prawidłową walidacją poświadczeń chroni treść i uwierzytelnianie serwera, ale nie gwarantuje dostępności sieci.

Omów możliwe zabezpieczenia: kontrolę ARP na przełączniku z odpowiednią bazą powiązań, segmentację, monitorowanie zmian i statyczne wpisy w małym, kontrolowanym środowisku. Wyjaśnij ograniczenia każdej metody. Nie utożsamiaj reguł dla IPv4/ARP z ochroną IPv6/NDP.

Oddaj: analizator offline, syntetyczny PCAP oraz, jeśli wykonano część aktywną, raport z trzech stanów, ograniczeniami i potwierdzeniem przywrócenia konfiguracji. Inspiracja dydaktyczna i dalsza lektura: SEED Labs: ARP Cache Poisoning. Ten zestaw jest osobnym, ograniczonym ćwiczeniem, nie kopią pełnego laboratorium MITM z SEED.

Lista 09 / TCPOd pola ACK do decyzji nadawcy

Cel: osobno wyjaśnić niezawodność, kontrolę przepływu i kontrolę przeciążenia, a następnie odnaleźć ich ślady w komunikatach. Przygotowanie: rozdział o mechanizmach TCP. Część A wykonujesz bez sieci; część B wyłącznie na swoim komputerze.

A. Przebieg z jedną luką

  1. Połączenie jest już zestawione. Pierwszy bajt danych ma numer 1001. Nadajemy pięć bloków A–E po 500 B. B ginie, a C, D i E docierają poza kolejnością. Przyjmij natychmiastowe ACK, stałe niezerowe okno, buforowanie wszystkich późniejszych bloków i uzgodnione SACK. Rozpisz przedziały bajtów każdego bloku.
  2. Przygotuj tabelę zdarzeń z kolumnami: odebrane dane, ciągły prefiks, ACK, bloki SACK, SND.UNA i SND.NXT. Najpierw oblicz wyniki, a dopiero potem porównaj je z modelem w wykładzie. Oddziel odbiór danych przez odbiorcę od dotarcia potwierdzenia do nadawcy.
  3. Wskaż pierwsze ACK 1501 oraz trzy dodatkowe zduplikowane ACK. Czy sama strata B wygenerowała komunikat? Wyjaśnij, kiedy klasyczny fast retransmit może ponowić B. Podaj SEQ retransmisji oraz ACK po uzupełnieniu luki. Czy trzeba ponawiać C–E?
  4. Rozważ dwa osobne warianty: ginie tylko ACK dla A; albo po stracie B nie wysyłamy C–E. W pierwszym wyjaśnij znaczenie późniejszego kumulacyjnego ACK. W drugim wskaż, dlaczego nie zbiorą się trzy duplikaty i jakie zadanie ma RTO. Timeout jest podejrzeniem straty, nie dowodem jej przyczyny.
  5. Dla rwnd = 12 000 B, cwnd = 8000 B i 5000 B w drodze oblicz limit nowych danych. Powtórz dla rwnd = 4000 B, cwnd = 12 000 B, 3000 B w drodze oraz dla zerowego rwnd. Wskaż w każdym przypadku ograniczający mechanizm. Obliczenia dotyczą uproszczonego stanu poza odzyskiwaniem strat; kalkulator w wykładzie pozwala je sprawdzić.

B. Własny transfer i pola segmentu

Potrzebujesz Pythona 3, curl i Wiresharka z uprawnieniami do przechwytywania loopback. Utwórz nowy, pusty katalog tcp-lab i pracuj tylko w nim. W pierwszym terminalu wygeneruj plik 1 MiB, a następnie udostępnij ten katalog lokalnie:

python3 -c 'from pathlib import Path; Path("payload.bin").write_bytes(bytes(range(256)) * 4096)'
python3 -m http.server 8000 --bind 127.0.0.1

Uruchom przechwytywanie na loopback: zwykle lo w Linuksie, lo0 w macOS. Filtr przechwytywania: tcp port 8000. Dopiero potem w drugim terminalu, w tym samym katalogu, wykonaj:

curl --noproxy '*' --http1.1 --fail \
  http://127.0.0.1:8000/payload.bin -o received.bin
cmp payload.bin received.bin
  1. Zatrzymaj przechwytywanie i serwer przez Ctrl+C. Filtr wyświetlania to tcp.port == 8000. Wybierz jeden strumień TCP i znajdź SYN, SYN-ACK, ACK, segmenty danych oraz zamknięcie.
  2. Dla kilku kolejnych segmentów serwera zapisz SEQ, długość danych i ACK klienta. Jawnie podaj, czy Wireshark pokazuje numery względne. ACK numeruje bajty, a długość danych nie obejmuje nagłówka TCP. Żądanie HTTP w przeciwnym kierunku ma własną numerację.
  3. Porównaj tcp.window_size_value z tcp.window_size oraz opcję Window Scale z SYN. Czy widoczne okno dotyczy wysyłającego segment, czy jego partnera? Wyjaśnij, dlaczego nie odczytasz w ten sposób cwnd.
  4. Sprawdź, czy widzisz retransmisje, duplikaty ACK lub SACK. Jeśli ich nie ma, zapisz ten wynik: nie dodawaj ich do raportu na podstawie samego modelu z części A. Etykieta „Retransmission” jest wnioskiem analizatora, nie flagą TCP.
  5. Porównaj cmp z transportowym ACK. Pierwsze bada zgodność zapisanych plików; drugie potwierdza przyjęcie bajtów przez TCP, nie zapis na dysku.

Na loopback nie ma fizycznej ramki Ethernet ani normalnej drogi przez routery. Offloading i łączenie segmentów mogą powodować bardzo duże widoczne segmenty lub pozorne błędy sum przed obliczeniem ich przez sprzęt. Nie wyciągaj z tego automatycznie wniosku o błędzie transmisji. Nie wywołuj strat w sieci uczelni ani w publicznym Internecie.

Oddaj: tabelę przewidzianych stanów, obliczenia trzech okien oraz małe własne przechwycenie z opisem konkretnych pól i ograniczeń obserwacji. Dokumentacja: pola TCP w Wiresharku.

Lista 10 / Bezpieczne połączeniaKlucze, certyfikaty TLS i tunel SSH

Cel: odróżnić klucz prywatny, klucz publiczny, CSR, certyfikat i zaufanie do wystawcy. Następnie sprawdzić, gdzie naprawdę kończy się ochrona kanału. Wprowadzenie: bezpieczeństwo w stosie protokołów. Realizujemy TLS 1.3, nie historyczny SSL.

Środowisko: OpenSSL 3.x, powłoka POSIX (Linux, macOS z OpenSSL 3 lub własna VM), dwa terminale i opcjonalnie Wireshark. Sprawdź openssl version; systemowy LibreSSL nie musi obsługiwać tych samych opcji. Serwer TLS nasłuchuje tylko na loopback. Testowego CA nie dodawaj do systemowego magazynu zaufania ani przeglądarki. Kluczy prywatnych, haseł i sekretów sesji nie umieszczaj w raporcie, repozytorium ani katalogu publikowanym w WWW.

A. Osobny wystawca i osobny serwer

Utwórz nowy, pusty katalog tls-lab, przejdź do niego i wykonaj umask 077. Jeśli katalog już istnieje, wybierz nową nazwę, aby nie nadpisać kluczy. Wszystkie kolejne polecenia wykonuj w tym katalogu. CA otrzyma zaszyfrowany klucz prywatny; program poprosi o własne hasło, także przy późniejszym podpisywaniu.

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 \
  -aes-256-cbc -out ca.key
openssl req -new -x509 -key ca.key -sha256 -days 2 \
  -subj "/CN=Network Lab CA" \
  -addext "basicConstraints=critical,CA:TRUE" \
  -addext "keyUsage=critical,keyCertSign,cRLSign" -out ca.crt

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 \
  -out server.key
openssl pkey -in server.key -pubout -out server.pub
openssl req -new -key server.key -subj "/CN=localhost" \
  -out server.csr
openssl req -in server.csr -verify -noout

ca.key podpisuje certyfikaty, a server.key służy serwerowi do uwierzytelnienia w TLS. To różne role. server.pub zawiera jawny klucz publiczny, a CSR zawiera ten klucz i żądane dane podmiotu, podpisane kluczem serwera. Poprawny podpis CSR potwierdza posiadanie klucza, nie uprawnienie do nazwy domeny. Klucz serwera w tym zamkniętym ćwiczeniu nie jest zaszyfrowany na dysku; chronią go uprawnienia katalogu. To nie instrukcja wdrażania produkcyjnego CA.

B. Certyfikat dla konkretnej nazwy

Utwórz w katalogu plik server.ext o poniższej zawartości. Ustawienia pochodzą od wystawcy: serwer nie może sam nadać sobie uprawnienia CA. SAN obejmuje dokładnie lokalne cele ćwiczenia.

basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature
extendedKeyUsage=serverAuth
subjectAltName=DNS:localhost,IP:127.0.0.1
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -sha256 -days 2 -extfile server.ext \
  -out server.crt
openssl x509 -in server.crt -noout -subject -issuer -dates
openssl x509 -in server.crt -noout -ext subjectAltName
openssl verify -CAfile ca.crt -purpose sslserver \
  -verify_hostname localhost server.crt

Oczekiwany wynik ostatniego polecenia: server.crt: OK. Klient ufa CA dlatego, że wskazaliśmy jego certyfikat przez -CAfile, a nie dlatego, że root jest samopodpisany. Nazwę serwera sprawdzamy względem SAN; sam napis CN nie wystarcza jako współczesna reguła identyfikacji usługi.

C. Połączenie i dwie próby negatywne

W pierwszym terminalu uruchom lokalny serwer testowy. Opcja -www zwraca stronę diagnostyczną, nie udostępnia zawartości katalogu z kluczami. Jej wynik może jednak zawierać sekrety sesji: do raportu wybierz wyłącznie status HTTP, wersję i szyfr, nie całą odpowiedź ani jej pełny zrzut ekranu. Lista dostępnych szyfrów nie jest listą wersji użytych w tym połączeniu; odczytaj pole Protocol bieżącej sesji.

openssl s_server -accept 127.0.0.1:8443 -cert server.crt \
  -key server.key -www -tls1_3

W drugim terminalu prześlij krótkie żądanie HTTP przez TLS:

printf 'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n' |
openssl s_client -connect 127.0.0.1:8443 -servername localhost \
  -verify_hostname localhost -CAfile ca.crt -verify_return_error \
  -tls1_3 -quiet
  1. Poprawne zaufanie i nazwa: zapisz, czy walidacja się udała i czy otrzymałeś odpowiedź HTTP. W diagnostyce serwera odnajdź wersję i zestaw szyfrów.
  2. Zła nazwa: powtórz polecenie klienta, zmieniając wyłącznie -verify_hostname localhost na -verify_hostname other.invalid. Zachowaj SNI i adres połączenia. Oczekuj błędu nazwy oraz przerwania połączenia, nie odpowiedzi HTTP.
  3. Nieznany wystawca: w pierwotnym poleceniu usuń -CAfile ca.crt, a dodaj -no-CAfile -no-CApath -no-CAstore. Oczekuj błędu zaufania. Pozostałe warunki mają być niezmienione.

-verify_return_error jest istotne: diagnostyczny klient bez tej opcji może zgłosić błąd weryfikacji i mimo to kontynuować. Po każdej próbie zanotuj echo $?, czyli kod zakończenia ostatniego polecenia potoku. Nie „naprawiaj” wyniku przez wyłączenie walidacji. -servername ustawia SNI, a -verify_hostname sprawdza tożsamość; te opcje nie są zamienne.

Opcjonalnie przechwyć własny loopback z filtrem tcp port 8443. Znajdź zestawienie TCP, ClientHello, ServerHello i rekordy chronione. W TLS 1.3 dalszy handshake, w tym certyfikat serwera, jest zwykle zaszyfrowany; brak jawnego certyfikatu w PCAP nie oznacza jego braku w protokole. Nie eksportuj sekretów sesji. Na koniec zatrzymaj serwer przez Ctrl+C.

D. SSH i granica tunelu, wariant dodatkowy

Ta część wymaga własnych VM A i B z listy 7, konta student oraz serwera OpenSSH na B (10.77.0.20), przygotowanych przez prowadzącego. Nazwę konta dostosuj do środowiska. Nie włączaj zdalnego logowania na cudzym ani służbowym komputerze. Nie zmieniaj polityk cudzych zapór. Na A, w nowym katalogu z umask 077, wygeneruj osobny klucz SSH; ustaw hasło na pytanie programu.

ssh-keygen -t ed25519 -a 64 -f ./student_ed25519 -C netlab
ssh-keygen -lf student_ed25519.pub -E sha256

Przez konsolę B dodaj wyłącznie zawartość student_ed25519.pub jako osobny wiersz do ~student/.ssh/authorized_keys, nie usuwając istniejących wpisów. Katalog powinien należeć do tego użytkownika i mieć uprawnienia 700, plik 600. Prywatny plik bez .pub zostaje na A. To nie certyfikat X.509 z poprzedniej części.

Na konsoli B odczytaj odcisk klucza hosta przez ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E sha256. Porównaj go z pierwszym zapytaniem klienta. Sam wynik skanowania klucza przez sieć nie potwierdza jego autentyczności. Na A wykonaj:

ssh -i ./student_ed25519 -o IdentitiesOnly=yes \
  -o HostKeyAlgorithms=ssh-ed25519 \
  -o UserKnownHostsFile=./known_hosts.lab \
  -o StrictHostKeyChecking=ask student@10.77.0.20

Po udanym logowaniu zakończ sesję przez exit. Na B uruchom w pustym katalogu testowym python3 -m http.server 8000 --bind 127.0.0.1. Na A utwórz tunel; serwer SSH musi zezwalać temu kontu na wskazane przekierowanie:

ssh -N -T -i ./student_ed25519 -o IdentitiesOnly=yes \
  -o HostKeyAlgorithms=ssh-ed25519 \
  -o UserKnownHostsFile=./known_hosts.lab \
  -o StrictHostKeyChecking=yes -o ExitOnForwardFailure=yes \
  -L 127.0.0.1:18080:127.0.0.1:8000 student@10.77.0.20

W drugim terminalu A wykonaj curl --noproxy '*' http://127.0.0.1:18080/. Lewy 127.0.0.1:18080 oznacza nasłuch na A; prawy 127.0.0.1:8000 jest celem widzianym z B. Kanał A–B chroni SSH, a od B do lokalnej usługi jest zwykły HTTP. Nie jest to przekierowanie całego Internetu ani zmiana HTTP w HTTPS. Zamknij tunel i serwer przez Ctrl+C, usuń tylko dodany własny wpis laboratoryjny albo przywróć migawkę VM.

Oddaj: diagram ról kluczy, jawne pola certyfikatu, tabelę trzech wyników TLS z przyczyną oraz granicę ochrony tunelu, jeśli go wykonano. W tabeli rozdziel zaufanie do CA, zgodność nazwy, dowód posiadania klucza i szyfrowanie sesji. Odpowiedz też: dlaczego zwykły Telnet nie daje tych własności? Nie dołączaj kluczy prywatnych ani haseł.

Dokumentacja: OpenSSL req, x509, s_server, s_client; OpenSSH ssh-keygen i ssh.

Proste rozszerzenia do wyboru

  1. Statystyki PCAP, offline. Grupuj własne pakiety według protokołu i pary końców. Podaj liczbę pakietów oraz bajtów osobno. Pokaż, dlaczego ranking według jednej miary nie musi odpowiadać drugiej.
  2. Fragmenty IPv4, offline. Skorzystaj z formatów i modelu fragmentacji w wykładzie. Skonstruuj większy pakiet, podziel go przez fragment(), odczytaj flagę MF i położenie fragmentu (Fragment Offset), a następnie odtwórz dane przez defragment(). Usuń jeden fragment i opisz różnicę. Offset jest liczony w jednostkach 8 B, nie bajtach.
  3. Mini-detektor konfliktów, offline. Rozszerz analizator ARP o okno czasowe i listę dozwolonych zmian w fikcyjnej konfiguracji. Podaj przykład fałszywego alarmu i niewykrytej zmiany. Nie opisuj go jako kompletnego systemu wykrywania włamań.

Materiały API: warstwy IP, ICMP, TCP i UDP, Ethernet i ARP.