Bağlantı Noktalarında TCP / HTTP Dinleme: Birçok Kullanıcı Aynı Bağlantı Noktasını Nasıl Paylaşabilir?
Peki, bir sunucu TCP bağlantı noktasında gelen bağlantıları dinlediğinde ne olur? Örneğin, 80 numaralı bağlantı noktasında bir web sunucunuz olduğunu varsayalım. Bilgisayarınızın genel IP adresi 24.14.181.229 ve size bağlanmaya çalışan kişinin 10.1.2.3 IP adresine sahip olduğunu varsayalım. Bu kişi 24.14.181.229:80'e bir TCP soketi açarak size bağlanabilir. Yeterince basit.
Sezgisel olarak (ve yanlış bir şekilde), çoğu insan bunun şöyle bir şeye benzediğini varsayar:
Local Computer | Remote Computer
--------------------------------
<local_ip>:80 | <foreign_ip>:80
^^ not actually what happens, but this is the conceptual model a lot of people have in mind.
Bu sezgiseldir, çünkü istemcinin bakış açısından bir IP adresine sahiptir ve IP: PORT'daki bir sunucuya bağlanır. Müşteri 80 numaralı bağlantı noktasına bağlandığına göre, bağlantı noktası da 80 olmalıdır? Bu düşünmek için mantıklı bir şey, ama aslında olan şey değil. Bu doğru olsaydı, yabancı IP adresi başına yalnızca bir kullanıcıya hizmet verebilirdik. Uzak bir bilgisayar bağlandığında, 80 numaralı bağlantı noktasını 80 numaralı bağlantı noktasına bağlar ve başka hiç kimse bağlanamaz.
Üç şey anlaşılmalıdır:
1.) Bir sunucuda, bir işlem bir bağlantı noktasında dinliyor . Bir bağlantı kurduğunda, onu başka bir konuya aktarır. İletişim asla dinleme bağlantı noktasını zorlamaz.
2.) Bağlantılar, aşağıdaki 5-tuple ile işletim sistemi tarafından benzersiz şekilde tanımlanır: (yerel-IP, yerel-bağlantı noktası, uzak-IP, uzak-bağlantı noktası, protokol). Demetteki herhangi bir öğe farklıysa, bu tamamen bağımsız bir bağlantıdır.
3.) Bir istemci bir sunucuya bağlandığında, rastgele, kullanılmamış bir yüksek sıralı kaynak bağlantı noktası seçer . Bu şekilde, tek bir istemcinin aynı hedef bağlantı noktası için sunucuya en çok ~ 64k bağlantısı olabilir.
Yani, bir istemci bir sunucuya bağlandığında gerçekten yaratılan şey budur:
Local Computer | Remote Computer | Role
-----------------------------------------------------------
0.0.0.0:80 | <none> | LISTENING
127.0.0.1:80 | 10.1.2.3:<random_port> | ESTABLISHED
Gerçekte Ne Olduğuna Bakmak
Öncelikle, bu bilgisayarda neler olduğunu görmek için netstat kullanalım. 80 yerine 500 numaralı bağlantı noktasını kullanacağız (çünkü ortak bir bağlantı noktası olduğu için 80 numaralı bağlantı noktasında bir sürü şey oluyor, ancak işlevsel olarak bir fark yaratmıyor).
netstat -atnp | grep -i ":500 "
Beklendiği gibi çıktı boş. Şimdi bir web sunucusu başlatalım:
sudo python3 -m http.server 500
Şimdi, işte netstat'ı tekrar çalıştırmanın çıktısı:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN -
Yani şimdi 500 numaralı bağlantı noktasında aktif olarak dinleyen bir işlem var (Durum: LISTEN). Yerel adres, "tüm ip adreslerini dinleme" için kod olan 0.0.0.0'dır. Yapılması kolay bir hata, yalnızca mevcut bilgisayardan gelen bağlantıları kabul edecek olan 127.0.0.1 bağlantı noktasını dinlemektir. Yani bu bir bağlantı değil, bu sadece bir işlemin IP bağlantı noktasına bağlanması () istendiği ve bu işlemin bu bağlantı noktasına yapılan tüm bağlantıların işlenmesinden sorumlu olduğu anlamına gelir. Bu, bir bağlantı noktasını dinleyen bilgisayar başına yalnızca bir işlem olabileceğine dair sınırlamaya işaret eder (çoğullamayı kullanarak bunu aşmanın yolları vardır, ancak bu çok daha karmaşık bir konudur). Bir web sunucusu 80 numaralı bağlantı noktasını dinliyorsa, bu bağlantı noktasını diğer web sunucuları ile paylaşamaz.
Şimdi, makinemize bir kullanıcı bağlayalım:
quicknet -m tcp -t localhost:500 -p Test payload.
Bu basit bir betiktir ( https://github.com/grokit/quickweb ), bir TCP soketi açar, yükü gönderir (bu durumda "Test yükü."), Birkaç saniye bekler ve bağlantıyı keser. Bu olurken netstat'ı tekrar yapmak aşağıdakileri görüntüler:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN -
tcp 0 0 192.168.1.10:500 192.168.1.13:54240 ESTABLISHED -
Başka bir istemciye bağlanır ve tekrar netstat yaparsanız, aşağıdakileri göreceksiniz:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN -
tcp 0 0 192.168.1.10:500 192.168.1.13:26813 ESTABLISHED -
... yani, istemci bağlantı için başka bir rastgele bağlantı noktası kullandı. Bu yüzden IP adresleri arasında asla bir karışıklık olmaz.