Bölüm 18:Kapsülleme ve Başlıklar
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
Katmanların birbirine ne sözü verdiğini kurduk. Söylemediğim şey, komşuya tam olarak neyin uzatıldığıydı.
Uzatılan şey çıplak veri değil. Her katman kendisine geleni bir zarfa koyup uzatıyor, ve o zarfın adı başlık. Peki zarfın içinde kaç zarf var?
Dört basamak, tek yük
Uygulama katmanı elindeki mesajı taşımaya veriyor ve taşıma onu hiç açmıyor. İçindeki baytların ne anlama geldiğine bakmadan başına kendi başlığını ekliyor; ortaya bir segment çıkıyor.
Ağ katmanı aynı işi bir basamak aşağıda tekrarlıyor. Aldığı segmentin tamamını, taşımanın az önce yazdığı başlık dahil, tek parça yük sayıyor. Kendi başlığını onun da önüne ekliyor: datagram. Son basamak bağ katmanı; o da datagramı olduğu gibi alıp sarıyor ve ortaya çerçeve çıkıyor.
uygulama [ mesaj ]
taşıma [ TCP | mesaj ] -> segment
ağ [ IP | TCP | mesaj ] -> datagram
bağ [ ETH | IP | TCP | mesaj | FCS ] -> çerçeveKargo şirketine dönersek, her basamak yalnızca kendi etiketini yazar. Bir öncekinin etiketi artık paketin parçasıdır.
Aynı merdiveni baytlarla izlemek istersen:
- Uygulama yalnızca mesajı görüyor. Tarayıcının sokete yazdığı şey 1.460 baytlık düz veri. Bu noktada hiçbir başlık yok; aşağıdaki üç satırda değişmeden kalacak olan yük bu.
- Taşıma 20 bayt ekliyor: segment. TCP başlığı mesajın önüne geçiyor. İçine bakmıyor, açmıyor, yorumlamıyor — mesajın tamamı onun için tek parça yük. Toplam 1.480 bayt.
- Ağ 20 bayt daha ekliyor: datagram. IP başlığı bu kez TCP başlığını da yük sayıyor.
(N)-PDU = (N−1)-SDUdenklemi tam burada işliyor: bir üstün paketi, bir altın ham verisi. Toplam 1.500 bayt. - Bağ hem baştan hem sondan sarıyor: çerçeve. Ethernet 14 baytlık başlığı öne, 4 baytlık
FCSsağlamasını sona koyuyor. Sondan yazan tek katman bu. Toplam 1.518 bayt. - Telde fatura biraz daha kabarıyor. Çerçevenin önüne 8 baytlık önsöz, arkasına 12 baytlık boşluk giriyor. Kanalda harcanan 1.538 baytın 1.460'ı veri: %94,9. Kutular ölçekli değil — gerçek oranda
TCPbaşlığı bu genişliğin yedide biri kadar olurdu.
Son satırdaki FCS dikkatini çekmiş olmalı. Çerçeve hem başlıkla hem kuyrukla sarılıyor; sondan yazan tek katman bağ katmanı.
Her başlık, onu ekleyen katmanın kendi hizmetini kurmak için ihtiyaç duyduğu alanları taşıyor. Üstteki katman o alanları hiç görmüyor. Alttaki katman görüyor ama anlamlarını bilmiyor. Kapsülleme dediğimiz şey tam olarak bu.
Başlıkta tam olarak ne var?
Seçenek taşımayan bir TCP başlığı 20 bayt. Başlık sabit değil; içinde head len adında bir alan var ve başlığın kendi uzunluğunu bildiriyor, çünkü seçeneklerle uzayabiliyor. Yük kısmı da değişken uzunlukta; uygulamanın sokete yazdığı kadar.
Seçeneksiz IPv4 başlığı da 20 bayt. İkisi birlikte her yükün üstüne 40 baytlık sabit bir zarf bindiriyor.
IPv4 başlığını tahmin etmeye gerek yok; RFC 791 alanları bit bit sayıyor. Başlık 32 bitlik satırlar hâlinde okunur ve seçeneksiz hâli tam beş satırdır:
| bit | alan | boy | ne yapıyor |
|---|---|---|---|
| 0 | Sürüm | 4 bit | IPv4 için değeri 4; alıcı başlığı okumadan önce buna bakar |
| 4 | IHL | 4 bit | başlığın kendi uzunluğu, 32 bitlik kelime cinsinden |
| 8 | DSCP | 6 bit | paketin hangi hizmet sınıfına ait olduğu |
| 14 | ECN | 2 bit | yol üstünde tıkanıklık görülüp görülmediği |
| 16 | Toplam Uzunluk | 16 bit | başlık dahil bütün datagram |
| 32 | Kimlik | 16 bit | aynı datagramdan doğan parçaları eşleştirir |
| 48 | Bayraklar | 3 bit | ayrılmış · DF (bölme) · MF (arkadan parça var) |
| 51 | Parça Ofseti | 13 bit | parçanın özgün yükteki yeri, 8 baytlık birimle |
| 64 | TTL | 8 bit | her yönlendiricide bir azalır, sıfırlanınca paket ölür |
| 72 | Protokol | 8 bit | yükün sahibi: 1 ICMP, 6 TCP, 17 UDP |
| 80 | Başlık Sağlaması | 16 bit | yalnızca başlığı korur, yükü değil |
| 96 | Kaynak Adres | 32 bit | gönderenin IP adresi |
| 128 | Hedef Adres | 32 bit | alıcının IP adresi |
| 160 | Seçenekler | 0-40 bayt | yalnızca IHL beşten büyükse vardır |
Dört alan ilk okumada kolayca kayıyor, oysa dördü de kitabın başka bölümlerinde karşına çıkacak.
IHL başlığın uzunluğunu bayt değil, 32 bitlik kelime cinsinden verir. Seçeneksiz başlıkta değeri 5’tir: 5 × 4 = 20 bayt. Alan 4 bit olduğu için en büyük değeri 15, yani başlığın tavanı 60 bayt. Seçeneklere ayrılabilecek yer bu yüzden 40 baytla sınırlı — bu bir tasarım tercihi değil, dört bitin matematiği.
DSCP ve ECN aslında tek bir 8 bitlik alandan bölündü. Eski adı Hizmet Türü’ydü; RFC 2474 üstteki altı biti hizmet sınıfına, RFC 3168 alttaki iki biti tıkanıklık bildirimine ayırdı. İlki paket zamanlamada, ikincisi tıkanıklık denetiminde işe yarıyor. İkisi de aynı bayttan çıkıyor.
Bayraklardaki DF biti “bu paketi bölme” demek. Bölmesi gereken bir yönlendirici DF bitini görürse paketi düşürüp gönderene bir ICMP mesajıyla haber verir ve o mesajın içinde bir sonraki atlamanın MTU’sunu yazar. Gönderen böylece yol boyunca sığacak en büyük boyu adım adım öğrenir; yöntemin adı yol MTU keşfi. O ICMP mesajları bir güvenlik duvarı tarafından susturulursa yöntem sessizce çöker; sahadaki hâlini tünelleri kurarken adım adım izleyeceğiz.
Başlık sağlaması yalnızca başlığı korur, yükü değil. Sebep basit: TTL her atlamada değiştiği için sağlamanın da her yönlendiricide yeniden hesaplanması gerekiyor, ve yükü de kapsasaydı bu hesap her atlamada bütün paket üstünde yapılacaktı. IPv6 alanı tamamen kaldırarak aynı sorunu kökünden çözdü.
Protokol alanı küçük ama işi büyük: yükün hangi üst katman protokolüne ait olduğunu söylüyor, TCP mi UDP mi.
Çerçevenin alanları da sırayla belli; boyları toplandığında zarfın maliyeti çıkıyor:
| alan | boy | ne yapıyor |
|---|---|---|
| önsöz | 8 bayt | alıcıyı çerçevenin başına kilitler |
| hedef adres | 6 bayt | çerçeveyi kimin alacağını söyler |
| kaynak adres | 6 bayt | gönderenin aynı biçimdeki adresi |
| tür alanı | 2 bayt | içerideki protokolü söyler |
| veri | 46-1.500 bayt | datagram buraya girer |
| FCS | 4 bayt | çerçevenin kuyruğu |
Bu iki adresin nasıl kurulduğunu burada kasten boş bırakıyorum. Alanların genişliğini biliyorsun; içlerindeki değerin ne anlama geldiğini 21. bölümde dolduracağız.
Adresler, tür alanı ve FCS birlikte 18 bayt tutuyor. Önsöz (preamble) hariç azami sade çerçeve bu yüzden 1.518 bayt. Araya 4 baytlık bir 802.1Q etiketi girerse tavan 1.522 bayta çıkıyor; etiketin ilk iki baytı 0x8100 tür tanımlayıcısını taşır ve o tanımlayıcıyı bilmeyen bir istasyon çerçeveyi bilinmeyen tür sanıp atar.

Tür alanı (EtherType) 0x0800 ise içeride IP var, 0x0806 ise ARP. FCS’nin içine yazılan değer ise bir CRC-32 sağlaması; hesabın kendisi ilerideki bir bölümün işi.
Her zarf bir sonrakini nasıl gösteriyor?
Kapsüllemenin asıl inceliği zarfları sarmakta değil, açarken hangi sırayla açılacağını bilmekte. Alıcıya gelen şey bir bayt dizisi. Nerede bittiğini, içinde ne olduğunu ve sonraki başlığın hangi protokole ait olduğunu ona kimse söylemiyor — bunların hepsi zarfın kendi içinde yazılı.
Her başlığın içinde, bir sonraki başlığın kim olduğunu söyleyen bir alan var. Bu alanlar bir zincir kuruyor ve zincir, bayt dizisini adım adım çözüyor:
| bulunduğun başlık | işaretçi alanı | değer | sonraki başlık |
|---|---|---|---|
| Ethernet | tür alanı | 0x0800 | IPv4 |
| Ethernet | tür alanı | 0x0806 | ARP |
| Ethernet | tür alanı | 0x86DD | IPv6 |
| Ethernet | tür alanı | 0x8100 | VLAN etiketi, sonra yeniden tür alanı |
| IPv4 / IPv6 | protokol | 1 / 58 | ICMP |
| IPv4 / IPv6 | protokol | 6 | TCP |
| IPv4 / IPv6 | protokol | 17 | UDP |
| IPv4 / IPv6 | protokol | 47 | GRE tüneli |
| IPv4 / IPv6 | protokol | 50 | IPsec ESP |
| TCP / UDP | hedef port | 443 | TLS, ardından HTTP |
| TCP / UDP | hedef port | 53 | DNS |
Zincirin bu kadar sıradan görünmesi aldatıcı. Bu üç alan, yığının tamamının değiştirilebilir olmasını sağlayan şey. Ethernet, içinde IP taşıdığını bilmiyor; yalnızca 0x0800 diye bir sayı taşıyor ve o sayının anlamını bir tabloya bırakıyor. IPv6 ortaya çıktığında Ethernet’in tek bir satırı bile değişmedi; tabloya yeni bir sayı eklendi. Katmanları gerçekten ayıran şey, başlıkta bir isim değil bir numara taşımaktır.
Zarfları açmanın adı kapsülleme çözme ve sarmanın tam tersi sırayla yürüyor. Alıcı kartı çerçeveyi alıyor, FCS’yi yeniden hesaplayıp yazandan farklı çıkarsa çerçeveyi sessizce atıyor. Sağlamsa 14 baytlık başlığı çıkarıp kalanı IP’ye uzatıyor. IP kendi başlığını doğruluyor, hedef adres kendisiyse başlığı çıkarıp protokol alanının gösterdiği yere — diyelim TCP’ye — uzatıyor. TCP checksum’ı denetliyor, hedef porta bakıp doğru sokete bırakıyor. Her kat kendi zarfını açıyor, kendi denetimini yapıyor ve bir üstteki katmanın zarfına hiç dokunmuyor.
Kapsüllemeyi tek cümleye indirmek gerekirse: her katman, bir üstündekinin verdiği her şeyi anlamsız bir yük sayar; ne olduğunu yalnızca bir sayıyla not eder ve o sayıyı okumayı karşı taraftaki eşine bırakır.
Yük hatta sığmazsa?
Bir bağlantı üzerinden gidebilecek en büyük çerçevenin veri alanına MTU deniyor. Ethernet’te 1.500 bayt. Bu bir ağ katmanı kararı değil, bağ katmanı kararı: değeri ikinci katmanda hangi protokolün çalıştığına göre değişiyor. Yol boyunca tek bir sabit değer yok.
Sayı yükseltilebilir de. Bir anahtar bugün 9.720 bayta kadar jumbo çerçeve taşıyabiliyor; aynı veriyi altı kat daha az çerçeveyle göndermek, çerçeve başına düşen 18 baytlık zarfı altı kat fazla verinin üstüne yaymak demek. Yine de bu yetenek standart dışı ve yerelde kalıyor. Sebebi yolun kendisinde. Bir yol, üstündeki en dar bağlantı kadar geniştir, ve yol üstündeki tek bir port jumbo çerçeveyi tanımıyorsa onu sessizce düşürüyor. Uçların birlikte büyütmeyi pazarlık edeceği bir mekanizma da yok; MTU her bağlantının kendi kararı. Büyük MTU bu yüzden ancak kapalı alanlarda işe yarıyor: veri merkezinin içi, depolama ağı, iki yönlendirici arasındaki tek bir hat. Oralarda iki uç da aynı yönetimin elinde.
Geriye kalanı hesaplamak kolay. 1.500 baytlık veri alanından IP başlığının 20 baytını ve TCP başlığının 20 baytını düşünce elde 1.460 bayt kalıyor. SYN paketiyle pazarlığa açılan en büyük segment boyunun tipik değeri de tam olarak bu.
Peki yük bu sınırı aşarsa? IPv4 datagramı bölüyor; işlemin adı parçalama. Her parça kendi başına tam bir IP datagramı ve kendi başlığını taşıyor.
Somut bir örnek kuralım. 2.048 baytlık bir datagramın yükü 2.028 bayt. MTU’su 1.500 olan bir bağlantıya girdiğinde ikiye ayrılıyor:
parça 1: veri 1.480 bayt · ofset 0 · MF=1 · toplam uzunluk 1.500
parça 2: veri 548 bayt · ofset 185 · MF=0 · toplam uzunluk 568Parçaları birbirine bağlayan üç alan var ve üçü de IP başlığında duruyor. Kimlik, iki parçanın aynı datagramdan doğduğunu söylüyor. Bayrak alanındaki MF biti arkadan başka parça gelip gelmediğini bildiriyor. Ofset ise parçanın özgün veri alanındaki yerini veriyor, o da bayt cinsinden değil, 64 bitin yani 8 baytın katları cinsinden. 1.480’i sekize bölünce 185 çıkıyor. Son parça hariç her parçanın verisi bu yüzden sekizin katı olmak zorunda.
Bir ayrıntı daha: TCP başlığı yalnızca ilk parçada duruyor. IP bölerken yükün içine bakmıyor; ikinci parça onun için sıradan bir bayt dizisi.
Parçaları birleştiren tek yer hedef uç sistem. Bedeli şu: bir parça yol boyunca yalnızca küçülebiliyor. IPv6 bu işi sabit başlıktan çıkardı; 40 baytlık başlıkta ne parçalama var ne checksum, amaç yönlendiricide işlemeyi hızlandırmak. Gerekirse parçalama ayrı bir uzatma başlığına iniyor.
Bir terim notu da düşeyim. OSI belgelerinde bu işleme segmentation, TCP/IP belgelerinde fragmentation deniyor. İkisi aynı şeyi anlatıyor.
Zarfın bedeli ne kadar?
Tel üstünde bir yükün taşıdığı toplam zarf 58 bayt: 20 TCP, 20 IP, 18 Ethernet.
1.460 baytlık dolu bir yükle çerçeve 1.518 bayta çıkıyor ve zarfın payı %3,8 oluyor. Şimdi yükü küçült. İstek satırı ve başlıklarla kurulan sade bir HTTP isteği 480 bayt tutsun. Aynı 58 bayt ekleniyor, toplam 538 bayt, zarfın payı %10,8. Zarf hiç değişmedi. Yük küçüldükçe oransal olarak şişti.
Uç vakayı da görelim. Yüksüz bir ACK, 20 baytlık TCP başlığı ile 20 baytlık IP başlığından ibaret: 40 baytlık bir datagram. Ethernet veri alanının alt sınırı 46 bayt olduğu için aradaki fark dolgu ile kapatılıyor ve çerçeve 64 bayta çıkıyor. Telden geçen her şey zarf.
O dolgu baytları ağ katmanına kadar çıkıyor. Onları ayıklayan şey IP başlığındaki uzunluk alanı.
Kanalın ödediği fatura çerçeve boyuyla değil toplamla ölçülüyor. 1.500 baytlık veri taşıyan bir çerçevenin kanal maliyeti, önsöz ve çerçeveler arası boşluk dahil, 1.538 bayt. Yükün payı %97,5. 10 Mbit/s’lik bir hatta bu saniyede 812 çerçeve demek. Aynı hatta asgari boy çerçeveler saniyede 14.880 adet geçiyor ve yalnızca 5.475.840 bit veri taşıyor: kanalın %54,7’si.
Ek yükün bit karşılığı da sabit: 64 bit önsöz, 96 bit iki adres, 16 bit tür alanı, 32 bit FCS. 10 Mbit/s’te çerçeveler arası boşluk 9,6 µs, yani 96 bit süresi. Toplamı 304 bit süresi.
Küçük çerçevenin bir yararı da var. Bozulan bir çerçevede yeniden gönderilecek bit sayısı daha az. Çoklama ile tek bağlantıya sığdırılan istekler de aynı hesabın içinde; zarf yok olmuyor, yalnızca daha çok yükün üstüne yayılıyor.
Bütün bunları kendi makinende görebilirsin:
ip link show
sudo tcpdump -n -e -c 5 'tcp port 443'İlk komut her arayüzün yanına mtu 1500 yazacak. İkincisi her satırın başında çerçevenin kaynak ve hedef adresini, ethertype IPv4 (0x0800) etiketini ve çerçevenin bayt cinsinden boyunu dökecek. Windows tarafında aynı değeri netsh interface ipv4 show subinterfaces komutu veriyor.
Özet
Peki, ne öğrendik?
- Kapsülleme dört basamaklı bir merdiven: mesaj segmente, segment datagrama, datagram çerçeveye giriyor ve her basamak bir öncekinin tamamını yük sayıyor.
- Her başlık kendi katmanının işi için var: üstteki alanları görmüyor, alttaki anlamlarını bilmiyor, ve sondan kuyruk ekleyen tek katman bağ katmanı.
- IPv4 başlığı beş satır, on üç alandır:
IHLbaşlığın tavanını 60 bayta kilitler,DSCPileECNaynı bayttan bölünmüştür,DFbiti yol MTU keşfini başlatır ve checksum yalnızca başlığı korur.- Bağlayıcı alanlar zinciri kuruyor: çerçevedeki tür alanı, IP’deki Protokol ve taşımadaki port numarası yükü doğru üst katmana yönlendiriyor.
- MTU aşılırsa datagram bölünüyor: Kimlik, Bayrak ve Ofset parçaları birbirine bağlıyor, birleştirmeyi ise yalnızca hedef uç yapıyor.
Zarfları saydık, alanlarını adlandırdık, bedelini hesapladık. Ama buraya kadar hepsi anlatı olarak kaldı. Zarflar gerçekten orada mı, bunu kendi gözünle görebilir misin?
19. bölüme devam et: Paket Yakalama ve Çözümleme