Ana içeriğe geç

Bölüm 5:Port Numarası ve Soket

11 dakikalık okumaGüncelleme:

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
  1. Giriş
  2. Adres Çubuğundan İsteğe
  3. Paket Anahtarlamalı Yol
  4. İsimden Adrese
  5. Önbellek, Tazelik ve Güven
  6. Port Numarası ve Soket
  7. Bağlantısız Taşıma: UDP
  8. Üç Adımlı El Sıkışma
  9. Simetrik Şifreleme
  10. Açık Anahtarlı Kriptografi
  11. TLS El Sıkışması
  12. Sertifika Zinciri
  13. HTTP Mesajının Anatomisi
  14. Durum, Çerez ve Oturum
  15. HTTP/2'den HTTP/3'e
  16. İçerik Dağıtım Ağları
  17. Diğer Uygulama Protokolleri
  18. Katmanlı Mimari
  19. Kapsülleme ve Başlıklar
  20. Paket Yakalama ve Çözümleme
  21. Ağ Arayüz Kartı
  22. Fiziksel Adresleme
  23. Hata Sezme ve CRC
  24. Adres Çözümleme: ARP
  25. Anahtarlama ve Ortam Erişimi
  26. Ağ Topolojileri
  27. Sanal Yerel Ağlar
  28. Kablosuz Erişim: 802.11
  29. Radyo Kanalı ve Kapasite
  30. Kablosuz Ağ Güvenliği
  31. Hücresel Ağlar
  32. Spektrum ve Kuşaklar
  33. Hareketlilik ve Aktarma
  34. Adres Kiralama: DHCP
  35. Adresin Anatomisi
  36. Adres Tükenmesi ve IPv6
  37. Yönlendirici Mimarisi
  38. Kuyruk Yönetimi
  39. Cihaz Yapılandırma
  40. Yönlendirme Protokolleri
  41. Kontrol Düzlemi ve SDN
  42. Ağ İzleme ve Yönetimi
  43. Alanlar Arası Yönlendirme
  44. Adres Çevirisi
  45. Ara Kutular
  46. Tünelleme ve IPsec
  47. Güvenlik Duvarları
  48. Operatör ve Metro Ağları
  49. Bitten Sinyale
  50. Çoklama Teknikleri
  51. İletim Ortamları
  52. Kablo Sonlandırma
  53. Fiber Optik İletim
  54. Bakır Erişim Ağı: DSL
  55. Pasif Optik Ağlar
  56. Kablo Erişim Ağları
  57. Denizaltı Kabloları
  58. Veri Merkezi Ağları
  59. Kapsülleme Çözme
  60. Güvenilir Aktarım
  61. Tıkanıklık Denetimi
  62. Trafik Çözümleme
  63. Gecikme Bütçesi
  64. Son Söz

Adres elinde. Ama tek başına adres, karşındaki makinede kiminle konuşacağını söylemiyor.

Bir konuşmanın hangi programa ait olduğuna ne karar veriyor?

Adres binayı gösteriyor, daireyi değil

Zincirin sonunda aldığın şey bir makinenin adresiydi. O adres posta kutusuna değil, binaya kadar götürüyor.

Bir sunucu makinesinde aynı anda web sunucusu, posta sunucusu, veritabanı ve yönetim arayüzü çalışıyor olabilir. Dördü de aynı adresin arkasında. Gelen bir parçanın hangisine ait olduğunu adres söylemiyor.

Bu yüzden kimliğe ikinci bir parça eklendi: port numarası. Süreci belirleyen şey adres ile port numarasının ikisi birden.

Sokak adresi binayı buluyor, daire numarası ise binanın içinde kimi arayacağını söylüyor. Postacı binaya kadar geliyor, sonrasını numara belirliyor. Haritalaması şöyle: bina makinenin adresi, daire numarası port, dairede oturan kişi ise o portu dinleyen süreç.

1919’da yapılmış bir New Orleans apartmanının girişinde sıra sıra posta kutuları; her kutunun yanında o daireye çıkan mekanik konuşma borusu var. Adres binaya kadar getiriyor, sonrasını numara belirliyor.

Benzetmenin nerede bittiğini söylemek gerekiyor. Apartmanda daireler sabittir ve boş daire de bir dairedir. Ağda ise dinleyen bir süreç yoksa o numara hiç yoktur; oraya gelen bir parça beklemeye alınmaz, geri çevrilir.

Numaranın kaç basamak olabileceği de başlıktaki alanın genişliğine bağlı. Taşıma katmanı parçasının başında kaynak ve hedef için birer alan var ve her biri 16 bit. Yani numara sıfırdan başlıyor ve 65.535’te bitiyor: toplam 65.536 ayrı kapı.

Numaralar rastgele değil

Bir sunucuya bağlanırken numarayı sen uydurmuyorsun. Tarayıcı https gördüğünde 443’e, http gördüğünde 80’e bağlanıyor. Posta sunucuları 25’i, isim sunucuları 53’ü dinliyor.

Bu numaralar üç aralığa bölünmüş durumda ve ayrım standartla tanımlı:

AralıkAdıKim kullanıyor
0-1.023iyi bilinenyaygın hizmetler; çoğu sistemde yönetici yetkisi ister
1.024-49.151kayıtlıbelirli bir uygulama için kayıt ettirilmiş numaralar
49.152-65.535dinamikkimseye ait değil; kaynak portlar buradan seçilir

Birinci aralıktaki numaraların çoğunu tanımasan da işin bir yerinde karşına çıkıyorlar. Ezberlenecek liste değil ama okunacak listedir; hangi hizmetin hangi kapıda oturduğunu bilmek, bir güvenlik duvarı kuralına ya da bir bağlantı hatasına bakarken tek başına yön verir.

numarahizmetne yapar
20 / 21FTPeski dosya aktarımı; veri ile denetim ayrı kapılarda
22SSHşifreli uzak kabuk, dosya kopyalama ve tünel
23Telnetşifresiz uzak kabuk; bugün yalnızca eski cihazlarda
25SMTPposta sunucuları arası teslim
53DNSad çözme; hem UDP hem TCP
67 / 68DHCPadres kiralama; sunucu 67, istemci 68
80HTTPşifresiz web
110 / 143POP3 / IMAPposta kutusunu okuma
123NTPsaat eşitleme
161 / 162SNMPcihaz izleme ve tuzak bildirimi
389 / 636LDAP / LDAPSdizin sorgulama
443HTTPSşifreli web; QUIC de aynı numarayı UDP’de kullanır
445SMBWindows dosya paylaşımı
465 / 587SMTPS / gönderimistemcinin postayı sunucuya bırakması
3306MySQLveritabanı
3389RDPWindows uzak masaüstü
5432PostgreSQLveritabanı
6379Redisbellek içi veri deposu
8080HTTP (alternatif)yönetici yetkisi olmadan açılan web sunucuları

Son satır bir kuralı ele veriyor. 1.024’ün altındaki numaraları açmak çoğu sistemde yönetici yetkisi ister. Kural, ağın kendisinden değil işletim sisteminden gelir ve amacı basittir: sıradan bir kullanıcı 443’ü kapıp kendi sahte sunucusunu oraya oturtamasın. Yetkisi olmayan geliştiricinin 8080’e ya da 3000’e düşmesinin sebebi bu tek kısıttır.

İlk aralığın yetki istemesi tarihsel bir güvenlik önlemi. Fikir şuydu: düşük numaralı bir kapıyı yalnızca makinenin yöneticisi açabilirse, sıradan bir kullanıcı sahte bir web sunucusu kurup gelenleri kandıramaz.

Ama burada altı çizilmesi gereken bir şey var. Numara ile hizmet arasındaki bağ gelenek, zorunluluk değil. 80’i dinleyen bir program web sunucusu olmak zorunda değil; istersen orada bambaşka bir protokol konuşabilirsin. Aynı şekilde web sunucunu 8080’de de çalıştırabilirsin, yalnızca adres çubuğunda numarayı yazmak zorunda kalırsın.

Bunu bilmek pratikte işe yarıyor. Bir kapının açık olması orada beklediğin hizmetin çalıştığını kanıtlamıyor; yalnızca bir şeyin dinlediğini gösteriyor.

Numaranın ne taşıdığı da başlıkta yazmıyor. Aynı numara iki ayrı taşıma protokolünde birbirinden bağımsız kullanılabiliyor: 53 hem bağlantı kuran hem bağlantısız taşımada tanımlı ve ikisi ayrı soketler. Yani “53 açık” cümlesi bile eksik; hangi taşımada açık olduğunu söylemeden bir şey ifade etmiyor.

Aynı kapıdan yüz binlerce konuşma

Şimdi ilk bakışta çelişki gibi duran bir şey. Bir web sunucusu tek bir numarayı dinliyor, diyelim 443. Aynı anda yüz binlerce kişi ona bağlanıyor. Numara bir tane olduğuna göre sunucu bunları nasıl ayırıyor?

Önce bir ayrım. Yoldaki kutular paketin üstündeki hedefe bakıyordu; o hedef adres, port değil. Yoldaki hiçbir yönlendirici port numarasına bakmak zorunda değil. Port, yalnızca iki uçta anlam taşıyor.

Cevap, taşıma katmanının soketi tek bir sayıyla değil, dört sayıyla tanımlamasında. Kaynak adres, kaynak port, hedef adres, hedef port. Bu four-tuple’ın (dörtlü) tamamı aynı olan iki konuşma olamaz.

Aynı sunucuya bağlanmış üç istemciyi yan yana koyalım:

Kaynak adresKaynak portHedef adresHedef port
192.0.2.1451322203.0.113.9443
192.0.2.1451323203.0.113.9443
198.51.100.749930203.0.113.9443

Üçünün de hedefi aynı, hatta ilk ikisi aynı makineden geliyor. Ayrım tek bir sütunda: kaynak port. Üçüncüsü ise başka bir makineden, dolayısıyla kaynak portu aynı olsa da karışmazdı.

Gelen her parça için makine bu dört değere bakıyor ve parçayı doğru sokete bırakıyor. Bu ayıklama işine çoklama çözme deniyor.

Four-tuple’da görünmeyen gizli bir beşinci sütun daha var: protokol. Port numarası taşıma katmanına ait ve her taşıma protokolünün kendi numara uzayı var. Yani TCP’nin 443’ü ile UDP’nin 443’ü aynı kapı değil, birbirinden tamamen bağımsız iki kapı. Aynı makinede biri açık öbürü kapalı olabilir; ikisini iki ayrı süreç dinleyebilir. HTTPS’in hem TCP hem UDP 443’te yaşayabilmesi de tam olarak bu yüzden mümkün — QUIC aynı numarayı öteki protokolde kullanıyor ve kimsenin ayağına basmıyor.

Bunun doğal sonucu şu: portu olmayan protokoller de var. IP başlığındaki protokol alanı ICMP diyorsa içeride port yoktur, çünkü ICMP bir taşıma protokolü değildir. Ping’in port numarası yoktur ve bir güvenlik duvarında ping’i “port kapatarak” engelleyemezsin; onu protokol düzeyinde ele almak zorundasın.

Sunucu tarafında olan biteni çağrı sırasıyla görmek daha da netleştiriyor:

1. tutamağı oluştur
2. yerel adres ve porta bağla     -> 203.0.113.9:443
3. gelen bağlantıları beklemeye başla
4. bekleyeni kabul et             -> YENİ bir soket doğar

Kendi makinende bu tabloyu görebilirsin. Linux’ta ss -tan, Windows’ta netstat -an dinleyen ve kurulu soketleri listeliyor:

Durum        Yerel adres:port        Uzak adres:port
LISTEN       0.0.0.0:443             0.0.0.0:*
ESTAB        203.0.113.9:443         192.0.2.14:51322
ESTAB        203.0.113.9:443         192.0.2.14:51323
ESTAB        203.0.113.9:443         198.51.100.7:49930
TIME-WAIT    203.0.113.9:443         192.0.2.14:51290

İlk satırda uzak uç boş. Dinleyen soketin karşı tarafı yok, çünkü henüz kimseyle konuşmuyor; yalnızca bekliyor. Yerel taraftaki 0.0.0.0 ise bir makineyi göstermiyor; “bu makinedeki bütün arayüzler” anlamına geliyor.

Bu ayrıntı pratikte sık karşına çıkıyor. Bir süreç soketi 0.0.0.0 yerine 127.0.0.1 adresine bağlarsa yalnızca aynı makineden erişilebilir hâle geliyor; dışarıdan gelen paketler o sokete hiç düşmüyor. Veritabanları çoğu zaman böyle kurulu geliyor ve “servis çalışıyor ama uzaktan bağlanamıyorum” şikâyetinin en yaygın sebebi bu tek satır. Tersi de doğru: yanlışlıkla bütün arayüzlere açılan bir yönetim arayüzü, olması gerekenden çok daha geniş bir kitleye görünür oluyor.

Son satır anahtar. Kabul etmek sana dinlediğin soketi vermiyor; o konuşmaya özel yeni bir soket veriyor. Dinleyen soket kapıda beklemeye devam ediyor. Yüz binlerce bağlantı, yüz binlerce ayrı soket demek — ama hâlâ tek bir port numarası.

DerinleşmeAynı porta iki süreç birden nasıl bağlanabiliyor?

Kural olarak bir portu aynı anda tek bir soket dinler. İkinci bir süreç aynı numaraya bağlanmaya kalkarsa hata alır ve çoğu geliştirici bu hatayı tanır: adres zaten kullanımda.

Ama modern sistemlerde bu kuralı gevşeten bir seçenek var. Süreç soketi açarken “bu portu paylaşmaya razıyım” diyebiliyor; aynı şeyi söyleyen başka süreçler de aynı numaraya bağlanabiliyor. Çekirdek gelen bağlantıları bu süreçler arasında dağıtıyor.

Neden istenir? Çünkü tek bir süreç, tek bir makinenin bütün çekirdeklerini kullanamıyor. Aynı portu dinleyen sekiz süreç açarsan, gelen bağlantılar sekize bölünüyor ve her biri ayrı bir çekirdekte çalışıyor. Aradaki dağıtımı uygulama değil çekirdek yapıyor, üstelik four-tuple’a bakarak: aynı konuşmanın bütün parçaları hep aynı sürece gidiyor.

İkinci faydası kesintisiz güncelleme. Yeni sürümü aynı portu dinleyerek başlatıyorsun, eski sürüm elindeki bağlantıları bitirip kapanıyor. Arada tek bir bağlantı bile reddedilmiyor.

Bedeli de var. Dağıtım bağlantı sayısına göre değil, four-tuple’ın karmasına göre yapılıyor; uzun ömürlü bağlantılarda yük eşit dağılmayabiliyor. Bir süreç yorulurken öteki boş durabiliyor.

Paylaşımı yasaklayan kuralların çoğu, tek çekirdekli bir dünyanın varsayımını taşıyor. Donanım değişince kural da gevşetiliyor — ama kaldırılmıyor, çünkü kazayla aynı portu açmak hâlâ bir hata.

Bir port dışarıdan neye benziyor?

Portun ikinci bir yüzü daha var. Dinleyen her port, dışarıdan bakan biri için bir giriş denemesi noktasıdır; bir makinenin saldırı yüzeyi, kabaca açık portlarının toplamıdır.

Dışarıdan bakan biri üç yanıttan birini alır ve üçü üç ayrı şey söyler:

gördüğüne demeknasıl anlaşılıyor
açıkorada dinleyen bir süreç varbağlantı isteği kabul ediliyor
kapalımakine ayakta ama o portu dinleyen yokmakine “burada kimse yok” diye açıkça reddediyor
filtrelenmişarada bir güvenlik duvarı varhiç cevap gelmiyor, istek sessizce yutuluyor

Aradaki fark önemli. Kapalı bir port cevap verdiği için makinenin varlığını ele veriyor; filtrelenmiş bir port ise makinenin orada olup olmadığını bile söylemiyor. Güvenlik duvarlarının varsayılan davranışının “reddet” değil “sessizce düşür” olmasının sebebi bu.

Buradan iki pratik sonuç çıkıyor. Birincisi, kapatılması gereken şey port değil süreçtir; kimsenin dinlemediği bir numara zaten kapalıdır. İkincisi, bir hizmeti standart dışı bir numaraya taşımak onu gizlemez. Numara değiştirmek yalnızca gelişigüzel taramaların gürültüsünü azaltır, hedefli bir taramayı hiç yavaşlatmaz.

Kendi numaranı sen seçmiyorsun

Four-tuple’ın üç değerini biliyorsun: hedef adres isim çözümlemesinden geldi, hedef port şemadan, kaynak adres de makinenin kendi adresi. Dördüncüsü nereden çıkıyor?

Onu işletim sistemi veriyor. Soket açılırken kaynak portu belirtmezsen çekirdek dinamik aralıktan boş bir numara seçip sana veriyor. Bu numaraya geçici port deniyor ve konuşma bitince havuza geri dönüyor.

Seçimin rastgele olması da önemli. İsim sorgusuna sahtecilik yapmak, kimlik numarasını ve kaynak portu tahmin etmeye dayanıyordu. Kaynak portu tahmin edilebilir olsaydı, araya girmek isteyen tarafın işi bir kat kolaylaşırdı.

Havuzun sınırları da yazılı. IANA dinamik aralığı 49152-65535 diye tanımlıyor, yani 16.384 numara. İşletim sistemleri bu öneriye tam uymuyor: Linux varsayılan olarak 32768-60999 aralığını kullanıyor ve 28.232 numara veriyor, Windows ise IANA aralığına sadık kalıyor. Kendi makinendeki değeri okuyabilirsin:

$ cat /proc/sys/net/ipv4/ip_local_port_range
32768   60999

Havuzun sonu da var. Aynı hedef adres ve porta doğru açabileceğin bağlantı sayısı, elindeki geçici numara kadar; four-tuple’ın öteki üç değeri sabitken ayrım yalnızca kaynak porttan gelebiliyor. Yani tek bir arka uca, tek bir porta doğru açabileceğin eşzamanlı bağlantı sayısının tavanı Linux’ta 28.232.

Sayı bol görünüyor ama tükendiği yerler var ve hep aynı desen: çok sayıda kısa ömürlü bağlantı, tek bir hedefe. Saniyede 500 bağlantı açıp kapatan bir vekil sunucu düşün. Her kapanan four-tuple bir süre beklemede kalıyor; bekleme dört dakikaysa aynı anda beklemede duran four-tuple sayısı 500 × 240 = 120.000 eder. Havuzda 28.232 numara var. Havuz saniyeler içinde tükenir ve yeni bağlantı açılamaz — arıza mesajı “adres zaten kullanımda” olur, oysa hedef sunucu turp gibi ayaktadır.

Yukarıdaki çıktıda görünen TIME-WAIT durumu da tam burada devreye giriyor. Kapanan bir bağlantının four-tuple’ı hemen serbest bırakılmıyor, bir süre beklemede tutuluyor. Sebep şu: yolda gecikmiş eski bir paket, aynı four-tuple’la açılan yeni bir bağlantıya düşerse yeni konuşmanın içine eski veri karışır. Bekleme, o paketlerin ömrünün dolmasını garanti ediyor. Bu sürenin kaç dakika olduğunu ve neden o kadar olduğunu el sıkışmayı kurarken hesaplayacağız.

Bedeli havuzda görülüyor. Kısa ömürlü çok sayıda bağlantı açan bir sunucuda beklemedeki four-tuple’lar birikiyor ve boş numara bulunamaz hâle gelebiliyor. Sıradan bir kullanıcı bunu hiç görmez; tek bir arka uca saniyede binlerce bağlantı açan bir vekil sunucu görür.

Soketin çekirdek tarafını burada kapalı kutu bırakıyorum: tutamağın nasıl bir tabloya düştüğünü, tamponların nerede durduğunu ve kopyalamanın maliyetini 20. bölümde ağ kartına indiğimizde açacağız.

Özet

Peki, ne öğrendik?

  • Adres binayı gösteriyor, süreci değil. Kimlik adres ile port numarasının ikisi birden; port alanı 16 bit olduğu için toplam 65.536 kapı var.
  • Numara ile hizmet arasındaki bağ gelenek. Standart üç aralık tanımlıyor, ama açık bir kapı orada beklediğin hizmetin çalıştığını kanıtlamıyor.
  • Soketi dört değer tanımlıyor: kaynak adres, kaynak port, hedef adres, hedef port. Tek bir dinleme portu bu sayede yüz binlerce ayrı konuşmayı taşıyabiliyor.
  • Kabul işlemi yeni bir soket doğuruyor; dinleyen soket kapıda kalıyor ve her konuşma kendi soketine düşüyor.
  • Kaynak portu sen değil çekirdek seçiyor, dinamik aralıktan ve tahmin edilemez biçimde; havuzun sonu da bağlantı sayısına sınır koyuyor.

Four-tuple tamam, kapı belli, soket açılmaya hazır. Ama şu ana kadar hep “taşıma katmanı” deyip geçtim; adını bir kez andım, ne vaat ettiğini hiç açmadım. Kapıyı buldun; peki oradan geçen her şey aynı sözü mü veriyor?

6. bölüme devam et: Bağlantısız Taşıma: UDP