14 KiB
Pytanie 8: TCP Three-Way Handshake
Pytanie
"Jaki jest cel uzgadniania trójetapowego (three way handshake) w protokole TCP? Jaka jest interpretacja numerów sekwencyjnych i potwierdzenia? Jaka jest wartość początkowa numeru sekwencyjnego?"
Przedmiot: SKM (Sieci Komputerowe)
📚 Odpowiedź główna
Wprowadzenie do TCP
TCP (Transmission Control Protocol) to protokół warstwy transportowej zapewniający:
- Niezawodne dostarczanie danych
- Kontrolę przepływu
- Kontrolę przeciążenia
- Połączeniowość (connection-oriented)
1. Three-Way Handshake - cel i przebieg
Cele uzgadniania trójetapowego
- Nawiązanie połączenia - obie strony zgadzają się na komunikację
- Synchronizacja numerów sekwencyjnych - ISN (Initial Sequence Number)
- Uzgodnienie parametrów - MSS, Window Scale, SACK, Timestamps
- Weryfikacja dostępności - obie strony są aktywne i gotowe
Przebieg (diagram)
Klient Serwer
│ │
│ (1) SYN, seq=x │
│──────────────────────────────────────────→│
│ │
│ (2) SYN+ACK, seq=y, ack=x+1 │
│←──────────────────────────────────────────│
│ │
│ (3) ACK, seq=x+1, ack=y+1 │
│──────────────────────────────────────────→│
│ │
│ [POŁĄCZENIE NAWIĄZANE] │
│ │
Szczegółowy opis kroków
Krok 1: SYN (Synchronize)
Klient → Serwer:
┌────────────────────────────────────────┐
│ Flaga: SYN = 1 │
│ Sequence Number: x (ISN klienta) │
│ Acknowledgment Number: 0 (nieistotny) │
│ Opcje: MSS, Window Scale, SACK, etc. │
└────────────────────────────────────────┘
- Klient inicjuje połączenie
- Wysyła swój ISN (Initial Sequence Number)
- Stan klienta: SYN_SENT
Krok 2: SYN-ACK (Synchronize-Acknowledge)
Serwer → Klient:
┌────────────────────────────────────────┐
│ Flagi: SYN = 1, ACK = 1 │
│ Sequence Number: y (ISN serwera) │
│ Acknowledgment Number: x + 1 │
│ Opcje: MSS, Window Scale, etc. │
└────────────────────────────────────────┘
- Serwer potwierdza otrzymanie SYN (ACK = x+1)
- Serwer wysyła swój ISN
- Stan serwera: SYN_RECEIVED
Krok 3: ACK (Acknowledge)
Klient → Serwer:
┌────────────────────────────────────────┐
│ Flaga: ACK = 1 │
│ Sequence Number: x + 1 │
│ Acknowledgment Number: y + 1 │
└────────────────────────────────────────┘
- Klient potwierdza otrzymanie SYN serwera
- Połączenie nawiązane (ESTABLISHED)
- Może zawierać już dane (TCP Fast Open)
2. Numery sekwencyjne (Sequence Numbers)
Interpretacja
Sequence Number (SEQ) = numer pierwszego bajtu danych w segmencie
Strumień danych:
Bajty: [0][1][2][3][4][5][6][7][8][9][10][11][12]...
Segment 1: SEQ=0, dane = bajty 0-4 (5 bajtów)
Segment 2: SEQ=5, dane = bajty 5-9 (5 bajtów)
Segment 3: SEQ=10, dane = bajty 10-12 (3 bajty)
Funkcje numerów sekwencyjnych
| Funkcja | Opis |
|---|---|
| Kolejność | Odbiorca składa segmenty we właściwej kolejności |
| Wykrywanie duplikatów | Ten sam SEQ = duplikat |
| Wykrywanie braków | Luka w SEQ = brakujący segment |
| Potwierdzanie | ACK wskazuje oczekiwany następny SEQ |
Przykład transmisji
Klient (ISN=1000) Serwer (ISN=5000)
│ │
│ SEQ=1000, "Hello" (5 bytes) │
│────────────────────────────────────→│
│ │
│ SEQ=5000, ACK=1005, "Hi" (2 bytes) │
│←────────────────────────────────────│
│ │
│ SEQ=1005, ACK=5002, "World" (5 b) │
│────────────────────────────────────→│
│ │
3. Numery potwierdzenia (Acknowledgment Numbers)
Interpretacja
Acknowledgment Number (ACK) = numer następnego oczekiwanego bajtu
ACK = ostatni_otrzymany_SEQ + liczba_otrzymanych_bajtów
Kumulatywne potwierdzenia
TCP używa cumulative ACK - potwierdza wszystkie bajty do danego numeru:
Otrzymano: SEQ=100 (10 bajtów), SEQ=110 (10 bajtów)
ACK = 120 (potwierdza bajty 100-119)
Otrzymano: SEQ=100 (10 bajtów), BRAK SEQ=110, SEQ=120 (10 bajtów)
ACK = 110 (nie można potwierdzić 120, bo brakuje 110-119!)
Selective ACK (SACK)
Opcja TCP pozwalająca potwierdzać niesąsiednie bloki:
Otrzymano: SEQ=100, BRAK SEQ=110, SEQ=120
ACK = 110
SACK: [120-130] ← "mam też te bajty"
4. Wartość początkowa numeru sekwencyjnego (ISN)
Dlaczego ISN nie zaczyna od 0?
- Bezpieczeństwo - przewidywalny ISN umożliwia ataki (TCP hijacking)
- Unikanie kolizji - stare segmenty z poprzednich połączeń nie będą mylone z nowymi
Generowanie ISN
Historycznie (RFC 793):
ISN = (4 mikrosekundy timer) mod 2^32
Zwiększany o 1 co 4μs → pełny cykl co ~4.55 godziny
Współcześnie (RFC 6528):
ISN = M + F(localhost, localport, remotehost, remoteport, secretkey)
Gdzie:
- M = timer (jak wyżej)
- F = funkcja kryptograficzna (MD5/SHA)
- secretkey = tajny klucz serwera
Właściwości dobrego ISN
| Właściwość | Powód |
|---|---|
| Losowy | Utrudnia ataki typu sequence prediction |
| Unikalny | Różny dla każdego połączenia |
| Monotonicznie rosnący | Unikanie kolizji z poprzednimi połączeniami |
Zakres numerów sekwencyjnych
SEQ: 32 bity → zakres 0 do 4,294,967,295 (2^32 - 1)
Przy szybkości 1 Gbps:
- 125 MB/s danych
- Przepełnienie (wrap-around) co ~34 sekundy!
Rozwiązanie: PAWS (Protection Against Wrapped Sequences)
- Używa opcji Timestamp do rozróżniania "starych" i "nowych" numerów
5. Stany połączenia TCP
┌─────────────┐
┌────────→│ CLOSED │←────────┐
│ └─────────────┘ │
│ │ │
(timeout) (passive open) (active open)
│ ↓ │
│ ┌─────────────┐ │
│ │ LISTEN │ │
│ └─────────────┘ │
│ │ │
│ (recv SYN) (send SYN)
│ ↓ ↓
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ TIME_WAIT │ │ SYN_RECEIVED│ │ SYN_SENT │
└─────────────┘ └─────────────┘ └─────────────┘
↑ │ │
(recv FIN+ACK) (send SYN+ACK) (recv SYN+ACK)
│ ↓ ↓
┌─────────────┐ ┌─────────────────────────────┐
│ FIN_WAIT_2 │ │ ESTABLISHED │
└─────────────┘ └─────────────────────────────┘
6. Zamykanie połączenia (Four-Way Handshake)
Klient Serwer
│ │
│ (1) FIN, seq=u │
│──────────────────────────────────────────→│
│ │
│ (2) ACK, ack=u+1 │
│←──────────────────────────────────────────│
│ │
│ (serwer może jeszcze wysyłać dane) │
│ │
│ (3) FIN, seq=v │
│←──────────────────────────────────────────│
│ │
│ (4) ACK, ack=v+1 │
│──────────────────────────────────────────→│
│ │
│ [TIME_WAIT: 2×MSL] │
│ │
MSL (Maximum Segment Lifetime) = maksymalny czas życia segmentu (~2 minuty) TIME_WAIT = 2×MSL = ~4 minuty (oczekiwanie na zagubione segmenty)
📊 Podsumowanie Three-Way Handshake
| Krok | Kierunek | Flagi | SEQ | ACK | Cel |
|---|---|---|---|---|---|
| 1 | C→S | SYN | x | - | Inicjacja, ISN klienta |
| 2 | S→C | SYN+ACK | y | x+1 | Akceptacja, ISN serwera |
| 3 | C→S | ACK | x+1 | y+1 | Potwierdzenie, połączenie gotowe |
🧠 Mnemoniki
"SYN-SYN/ACK-ACK" - trzy kroki:
- SYN - "Chcę rozmawiać" (klient)
- SYN/ACK - "OK, ja też" (serwer)
- ACK - "Super, zaczynamy" (klient)
"SEQ = Sent, ACK = Expected":
- SEQuence = numer wysyłanego bajtu
- ACKnowledgment = numer oczekiwanego bajtu
"ISN = Initial Secret Number":
- Initial - początkowy
- Secret - losowy dla bezpieczeństwa
- Number - 32-bitowa liczba
"ESTABLISHED po trzech krokach":
- 1: SYN_SENT
- 2: SYN_RECEIVED
- 3: ESTABLISHED (obie strony)
❓ Możliwe pytania dodatkowe (follow-up)
Q1: "Dlaczego trzy kroki, nie dwa?"
Odpowiedź:
Dwa kroki nie wystarczą do synchronizacji obu ISN:
Dwa kroki (hipotetycznie):
Klient: SYN, seq=x → Serwer zna ISN klienta
Serwer: SYN+ACK, seq=y → Klient zna ISN serwera
→ Ale serwer NIE WIE, czy klient otrzymał y!
Trzy kroki:
Klient: SYN, seq=x → Serwer zna ISN klienta
Serwer: SYN+ACK, seq=y → Klient zna ISN serwera
Klient: ACK, ack=y+1 → Serwer WIE, że klient otrzymał y ✓
Q2: "Co to jest SYN flood attack?"
Odpowiedź:
SYN flood = atak DoS wysyłający masę SYN bez dokończenia handshake'a.
Atakujący: SYN, SYN, SYN, SYN... (tysiące)
Serwer: SYN+ACK, SYN+ACK... (czeka na ACK)
→ Kolejka half-open connections pełna
→ Serwer nie może przyjąć nowych połączeń
Obrona:
- SYN cookies - serwer nie przechowuje stanu, koduje go w ISN
- Zwiększenie kolejki SYN
- Zmniejszenie timeout SYN_RECEIVED
- Firewall/IDS
Q3: "Co to jest TCP Fast Open (TFO)?"
Odpowiedź:
TFO pozwala wysyłać dane już w pierwszym SYN (0-RTT):
Standardowo: TFO:
SYN → SYN + dane →
← SYN+ACK ← SYN+ACK + dane
ACK + dane → ACK →
3 RTT do danych 1 RTT do danych!
Wymaga: Cookie TFO z poprzedniego połączenia (uzyskany przy pierwszym handshake).
Q4: "Jak działa retransmisja w TCP?"
Odpowiedź:
- Timeout (RTO): Brak ACK w określonym czasie → retransmisja
- Fast Retransmit: 3 duplikaty ACK → retransmisja bez czekania na timeout
Wysłano: SEQ=100, SEQ=200, SEQ=300
Zgubiono: SEQ=200
Odbiorca: ACK=200, ACK=200, ACK=200 (3× duplikat)
Nadawca: "Ah, brakuje 200!" → retransmisja SEQ=200
Q5: "Co oznacza flaga RST?"
Odpowiedź:
RST (Reset) = natychmiastowe przerwanie połączenia.
Kiedy wysyłane:
- Segment do zamkniętego portu
- Segment do nieistniejącego połączenia
- Połączenie w nieprawidłowym stanie
- Aplikacja chce natychmiast zamknąć (bez FIN handshake)
RST nie wymaga potwierdzenia - połączenie natychmiast zamknięte.
Q6: "Wyjaśnij opcje negocjowane podczas handshake"
Odpowiedź:
| Opcja | Opis | Wartość typowa |
|---|---|---|
| MSS | Maximum Segment Size | 1460 (Ethernet) |
| Window Scale | Mnożnik okna (>65535) | 0-14 (×2^n) |
| SACK Permitted | Selective ACK dozwolone | tak/nie |
| Timestamp | Pomiar RTT, PAWS | 32-bit timer |
| NOP | Padding | - |
🎯 Kluczowe punkty do zapamiętania
- 3 kroki: SYN → SYN+ACK → ACK
- SEQ = numer pierwszego bajtu w segmencie
- ACK = numer następnego oczekiwanego bajtu
- ISN = losowy, dla bezpieczeństwa i unikania kolizji
- Zamknięcie: 4 kroki (FIN → ACK → FIN → ACK) + TIME_WAIT
- SYN flood - atak DoS, obrona: SYN cookies
📖 Źródła do pogłębienia
- RFC 793 - TCP Specification
- RFC 6528 - Defending Against Sequence Number Attacks
- RFC 7413 - TCP Fast Open
- Stevens - "TCP/IP Illustrated, Volume 1"