Ana içeriğe geç

Bölüm 7: Bağlantısız Taşıma: UDP

7 dakikalık okumaGüncelleme:

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
  1. Giriş
  2. Adres Çubuğundan İsteğe
  3. Paket Anahtarlamalı Yol
  4. İsimden Adrese
  5. DNS Kayıtları
  6. Önbellek, Tazelik ve Güven
  7. Port Numarası ve Soket
  8. Bağlantısız Taşıma: UDP
  9. Üç Adımlı El Sıkışma
  10. Simetrik Şifreleme
  11. Açık Anahtarlı Kriptografi
  12. TLS El Sıkışması
  13. Sertifika Zinciri
  14. HTTP Mesajının Anatomisi
  15. Durum, Çerez ve Oturum
  16. HTTP/2'den HTTP/3'e
  17. İçerik Dağıtım Ağları
  18. Diğer Uygulama Protokolleri
  19. Katmanlı Mimari
  20. Hizmet ve Protokol
  21. Encapsulation ve Başlıklar
  22. Paket Yakalama ve Çözümleme
  23. Ağ Interface Kartı
  24. Fiziksel Adresleme
  25. Hata Sezme ve CRC
  26. Adres Çözümleme: ARP
  27. Ortam Erişimi: CSMA/CD
  28. Switch'ler
  29. Ağ Topolojileri
  30. Sanal Yerel Ağlar
  31. Kablosuz Erişim: 802.11
  32. Radyo Kanalı ve Kapasite
  33. Kablosuz Ağ Güvenliği
  34. Hücresel Ağlar
  35. Spektrum ve Kuşaklar
  36. Hareketlilik ve Aktarma
  37. Adres Kiralama: DHCP
  38. Adresin Anatomisi
  39. Adres Tükenmesi ve IPv6
  40. Router Mimarisi
  41. Kuyruk Yönetimi
  42. Cihaz Yapılandırma
  43. Routing Protokolleri
  44. Kontrol Düzlemi ve SDN
  45. Ağ İzleme ve Yönetimi
  46. Alanlar Arası Routing
  47. Adres Çevirisi
  48. Ara Kutular
  49. Tünelleme ve IPsec
  50. Firewall'lar
  51. Ağ Saldırıları
  52. Operatör ve Metro Ağları
  53. Bitten Sinyale
  54. Sembol Hızı ve Kanal Kapasitesi
  55. Multiplexing Teknikleri
  56. İletim Ortamları
  57. Bakır Kablo Sonlandırma
  58. Fiber Sonlandırma
  59. Fiber Optik İletim
  60. Bakır Erişim Ağı: DSL
  61. DSL'de Hız ve Mesafe
  62. Pasif Optik Ağlar
  63. Kablo Erişim Ağları
  64. Kablo Modem ve CMTS
  65. Denizaltı Kabloları
  66. Veri Merkezi Ağları
  67. Encapsulation Çözme
  68. Güvenilir Aktarım
  69. Tıkanıklık Denetimi
  70. Trafik Çözümleme
  71. Gecikme Bütçesi
  72. Soket Programlama
  73. Eşten Eşe ve Protokol Tasarımı
  74. Uyarlanır Video Akışı
  75. Gerçek Zamanlı Ses ve Görüntü
  76. Kablosuz Sensör Ağlarının Mimarisi
  77. Sensör Ağlarında Ortam Erişimi
  78. Sensör Ağlarında Yönlendirme ve IP
  79. Zaman Eşitleme ve Konum Bulma
  80. Sensör Ağı Uygulamaları
  81. Mobil Kablosuz Sensör Ağları
  82. 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