Bölüm 7:Üç Adımlı El Sıkışma
Ağlar'a “Sen”i Katmak yazısının parçası: adres çubuğuna yazdığın tek bir isteğin peşinden bakırla fiberin fiziğine kadar inen uzun bir teknik yolculuk.
Tüm bölümler
- Giriş
- Adres Çubuğundan İsteğe
- Paket Anahtarlamalı Yol
- İsimden Adrese
- Önbellek, Tazelik ve Güven
- Port Numarası ve Soket
- Bağlantısız Taşıma: UDP
- Üç Adımlı El Sıkışma
- Simetrik Şifreleme
- Açık Anahtarlı Kriptografi
- TLS El Sıkışması
- Sertifika Zinciri
- HTTP Mesajının Anatomisi
- Durum, Çerez ve Oturum
- HTTP/2'den HTTP/3'e
- İçerik Dağıtım Ağları
- Diğer Uygulama Protokolleri
- Katmanlı Mimari
- Kapsülleme ve Başlıklar
- Paket Yakalama ve Çözümleme
- Ağ Arayüz Kartı
- Fiziksel Adresleme
- Hata Sezme ve CRC
- Adres Çözümleme: ARP
- Anahtarlama ve Ortam Erişimi
- Ağ Topolojileri
- Sanal Yerel Ağlar
- Kablosuz Erişim: 802.11
- Radyo Kanalı ve Kapasite
- Kablosuz Ağ Güvenliği
- Hücresel Ağlar
- Spektrum ve Kuşaklar
- Hareketlilik ve Aktarma
- Adres Kiralama: DHCP
- Adresin Anatomisi
- Adres Tükenmesi ve IPv6
- Yönlendirici Mimarisi
- Kuyruk Yönetimi
- Cihaz Yapılandırma
- Yönlendirme Protokolleri
- Kontrol Düzlemi ve SDN
- Ağ İzleme ve Yönetimi
- Alanlar Arası Yönlendirme
- Adres Çevirisi
- Ara Kutular
- Tünelleme ve IPsec
- Güvenlik Duvarları
- Operatör ve Metro Ağları
- Bitten Sinyale
- Çoklama Teknikleri
- İletim Ortamları
- Kablo Sonlandırma
- Fiber Optik İletim
- Bakır Erişim Ağı: DSL
- Pasif Optik Ağlar
- Kablo Erişim Ağları
- Denizaltı Kabloları
- Veri Merkezi Ağları
- Kapsülleme Çözme
- Güvenilir Aktarım
- Tıkanıklık Denetimi
- Trafik Çözümleme
- Gecikme Bütçesi
- Son Söz
Kapıyı buldun. Karşı taraf ise senin geldiğini henüz bilmiyor: bir soket açmak bağlantı kurmuyor, önce iki ucun da birbirini duyduğunu kanıtlaması gerekiyor.
Bunun bedeli üç mesaj, ve o üçüncü mesajın neden gerektiği ilk bakışta belli olmuyor.
İki mesaj neden yetmiyor?
El sıkışmanın üç işi var. Birincisi karşılıklı isteklilik: her iki uç da diğerinin bağlanmaya razı olduğunu öğreniyor. İkincisi parametre kararı. Başlangıç sıra numarası ve alıcının ilan ettiği tampon boyu tam burada kararlaştırılıyor. Üçüncüsü kaynak ayırmak. Tampon alanı ile bağlantı tablosunda bir satır ayrılıyor; saldırganın bastığı yer orası.
İnsan konuşmasında iki mesaj yeter. Sorarsın, cevap gelir, iş biter. Ağda yetmiyor, çünkü araya üç şey giriyor: gecikme sabit değil, kaybolan mesajlar yeniden gönderiliyor ve mesajlar sırasını şaşırabiliyor.
İki mesajlı kurulumun birinci arızası gecikmiş bir kopya. Eski bir kurulum isteğinin kopyası ağda oyalanıp sunucuya geç varırsa, sunucu tarafında yarı açık bir bağlantı kalıyor. İstemcisi olmayan bir bağlantı. İkinci arıza daha sinsi: kapanmış bir bağlantının gecikmiş verisi yeni bağlantıda ikinci kez kabul ediliyor.
Üçüncü mesajın gerekçesi bu yüzden nezaket değil. RFC 9293 onu, ağda dolaşan eski kurulum isteklerinin karışıklık yaratmasını engellemek diye yazıyor. İlk isteği alan taraf onun taze mi bayat mı olduğunu bilemiyor. Tek çıkar yol gönderene doğrulatmak.
Standart aslında dört mantıksal adım tanımlıyor. Ortadaki ikisi tek segmentte birleşebildiği için geriye üç mesaj kalıyor. Üçlü el sıkışma adı da tam olarak buradan geliyor.
Üç mesaj, iki durum makinesi
Adım bir: istemci başlangıç sıra numarasını seçiyor ve SYN denetim biti kalkık bir segment gönderiyor. Bu bitlerin yaygın adı bayrak, ben de öyle diyeceğim. Kendisi SYN-SENT durumuna geçiyor.
Adım iki: sunucu SYN-RECEIVED durumuna geçiyor. Henüz bağlanmış değil. Kendi başlangıç numarasını ilan ediyor ve istemcininkini onaylıyor; SYN ile ACK aynı segmentte birlikte kalkık duruyor.
Adım üç: istemci onayı gönderiyor ve ESTABLISHED oluyor. Sunucu ise ancak bu üçüncü mesaj eline geçince aynı duruma varıyor. İki uç aynı anda kurulmuş sayılmıyor.
| Mesaj | Kalkık bayraklar | İstemci durumu | Sunucu durumu |
|---|---|---|---|
| birinci | SYN | SYN-SENT | LISTEN |
| ikinci | SYN + ACK | SYN-SENT | SYN-RECEIVED |
| üçüncü | ACK | ESTABLISHED | ESTABLISHED |
Üç mesajı ve iki tarafın durumlarını birlikte izlemek istersen:
SYN biti kalkık, içinde istemcinin seçtiği başlangıç sıra numarası var. Bu numara sıfırdan başlamıyor; her bağlantı için tahmin edilemeyecek biçimde yeniden üretiliyor.- İstemci ilk mesajı yolluyor ve bekliyor.
SYNbiti kalkık, içinde istemcinin seçtiği başlangıç sıra numarası var. Bu numara sıfırdan başlamıyor; her bağlantı için tahmin edilemeyecek biçimde yeniden üretiliyor. - Sunucu tek segmentte hem cevaplıyor hem soruyor. Aynı segmentte
SYNveACKbirlikte kalkık. Onay numarasıx+1, çünküSYNbayrağı sıra uzayında bir bayt yer kaplıyor. Sunucu henüz bağlanmış değil, yalnızca yer ayırdı. - Üçüncü mesaj gönderene doğrulatıyor. Bu mesaj nezaket değil. İlk isteği alan taraf onun taze mi yoksa ağda oyalanmış bayat bir kopya mı olduğunu bilemez; ayıran tek şey, doğru numaranın geri getirilmesi.
- İki uç aynı anda kurulmuyor. İstemci üçüncü mesajı **yollar yollamaz**
ESTABLISHEDoluyor. Sunucu ise o mesaj **eline geçene kadar** bekliyor. Aradaki boşluk tam bir tek yön gecikmesi kadar; bu sürede istemci veri yollayabilir, sunucu henüz dinliyordur. - Fatura: veri gitmeden ödenen bir gidiş-dönüş. Uygulama verisi ancak buradan sonra akabiliyor. Üçüncü mesaj boş gitmek zorunda da değil — içinde ilk isteği taşıyabilir, ve el sıkışmayı güvenlikle birleştiren protokollerin hedeflediği tasarruf tam olarak bu turdur.
Sunucudaki uygulama süreci bağlantıyı tam o anda görüyor; kabul için bekleyen çağrı üçüncü mesaj varınca dönüyor. Dinleyen soket ile konuşan soket ayrı şeylerdi; el sıkışma bitince sunucuda ikincisi yaratılıyor ve dinleme kesintisiz sürüyor.
Beşinci bölümün apartmanına dönersek: kapıyı çalmak içeri girmek değil. Kapı açılacak, içeriden bir ses cevap verecek, sen de o sesi duyduğunu belli edeceksin. Üç mesaj tam olarak bu. İkinci mesaj istemciye sunucunun canlı olduğunu kanıtlıyor, üçüncü mesaj sunucuya istemcinin canlı olduğunu. Daha kısası yok.
Üçüncü mesajın boş gitmesi zorunlu değil; içinde istemciden sunucuya veri taşıyabiliyor. Bağlantı zaten tam çift yönlü (full duplex): aynı bağlantıda veri iki yöne birden akıyor. İki ucun da kendi başlangıç numarasını ilan etmesinin sebebi bu.
İki uç aynı anda kurulum isteği gönderirse sorun çıkmıyor. İkisi de SYN-SENT durumundan SYN-RECEIVED durumuna, oradan ESTABLISHED durumuna geçiyor ve standart bunu desteklemeyi şart koşuyor. Aynı port çifti arasında aynı anda yalnızca tek bir bağlantı olabiliyor; ama tek bir port, farklı karşı portlarla çok sayıda bağlantı taşıyabiliyor.
Bir ayrıntı da sıra numarası uzayında duruyor. SYN bayrağı orada 1 bayt yer kaplıyor, bu yüzden onay numarası başlangıç numarasının bir fazlası oluyor. Salt onay ise hiç yer kaplamıyor. Kaplasaydı onayların onayı diye sonsuz bir zincir doğardı ve standart bunu açıkça yazıyor.
İki ucun ilan ettiği numara sıfırdan başlamıyor. Her bağlantı için yeniden ve tahmin edilemeyecek biçimde seçiliyor. Sebebi güvenlik: numarayı bilen biri trafiği hiç görmeden o bağlantıya veri yazabiliyor. Numaranın burada yaptığı tek iş kurulumu işaretlemek. Kayıpları bulup sırayı düzelten asıl işini 58. bölümde çalıştıracağız; burada yalnızca ilan ediyorum.
DerinleşmeNumarayı tahmin edilemez yapan tam olarak ne?
Standart seçimi rastlantıya bırakmıyor, şarta bağlıyor. RFC 9293 saat sürümlü bir üretim istiyor (MUST-8): sayaç kabaca her 4 µs’de bir artıyor ve 32 bitlik uzay yaklaşık 4,55 saatte başa dönüyor. Bir segmentin ağda yaşayabileceği en uzun süreden çok daha uzun; eski bir bağlantının numaraları yenisiyle çakışmıyor.
Saat tek başına yetmiyor. Önerilen formül numarayı bağlantının kimliğine bağlıyor: yerel adres, yerel port, uzak adres, uzak port ve gizli bir anahtar bir işleve giriyor, çıkan değer sayaca ekleniyor. O işlevin dışarıdan hesaplanabilir olmaması ayrıca şart koşulmuş (MUST-9), yoksa bir bağlantının numarasından diğerininki türetiliyor.
Uzayın büyüklüğü 4.294.967.296 farklı numaraya çıkıyor. Kulağa bol geliyor ama saldırgan four-tuple’ı zaten biliyor. Asıl korumayı sağlayan şey uzayın genişliği değil, seçimin tahmin edilemezliği.
Numara aynı zamanda bir tazelik damgası. Gecikmiş eski bir kurulum isteği karşı tarafa taze bir istek gibi görünüyor; alıcı ikisini kendi başına ayıramıyor. Ayıran şey, üçüncü mesajın doğru numarayı geri getirmesi.
El sıkışma aynı zamanda bir pazarlık
İlk iki mesaj yalnızca selamlaşma taşımıyor. Başlıktaki alanlar burada dolduruluyor ve seçeneksiz haliyle o başlık 20 bayt.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+-------------------------------+
| kaynak portu | hedef portu |
+-------------------------------+-------------------------------+
| sıra numarası |
+---------------------------------------------------------------+
| onay numarası |
+-------+-------+---------------+-------------------------------+
| uzun. | ayrl. | bayraklar | pencere |
+-------+-------+---------------+-------------------------------+
| checksum | acil veri işaretçisi |
+-------------------------------+-------------------------------+
| seçenekler (0 ile 40 bayt) |Alanları soldan okuyalım. Kaynak portu ile hedef portu 16’şar bit; soket four-tuple’ının taşıma tarafı bu iki alan. Sıra numarası ile onay numarası 32’şer bit, yani 4’er bayt. Onay numarası beklenen bir sonraki baytın numarasını taşıyor, ACK bayrağı da o alanın geçerli olduğunu söylüyor.
Başlık uzunluğu alanı 4 bit ve başlığı 32 bitlik kelimeler cinsinden ölçüyor. Üst sınırı on beş kelime, yani 60 bayt. Seçeneklere kalan en fazla yer 40 bayt. Taşıma başlığı ile IPv4 başlığı birlikte her veri birimine en az 40 bayt sabit yük bindiriyor.
Bayrak alanı bugün sekiz atanmış denetim biti taşıyor ve her birinin tek cümlelik bir işi var:
| bayrak | ne demek |
|---|---|
SYN | bağlantı kur; başlangıç numaram bu |
FIN | benden yollanacak veri kalmadı |
RST | bu bağlantı yok, iptal et |
ACK | onay numarası alanı geçerli |
PSH | biriktirme, uygulamaya hemen ver |
URG | acil işaretçi alanı geçerli |
ECE | karşı taraftan tıkanıklık bildirimi geldi |
CWR | bildirimi aldım, pencereyi kıstım |
Listeyi IANA’nın TCP Header Flags defteri yönetiyor; yeni bir bit oraya yazılmadan kullanılamıyor. Bağlantı yönetimini bunlardan üçü yapıyor: RST, SYN ve FIN.
RST ile FIN arasındaki fark ince ama sahada belirleyici. FIN kibar bir kapanış: “benim söyleyeceğim bitti, sen devam edebilirsin”. RST ise “böyle bir bağlantı yok, ne gönderdiysen at” demek. Kapalı bir porta bağlanmaya çalıştığında aldığın o anlık ret, teldeki karşılığıyla tam olarak bu bayraktır — bekleyip zaman aşımına uğramamanın sebebi de o.
Son ikisi ilerideki bir durağa bağlanıyor: tıkanıklık kayıp beklemeden, yol üstündeki bir yönlendirici tarafından da bildirilebiliyor. ECE ve CWR o bildirimin taşıma katmanındaki iki ucu.
Seçenekler: pazarlığın asıl yapıldığı yer
Pazarlık kısmı seçeneklerde duruyor ve bunların çoğu yalnızca SYN bayraklı segmentlerde gönderilebiliyor. Yani anlaşma ya el sıkışmada olur ya hiç olmaz; bağlantı kurulduktan sonra taraflar bu ayarları değiştiremiyor.
| tür | seçenek | boy | ne pazarlık ediliyor |
|---|---|---|---|
| 2 | En büyük segment boyu (MSS) | 4 bayt | tek seferde kaç bayt veri kabul ediyorum |
| 3 | Pencere ölçekleme | 3 bayt | pencere alanını kaç bitlik kaydırmayla çarpayım |
| 4 | SACK izinli | 2 bayt | seçici onayı destekliyorum |
| 8 | Zaman damgası | 10 bayt | her segmente saat vur; gidiş-dönüşü ölç |
| 1 | Dolgu (NOP) | 1 bayt | sonraki seçeneği 4 baytlık hizaya getir |
| 0 | Seçenek sonu | 1 bayt | liste bitti |
İlk dördü bağlantının ömrü boyunca etkili olan kararlar ve üçü de bu kitapta ilerideki bölümlerin konusu: pencere ölçekleme ile seçici onay 59. bölümde kayan pencereyi kurarken, zaman damgası ise 61. bölümde gecikmeyi ölçerken çalışacak.
Bir seçenek karşı tarafça anlaşılmazsa sessizce yok sayılıyor — cevapta o seçenek geri gelmiyor ve gönderen “desteklenmiyor” diye anlıyor. Pazarlığın “hayır” demesi bu: konuşmamak.
MSS seçeneği hiç gelmezse varsayılan devreye giriyor: IPv4’te 536 bayt, IPv6’da 1.220 bayt. İkisi de taban boydan başlık yükü düşülerek çıkıyor, 576 bayt eksi 40 bayt ve 1.280 bayt eksi 60 bayt. Bu değerler kimseyi mutlu etmiyor ama kimseyi de kırmıyor.
Üçüncü mesaj hiç gelmezse?
Önce kapıyı çalmanın cevabına bakalım. Kapalı bir porta gelen bağlantı isteği sessizlikle karşılanmıyor; geriye RST ile ACK birlikte dönüyor. Açık portta ise SYN ile ACK dönüyor. Fark tek bir segmentte görünüyor.
Bu yüzden port taraması el sıkışmanın ortasında durabiliyor. Yarı açık tarama (nmap -sS) üçüncü mesajı hiç göndermiyor, yerine RST atıp bağlantıyı koparıyor; el sıkışma tamamlanmadığı için uygulamanın günlüğüne hiçbir bağlantı düşmüyor. Üçüncü mesajı gönderip el sıkışmayı bitiren tarama (nmap -sT) ise iz bırakıyor.
Aynı boşluk bir saldırıya da açık. SYN seli ağı ya da belleği değil, port numarasına bağlı yarı açık bağlantı kuyruğunu tüketmeyi hedefliyor. Saldırgan çoğu zaman sahte kaynak adresle SYN yağdırıyor; ikinci mesajın cevabı hiç gelmiyor ve kayıt kuyrukta asılı kalıyor. Varsayılan kuyruk derinliği tipik olarak yarım düzine ile birkaç düzine arasında. Saldırının ucuzluğu tam buradan geliyor.
Kayıt sonsuza kadar durmuyor. Örnek bir uygulamada ilk SYN-ACK gönderilirken 75 saniyelik bir zamanlayıcı kuruluyor. Ama zamanlayıcı dolmadan kuyruk dolarsa gerçek istemciler kapıda kalıyor.
Standart yarı açık bağlantıyı ayrıca tanımlıyor: bir uç kapatmış ya da çökmüş, diğerinin haberi yok. Böyle bir bağlantı sessizce sürmüyor. İki yönden birine veri gönderilmeye çalışıldığı anda RST ile sıfırlanıyor. Kural genel: bağlantı henüz açık değilken gönderilmemiş bir şeyi onaylayan geçersiz bir ACK gelirse RST gidiyor. Gecikmiş eski bir SYN’in yarattığı sahte kurulum böyle iptal ediliyor.
Kuyruğun neden bu kadar kolay dolduğu da ölçülmüş. Bağlantı durumunu tutan yapı Linux 2.6.10’da 1.300 baytın üstünde yer kaplıyor; ölçümleri derleyen belge RFC 4987. SYN cookie savunması bu yükü tümden kaldırıyor. Sunucu SYN-RECEIVED için hiç durum ayırmıyor. Tutması gereken durumu ikinci mesajın sıra numarasına kodluyor. Üçüncü mesajın onay numarası o değeri geri getirince durum yeniden kuruluyor.
Kuyruk diye bir yapı olmayınca taşacak bir şey de kalmıyor. Bedeli, sıra numarasına sığmayan bazı TCP seçeneklerinin bu kipte kaybolması; çoğu sistemde varsayılan olarak kapalı duruyor. Sunucu durumu saklamak yerine karşı tarafa taşıtınca tüketilebilecek kaynağı da ona devretmiş oluyor. Aynı fikri, durumu senin makinene yazan çerez mekanizmasında yeniden göreceğiz.
Bu üç mesajın faturası ne kadar?
Bedeli ölçmenin birimi belli. El sıkışmanın maliyeti tam olarak bir gidiş-dönüş süresi, kısaca 1 RTT. Bağlantı kurup tek bir nesne çekmek ise 2 RTT artı aktarım süresi ediyor.
Bağlantısız gönderim kurulum için hiçbir gidiş-dönüş ödemiyordu; aradaki fark tam olarak bu bir tur. Taşıma el sıkışması ile güvenlik el sıkışması ayrı yapıldığında iki ardışık el sıkışma oluyor ve fatura ikiye katlanıyor. İkisini tek el sıkışmada birleştiren protokoller, ve oturum biletiyle kurulumu sıfır gidiş-dönüşe indiren yöntemler tam olarak bu bedeli hedef alıyor.
İlk SYN’in ağ için hiçbir ayrıcalığı yok. Yetkili sunucudan öğrenilen adres burada ilk kez bir bağlantı isteğinin üstüne yazılıyor. Paketin başına gelen dört gecikme onun için de aynen geçerli; sıradan bir paket gibi, alan adları arası yönlendirmeyle yol alıyor.
Kapanış tarafı ise kurulumdan pahalıya geliyor ve dört mesaj sürüyor: FIN, ACK, FIN, ACK. Sebebi bağlantının tam çift yönlü olması — iki ayrı yön var ve her yön ayrı ayrı kapanıyor. Buna yarı kapanma deniyor: bir uç “benim söyleyeceğim bitti” derken karşı taraf konuşmaya devam edebiliyor.
Kapanışın da kendi durum adları var ve iki taraf ayrı yollardan yürüyor:
| taraf | sıra | durumlar |
|---|---|---|
| kapatan | FIN gönderir → ACK alır → FIN alır → ACK gönderir | FIN-WAIT-1 → FIN-WAIT-2 → TIME-WAIT → CLOSED |
| kapatılan | FIN alır → ACK gönderir → uygulama kapatır → FIN gönderir | CLOSE-WAIT → LAST-ACK → CLOSED |
İkinci satırın ortasındaki italik adım bir arıza teşhisi taşıyor. CLOSE-WAIT durumundan çıkışı protokol değil uygulama tetikliyor: karşı taraf kapandı, çekirdek onayladı, ve şimdi sıra senin programının soketi kapatmasında. Program bunu yapmayı unutursa soket orada kalıyor. Bir sunucuda yığınla CLOSE-WAIT görüyorsan sorun ağda değil, kodda — bir yerde kapatılmayan bir tutamaç var. Buna karşılık yığınla TIME-WAIT görmek normaldir; o durumdan çıkışı zamanlayıcı sağlıyor.
Onay kendi FIN’iyle aynı segmentte birleşirse mesaj sayısı üçe iniyor. Kapanışı başlatan taraf TIME-WAIT durumunda en uzun segment ömrünün iki katı kadar bekliyor. RFC 9293 o ömrü 2 dakika sayıyor, yani bekleme 4 dakika.
Bu dört dakikanın iki ayrı gerekçesi var ve ikisi de bir arızayı önlüyor. Birincisi son onayın kaybolma ihtimali: ACK yolda düşerse karşı taraf FIN’ini yeniden gönderiyor ve onu tekrar onaylayacak birinin ayakta olması gerekiyor. İkincisi gecikmiş kopya: aynı four-tuple hemen yeniden kullanılırsa eski bağlantının yolda kalmış bir segmenti yeni konuşmanın içine düşebiliyor. Bekleme, o segmentlerin ömrünü doldurmasını garanti ediyor. Beşinci bölümde geçici port havuzunun neden daraldığını sormuştuk; cevabı bu dört dakika.
Buraya kadar anlatılan her adımı kendi makinende görebilirsin. Wireshark’ta tcp.flags.syn == 1 && tcp.flags.ack == 0 süzgeci yalnızca ilk mesajları listeliyor, yani bir sayfa açtığında kaç ayrı bağlantı kurulduğunu orada sayabilirsin. Komut satırında ise ss -tan çıktısını izle: aynı bağlantı sırayla SYN-SENT, ESTAB ve kapanıştan sonra TIME-WAIT satırlarında görünüyor.
Özet
Peki, ne öğrendik?
- Üçüncü mesaj bir doğrulama adımı: ilk isteği alan taraf onun taze mi bayat mı olduğunu bilemediği için gönderene doğrulatıyor.
- Kurulum aynı zamanda pazarlık: en büyük segment boyu yalnızca SYN bayraklı segmentlerde gönderilebildiği için boy anlaşması ya el sıkışmada olur ya hiç olmaz.
- Başlangıç sıra numarası bir güvenlik parametresi: tahmin edilebilirse yol üstünde hiç bulunmayan bir saldırgan kurulmuş bağlantıya veri sokabiliyor.
- Kaynak ayırma saldırının hedefi: yarı açık bağlantı kuyruğu sahte kaynak adresli SYN’lerle doluyor ve gerçek istemciler kapıda kalıyor.
- Bağlantının faturası bir gidiş-dönüş: veri gitmeden önce ödenen bu tur, garanti vermeyen taşımada hiç ödenmiyor.
Üç mesaj bitti, iki uç da karşısının orada olduğunu biliyor ve sıra numaraları anlaşıldı. Bağlantı kuruldu; peki aradaki herkes ne yazdığını okuyabilir mi?
8. bölüme devam et: Simetrik Şifreleme