Bölüm 6: Port Numarası ve Soket
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
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. Bina makinenin adresine, daire numarası porta, dairede oturan kişi ise o portu dinleyen sürece karşılık geliyor.

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.
Port numarasını taşıyan katmanın adı transport layer (taşıma katmanı): veriyi bir makineden ötekine değil, bir programdan ötekine ulaştıran katman. Ağın bütün katmanlarını 18. bölümde sırayla göreceğiz; şimdilik adını bilmek yetiyor.
Programın bu katmana açılan ucuna soket deniyor: işletim sisteminin bir program için açtığı, adresi ve portu olan bir uç. Bir konuşmanın iki ucunda iki soket durur. Soket iki cihazı değil iki programı birbirine bağlar; uçlar çoğu zaman iki ayrı makinede olur, ama aynı makinedeki iki program da birbirine soketle bağlanabilir. 71. bölümde yazacağın örneklerin çoğu tam da böyle, tek bir makinenin içinde konuşuyor.
Numaranın kaç basamak olabileceği de bu katmanın başlığındaki alanın genişliğine bağlı. Her parçanı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ı port.
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ık | Adı | Kim kullanıyor |
|---|---|---|
| 0-1.023 | iyi bilinen | yaygın hizmetler; çoğu sistemde yönetici yetkisi ister |
| 1.024-49.151 | kayıtlı | belirli bir uygulama için kayıt ettirilmiş numaralar |
| 49.152-65.535 | dinamik | kimseye 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 portta oturduğunu bilmek, bir firewall (güvenlik duvarı, 49. bölüm) kuralına ya da bir bağlantı hatasına bakarken tek başına yön verir.
| numara | hizmet | ne yapar |
|---|---|---|
| 20 / 21 | FTP | eski dosya aktarımı; veri ile denetim ayrı portlarda |
| 22 | SSH | şifreli uzak kabuk, dosya kopyalama ve tünel |
| 23 | Telnet | şifresiz uzak kabuk; bugün yalnızca eski cihazlarda |
| 25 | SMTP | posta sunucuları arası teslim |
| 53 | DNS | ad çözme; hem UDP hem TCP |
| 67 / 68 | DHCP | adres kiralama; sunucu 67, istemci 68 |
| 80 | HTTP | şifresiz web |
| 110 / 143 | POP3 / IMAP | posta kutusunu okuma |
| 123 | NTP | saat eşitleme |
| 161 / 162 | SNMP | cihaz izleme ve tuzak bildirimi |
| 389 / 636 | LDAP / LDAPS | dizin sorgulama |
| 443 | HTTPS | şifreli web; QUIC de aynı numarayı UDP’de kullanır |
| 445 | SMB | Windows dosya paylaşımı |
| 465 / 587 | SMTPS / gönderim | istemcinin postayı sunucuya bırakması |
| 3306 | MySQL | veritabanı |
| 3389 | RDP | Windows uzak masaüstü |
| 5432 | PostgreSQL | veritabanı |
| 6379 | Redis | bellek içi veri deposu |
| 8080 | HTTP (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.
Kural, çok kullanıcılı eski Unix makinelerinden kalma. O dönemde bazı hizmetler, düşük numaralı bir porttan gelen bağlantının karşı makinenin yöneticisi tarafından açıldığını varsayıp ona parola sormadan güveniyordu. O güven çoktan geçersiz; bugün sınır bir ayar hâline geldi. Linux’ta aşağı çekilebiliyor, macOS ise 2018’den beri çoğu durumda bu kısıtı uygulamıyor.
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 portun açık olması orada beklediğin hizmetin çalıştığını kanıtlamıyor; yalnızca bir şeyin dinlediğini gösteriyor.
Aynı porttan 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 router port numarasına bakmak zorunda değil. Port, yalnızca iki uçta anlam taşıyor.
Cevap, transport layer’ı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 adres | Kaynak port | Hedef adres | Hedef port |
|---|---|---|---|
| 192.0.2.14 | 51322 | 203.0.113.9 | 443 |
| 192.0.2.14 | 51323 | 203.0.113.9 | 443 |
| 198.51.100.7 | 49930 | 203.0.113.9 | 443 |
Üçü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 demultiplexing deniyor. Gönderen taraftaki karşılığı, pek çok soketin verisini aynı kablodan çıkarmak, yani multiplexing.
Dörtlü ayrım, bağlantı kuran taşımanın kuralı. Bağlantısız taşımada kernel, parçayı teslim edeceği soketi çoğu zaman yalnızca hedef adres ile hedef porta bakarak seçiyor; farklı istemcilerden gelen parçalar aynı sokete düşüyor ve kimden geldiklerini uygulama kendisi ayıklıyor. İki taşımanın farkını 7. bölümde açacağız.
Four-tuple’da görünmeyen gizli bir beşinci sütun daha var: protokol. Port numarası transport layer’a ait ve her taşıma protokolünün kendi numara uzayı var. Yani TCP’nin 443’ü ile UDP’nin 443’ü aynı port değil, birbirinden tamamen bağımsız iki port. Aynı makinede biri açık öbürü kapalı olabilir; ikisini iki ayrı süreç dinleyebilir. “53 açık” cümlesi bu yüzden eksik: hangi protokolde açık olduğunu söylemeden bir şey ifade etmiyor. HTTPS’in hem TCP hem UDP 443’te yaşayabilmesi de bu sayede 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 firewall’da 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 socket()
2. yerel adres ve porta bağla bind() -> 203.0.113.9:443
3. gelen bağlantıları beklemeye başla listen()
4. bekleyeni kabul et accept() -> YENİ bir soket doğarAsıl nokta son adımda. 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; port numarası ise hâlâ tek. Bu dört çağrıyı 71. bölümde kendi yazdığın bir sunucuda çalıştıracaksın.
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 interface’ler (ağ arayüzleri)” 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 interface’lere açılan bir yönetim paneli, olması gerekenden çok daha geniş bir kitleye görünür oluyor.
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. Kernel gelen bağlantıları bu süreçler arasında dağıtıyor. Seçeneğin Linux’taki adı SO_REUSEPORT.
Neden istenir? Çünkü tek iş parçacığıyla çalışan bir süreç, 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 kernel 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. Doğru yapıldığında arada hiçbir bağlantı reddedilmiyor; eski sürümün kabul sırasında bekleyen bağlantıları unutulursa ise onlar kopuyor.
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 demek | nasıl anlaşılıyor |
|---|---|---|
| açık | orada dinleyen bir süreç var | bağlantı isteği kabul ediliyor |
| kapalı | makine ayakta ama o portu dinleyen yok | makine “burada kimse yok” diye açıkça reddediyor |
| filtrelenmiş | arada bir firewall var | hiç 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. Firewall’ları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 kernel 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 60999Havuzun 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.
Tavan yalnızca açık bağlantıları saymıyor. Yukarıdaki çıktıda görünen TIME-WAIT durumu, kapanan bir bağlantının four-tuple’ının hemen serbest bırakılmadığını, bir süre beklemede tutulduğunu gösteriyor. 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. Standardın öngördüğü sürenin neden dört dakika olduğunu 8. bölümde el sıkışmayı kurarken hesaplayacağız; Linux bu süreyi 60 saniyede tutuyor.
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 proxy düşün. Linux’taki 60 saniyelik beklemeyle aynı anda beklemede duran four-tuple sayısı 500 × 60 = 30.000 eder; havuzda ise 28.232 numara var. Havuz bir dakika dolmadan tükenir ve yeni bağlantı açılamaz. Hata iletisi “Cannot assign requested address” olur, oysa hedef sunucu turp gibi ayaktadır. Sıradan bir kullanıcı bunu hiç görmez; tek bir arka uca saniyede yüzlerce bağlantı açan bir proxy görür.
Soketin kernel tarafını burada kapalı kutu bırakıyorum: tamponların nerede durduğunu ve kopyalamanın maliyetini 22. bölümde ağ kartına indiğimizde, gelen verinin hangi kuyruklardan geçip uygulamaya vardığını da 66. bölümde açacağız.
Özet
- 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 port var.
- Numara ile hizmet arasındaki bağ gelenek. Standart üç aralık tanımlıyor ama açık bir port, 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 kernel seçiyor, dinamik aralıktan ve tahmin edilemez biçimde; havuzun sonu, beklemedeki bağlantılar da sayıldığı için, tek bir hedefe açılan bağlantı sayısına sınır koyuyor.
Four-tuple tamam, port belli, soket açılmaya hazır. Ama şu ana kadar hep “transport layer” deyip geçtim; adını andım, ne vaat ettiğini hiç açmadım. Portu buldun; peki oradan geçen her şey aynı sözü mü veriyor?
7. bölüme devam et: Bağlantısız Taşıma: UDP