Port Exhaustion problemi nasıl oluşur ve nasıl önlenir?
Bu flood’da Port Exhaustion
olarak bilinen ve istemci üzerinde soket açacak uygun port kalmaması probleminin nasıl oluştuğunu ve önlenebileceğini anlatacağım.
TCP ve UDP header’larında kaynak ve hedef port numaraları için 16 bit ayrılmıştır. Bu 16 bit ile 2 ^ 16 = 65536
farklı port numarası ifade edilebilir. Dolayısıyla bir bilgisayardan yapılabilecek toplam TCP veya UDP bağlantı sayısı teorik olarak 65536 sayısı ile sınırlıdır.
Pratik durumda ise bir istemciden bir sunucuya yapılabilecek bağlantı sayısı daha düşüktür. Bilgisayarda bulunan portlardan bir kısmı Internet Corporation for Assigned Names and Numbers - ICANN
(önceki adıyla IANA
) kurumu tarafından bazı uygulamalara tahsis edilmiştir.
0
ile 1023
arasındaki portlar Well-known ports
olarak adlandılır. İşletim sistemleri genel olarak uygulamaların bu portları kullanabilmesi için yönetici hesabı ile çalıştırılmalarını şart koşar. Bu sayede kullanıcı seviyesi proseslerin bu portları kullanması engellenir.
HTTP/S - 80, 443
, SSH - 22
, FTP - 20, 21
iyi bilinen port örnekleridir. İyi bilinen portları, 1024
ile 49151
arasındaki portlar ile Registered ports
takip eder. Kayıtlı portlar ICANN
tarafından kontrol edilmese de topluluk faydası için kayıt edilip yayınlanır.
Redis - 6379
, MongoDB - 27017
, Skype - 23399
kayıtlı port örnekleridir. 49152
ile 65535
arasındaki portlar Dynamic
, Private
veya en çok kullanıldığı şekli ile Ephemeral
(kısa ömürlü, geçici) port olarak adlandırılırlar.
Anlaşılacağı üzere 0
'dan başlayarak 49152
'ye kadar portlar bilgisayarın ağ iletişiminin hedef yani sunucu rolünde yer aldığı bağlantı tiplerinde kullanılır. Ephemeral
portlar ise bilgisayarın istemci rolü ile yer aldığı durumlarda kullanılmaktadır.
Daha önce de üzerinden geçtiğimiz üzere bilgisayarımız istemci olarak bir web sunucusunun 443
numaralı portu ile iletişim kuracağı zaman işletim sistemi tarafından ilgili uygulamaya (curl
, tarayıcı, vb) Ephemeral
port aralığından bir port tahsis edilir.
Bir ağ iletişimini kaynak ip/port ve hedef ip/port olmak üzere 4 değer tanımlar. Dolayısıyla yukarıda 65536 olarak verilen teorik sınır aslında istemcideki Ephemeral
port sayısı kadardır. Ephemeral
port aralığının 49152
- 65535
olduğu durumda limit 16384
olacaktır.
Linux işletim sisteminde Ephemeral
port aralığı cat /proc/sys/net/ipv4/ip_local_port_range
komutu ile görülebilir. Ubuntu dağıtımının sunucularında bu aralık 32768
- 60999
olarak belirlenerek tavsiye edilenden daha fazla Ephemeral
port (28231
) kullanıma sunulmuştur.
Şimdi gelelim Port Exhaustion
problemine. Port Exhaustion
bir cihazda başka bir cihaz ile iletişim kurmak üzere uygun durumda port bulunmadığı için soket oluşturulamaması problemine verilen isimdir. Anlaşılacağı üzere istemci ya da proxy'lerde görülen bir problemdir.
Port Exhaustion
'ın sık görülmesinin sebebi TCP soketlerin kapatıldıktan sonra paket kaybı ve tekrar iletimi ihtimaline karşılık TIME_WAIT
state'ine alınması, belirli süre (1-2 dakika) bu state'te tutulması ve bu state'te olduğu süre boyunca yeni bağlantıda kullanılamamasıdır.
Anlaşılacağı üzere kısa süreli çok fazla sayıda bağlantı açıp kapatan istemci, proxy
(vekil) sunucular ve yük dağıtıcılarda fazla sayıda port TIME_WAIT
state'inde kalabilir ve sistem Port Exhaustion
durumuna gelebilir. Farklı bir şekilde istemci ve sunucu arasındaki TCP bağlantısının sürekli açık tutulması gereken websocket
kullanımı gibi durumlarda portlar halihazırda kullanıldığı için soketler TIME_WAIT
durumunda olmasa da kullanılabilir boş port eksikliğinden Port Exhaustion
oluşabilir.
Linux’ta istemcideki bir ephemeral port aynı hedef sunucudaki farklı bir porta veya farklı hedef sunucudaki aynı porta erişmek için kullanılabilir. Örneğin, Linux istemci üzerindeki 52301
numaralı port, üç farklı hedef IP'deki 443
portuna erişmek için kullanılabilir.
Yukarıdaki bilgi ışığında bir istemciden sunucu sayısı sınırsız olmak üzere yapılabilecek bağlantı sayısı teorik olarak sınırsızdır (aslında istemcinin işlemci ve memory’si ile sınırlıdır). Linux çekirdeği bütün Ephemeral
portlar tükenmeden bir portu tekrar kullanmayacaktır.
Özetle Port Exhaustion
'ın oluşması için bir istemci ve az sayıda sunucu gerekir dolayısıyla bu problem ağırlıklı olarak Proxy
ve yük dağıtıcılarda karşımıza çıkar. Problemi hafifletmek için dağıtım yapılan sunucu sayısı artırılabilir. Alternatif olarak aynı sunucu üzerinde aynı network interface
üzerinde farklı sanal IP'ler oluşturulabilir ya da daha modern ve yönetilebilir şekilde yine aynı sunucu üzerinde birden fazla konteyner çalıştırılarak istemcinin fazla sayıda IP adresi ile iletişim kurması ve Port Exhaustion
'dan kaçınması sağlanabilir.
Ek olarak istemci tarafındaki TIME_WAIT
state'indeki bağlantıları azaltmak için HTTP protokolünde Keep-Alive
'da olduğu gibi mevcut TCP bağlantısı kapatılmadan tekrar kullanılabilir.
Son olarak sonraki flood’larda Port Exhaustion
problemini oluşturup semptomları gözlemleyip soket debug etme ile ilgili araçları tanıyacağız. Ek olarak yazıda geçen aynı network interface
üzerinde farklı sanal IP'ler oluşturmayı ve kullanım alanlarını inceleyeceğiz.