Bölüm 7: Bağlantısız Taşıma: UDP
Ağlar'a “Sen”i Katmak kitabının bir bölümü: adres çubuğuna yazdığın tek bir isteğin peşinden bakırla fiberin fiziğine inip karşı taraftan geri dönen uzun bir teknik yolculuk.
Kısım 2: Bağlantı Kuruluyor (Bölüm 6-12)
Tüm bölümler
- Giriş
- Adres Çubuğundan İsteğe
- Paket Anahtarlamalı Yol
- İsimden Adrese
- DNS Kayıtları
- Ö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
- Hizmet ve Protokol
- Encapsulation ve Başlıklar
- Paket Yakalama ve Çözümleme
- Ağ Interface Kartı
- Fiziksel Adresleme
- Hata Sezme ve CRC
- Adres Çözümleme: ARP
- Ortam Erişimi: CSMA/CD
- Switch'ler
- 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
- Router Mimarisi
- Kuyruk Yönetimi
- Cihaz Yapılandırma
- Routing Protokolleri
- Kontrol Düzlemi ve SDN
- Ağ İzleme ve Yönetimi
- Alanlar Arası Routing
- Adres Çevirisi
- Ara Kutular
- Tünelleme ve IPsec
- Firewall'lar
- Ağ Saldırıları
- Operatör ve Metro Ağları
- Bitten Sinyale
- Sembol Hızı ve Kanal Kapasitesi
- Multiplexing Teknikleri
- İletim Ortamları
- Bakır Kablo Sonlandırma
- Fiber Sonlandırma
- Fiber Optik İletim
- Bakır Erişim Ağı: DSL
- DSL'de Hız ve Mesafe
- Pasif Optik Ağlar
- Kablo Erişim Ağları
- Kablo Modem ve CMTS
- Denizaltı Kabloları
- Veri Merkezi Ağları
- Encapsulation Çözme
- Güvenilir Aktarım
- Tıkanıklık Denetimi
- Trafik Çözümleme
- Gecikme Bütçesi
- Soket Programlama
- Eşten Eşe ve Protokol Tasarımı
- Uyarlanır Video Akışı
- Gerçek Zamanlı Ses ve Görüntü
- Kablosuz Sensör Ağlarının Mimarisi
- Sensör Ağlarında Ortam Erişimi
- Sensör Ağlarında Yönlendirme ve IP
- Zaman Eşitleme ve Konum Bulma
- Sensör Ağı Uygulamaları
- Mobil Kablosuz Sensör Ağları
- Son Söz
Vermiyor. Taşıma protokollerinin kimi teslimi, sırayı ve hızı üstleniyor, kimi hiçbirini. En kolayı hiçbir vaatte bulunmayanı: isim sorgusunun 53 numaralı porta “bağlantısız taşımayla”, yani UDP ile gittiğini söyleyip geçmiştim.
UDP’nin tanımı 1980 tarihli RFC 768’de duruyor ve belgenin tamamı üç sayfa. Hiçbir şey vaat etmeyen bir taşıma neye yarıyor?
Sekiz bayt, dört alan
Başlığın tamamı bu:
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 port | hedef port |
+-------------------------------+-------------------------------+
| uzunluk | checksum |
+-------------------------------+-------------------------------+
| yük (payload) |Dört alan, her biri 16 bit, toplam sekiz bayt. Karşılaştırma için: bir sonraki bölümde göreceğimiz bağlantı kuran taşımanın başlığı en az yirmi bayt ve on bir alan taşıyor.
Alanları soldan sağa okuyalım. Kaynak ve hedef port, four-tuple’ın iki ayağı; makine gelen parçayı doğru sokete bunlarla bırakıyor. Kaynak port zorunlu bile değil, cevap beklemiyorsan sıfır bırakabiliyorsun.
Uzunluk alanı başlık dahil parçanın bayt sayısını taşıyor. On altı bit olduğu için üst sınır 65.535 bayt, yükte kalan da 65.527. IPv4’te tavan biraz daha aşağıda, 65.507 bayt, çünkü IP paketinin kendi uzunluk alanı da 16 bit ve kendi başlığını da aynı sayının içine sığdırmak zorunda. Pratikte bu sınıra hiç yaklaşılmıyor: yol üstündeki en küçük frame’e (çerçeveye) sığmayan bir parça yolda bölünüyor ve bölünen parçalardan biri kaybolursa tamamı çöpe gidiyor.
Dördüncü alan checksum (Türkçesiyle sağlama toplamı) ve ilginç olan o. Kitabın geri kalanında iki adı da göreceksin; ikisi aynı şey.
Hesaba giren şey yalnızca yukarıdaki sekiz bayt ile yük değil. Gönderen, hesabı yapmadan önce var olmayan bir başlık uyduruyor: içinde IP kaynak adresi, IP hedef adresi, protokol numarası ve UDP uzunluğu var. Adı pseudo-header ve telde hiç gitmiyor; yalnızca iki uçta da aynı biçimde kurulup hesaba katılıyor.
Neden? Çünkü UDP’nin tek başına cevaplayamadığı bir soru var: bu datagram gerçekten bana mı geldi? Bir router’ın belleğinde hedef adres bozulursa paket yanlış makineye düşer; o makinenin UDP katmanı, kendi adresini pseudo-header’a koyup hesapladığında checksum tutmaz ve paketi atar. Adresi hesaba katmayan bir checksum bu hatayı hiç göremezdi.
Bunun bir bedeli var ve adını koymak gerekiyor: transport layer, altındaki katmanın alanlarını okuyor. Katman sınırının kasten delindiği yerlerden biri burası. Ve delinmesinin somut bir bedeli daha var: adres çevirisi, IP başlığındaki adresi değiştirdiği için transport layer checksum’ını da yeniden hesaplamak zorunda kalıyor.
Checksum ne yakalar, ne kaçırır?
Hesap sandığından basit. Gönderen taraf parçanın içeriğini 16 bitlik sayılar dizisi sayıyor, hepsini topluyor, en anlamlı bitten taşan eldeyi sonuca geri ekliyor ve çıkan sayının tersini alana yazıyor. Adreslerin de hesaba katılması, parçanın yanlış makineye teslim edildiğini yakalamayı sağlıyor.
Alıcı aynı hesabı tekrarlıyor. Sonuç tutmuyorsa parça bozulmuş demektir ve sessizce atılıyor; kimse haber vermiyor.
Şimdi bu korumanın sınırı. İki ayrı 16 bitlik sayıda birbirini götüren iki bit dönerse toplam değişmiyor:
1110 0110 0110 0110 -> 1110 0110 0110 0111 (son bit 0 -> 1)
1101 0101 0101 0101 -> 1101 0101 0101 0100 (son bit 1 -> 0)
----------------------- -----------------------
toplam aynı toplam aynıBitler değişti, toplam değişmedi, alıcı hiçbir şey fark etmedi. Bu yüzden checksum’a hata saptama deniyor, hata düzeltme değil; üstelik saptaması da eksiksiz değil.
Bir tuhaflık daha: alan isteğe bağlı. Sıfır yazılırsa “ben hiç hesaplamadım” anlamına geliyor ve alıcı denetlemiyor. Bu esneklik protokolün ilk tasarımından kalma; IPv6 üstünde ise checksum zorunlu, çünkü orada IP başlığının kendi sağlaması yok.
DerinleşmeBu kadar zayıf bir koruma neden hâlâ kullanılıyor?
Checksum’ın zayıflığı 1980’de de biliniyordu. Yerine daha güçlü bir yöntem koymamanın üç sebebi var ve üçü de hâlâ geçerli.
Birincisi maliyet. Birler tümleyeni toplaması, dönemin donanımında birkaç talimatla yapılabilen en ucuz işlemdi ve bugün de öyle: toplama, ekleme, tersini alma. Daha güçlü yöntemler bit düzeyinde bölme ya da çarpma istiyor. Her paket için, saniyede milyonlarca kez.
İkincisi katmanlı savunma sağlıyor, çünkü bu yolun tek denetimi olmuyor. Kablo düzeyinde her frame’in kendi ve çok daha güçlü bir denetimi var; bozulmuş bir frame’in transport layer’ına kadar gelmesi zaten beklenmiyor. Taşımadaki hesap, o denetimin kapsamadığı yeri kolluyor: router’ın belleğinde ya da kartın tamponunda dönen bir bit, kablo denetiminden sonra oluştuğu için orada yakalanamaz.
Üçüncüsü end-to-end argument (uçtan uca savı). Aradaki her cihaza güvenmek yerine, denetimi yolun iki ucuna koymak. Zayıf bir uçtan uca denetim, güçlü ama parça parça denetimlerin yakalayamadığı bir sınıf hatayı yakalıyor.
Peki yetiyor mu? Yetmiyor. 2000’de yayımlanan bir ölçüm, bağlantı düzeyindeki güçlü denetime rağmen her 1.100 ile 32.000 paketten birinin taşıma checksum’ına takıldığını gösterdi. Hatalar kablo denetiminden sonra, cihazların içinde doğuyordu ve checksum’ın göremediği kadarı da uçlara varıyordu. Bu yüzden veri bütünlüğüne gerçekten ihtiyaç duyan katmanlar kendi denetimlerini kuruyor. Dosya aktarım protokolleri özet alıyor, şifreli taşımalar bütünlük etiketi taşıyor, depolama sistemleri kendi sağlamalarını yazıyor.
Bir denetimin gücü, onu kimin ve nerede yaptığından ayrı düşünülemez. Aynı zayıf hesap, tek başına dayanılırsa yetersiz; katmanlı bir savunmanın parçasıysa yerinde.
Hiçbir söz vermemek neden işe yarıyor?
Bu taşıma teslim sözü vermiyor, sıra sözü vermiyor, yineleme koruması vermiyor. Kaybolan paketi yeniden göndermiyor, sıralamayı düzeltmiyor, hızını ağa göre kısmıyor. Standart bunu gizlemiyor bile; teslimin garanti edilmediği metnin kendisinde yazılı.
Karşılığında iki şey kazanıyorsun.
Birincisi zaman: bağlantı kurulmadığı için baştan bir gidiş-dönüş ödemiyorsun. İlk paket doğrudan veriyi taşıyor. Bir isim sorgusu tek paket gidip tek paket dönüyor ve milisaniyeler içinde bitiyor. El sıkışan bir taşımada aynı sorgu, daha soru sorulmadan bir tur harcardı.
İkincisi mesaj sınırı. Gönderdiğin her mesaj alıcıya ayrı bir mesaj olarak çıkıyor; iki mesaj birleşmiyor, bir mesaj ikiye bölünmüş gibi okunmuyor. Stream taşıyan bir protokolde nerede bittiğini kendin işaretlemek zorundasın. Burada sınır zaten korunuyor.
Bir ayrıntı da soket tarafında. Bağlantısız bir sokete de “bağlan” diyebiliyorsun; bu gerçek bir bağlantı kurmuyor, yalnızca karşı ucu sabitliyor. Kazancı şu: kernel artık o sokete hangi hataların ait olduğunu bilebiliyor ve karşı makinenin “bu portta kimse yok” cevabını sana iletebiliyor. Sabitlemezsen o cevap Linux’ta ve BSD ailesinde sessizce düşüyor. Windows bu konuda ayrışıyor ve hatayı sabitlenmemiş sokete de iletiyor; 71. bölümde bunu çalışan bir kodda göreceksin.
Bu yüzden bu taşımayı seçen uygulamalar birbirine benziyor: isim çözümlemesi, ağ yönetimi, sesli ve görüntülü görüşme, oyunlar. Ortak noktaları, geç gelen verinin hiç gelmemiş sayılması. Kaybolan bir ses paketini yeniden istemek anlamsız; o an çoktan geçti.
Şaşırtıcı olan, en yeni web protokolünün de bunun üstüne kurulmuş olması. HTTP/3 garantileri bırakmıyor, onları taşımadan alıp uygulamanın içine taşıyor: yeniden gönderim de tıkanıklık denetimi de var, ama artık kernel’da değil uygulamada. Sebebini 15. bölümde açacağız.
El sıkışma olmamasının bir de karanlık tarafı var. Kaynak adresi doğrulayan hiçbir adım olmadığı için gönderen, paketin üstüne başkasının adresini yazabiliyor. Cevap o adrese gidiyor.
Sorun, cevabın sorudan büyük olmasıyla ciddileşiyor. Kısa bir isim sorgusuna çok daha uzun bir cevap dönebiliyor; saldıran taraf küçük paketler gönderip kurbanın üstüne katlanmış bir trafik yığıyor. Buna yükseltme saldırısı deniyor ve bağlantısız taşımanın en bilinen kötüye kullanımı. Savunması da protokolde değil, işletmede: açık resolver’ı herkese kapatmak, cevap hızını sınırlamak, kaynak adresi kendi ağının çıkışında doğrulamak.
Kendi makinende görmek istersen bunlar soyut kalmasın. Wireshark’ta udp.port == 53 süzgeci, ya da komut satırında tcpdump -n udp port 53, bir sayfa açtığın anda giden isim sorgularını dökecek. Her satırda göreceğin şey tek bir paket: soru gitti, cevap geldi, arada başka hiçbir şey yok.
Özet
- Başlık sekiz bayt ve dört alan: kaynak port, hedef port, uzunluk, checksum. Bağlantı kuran taşımanın başlığı bunun en az iki buçuk katı.
- Checksum hata saptar, düzeltmez ve saptaması da eksiksiz değil: birbirini götüren iki bit dönmesi toplamı hiç değiştirmiyor.
- Hiçbir söz vermemenin karşılığı zaman ve sınır. El sıkışma olmadığı için ilk paket doğrudan veri taşıyor; mesaj sınırları da alıcıda korunuyor.
- Bu taşımayı seçen uygulamaların ortak noktası, geç gelen verinin işe yaramaması.
İsim sorgusu bu yüzden tek pakette bitti. Ama sayfanın kendisi tek pakete sığmıyor ve kaybolan bir parçayı kimsenin fark etmemesi kabul edilebilir değil. Garanti istemeyen taşımayı gördün; peki karşı taraf senin geldiğini nereden bilecek?
8. bölüme devam et: Üç Adımlı El Sıkışma