Ascolto TCP / HTTP sulle porte: quanti utenti possono condividere la stessa porta
Allora, cosa succede quando un server ascolta le connessioni in entrata su una porta TCP? Ad esempio, supponiamo che tu abbia un server web sulla porta 80. Supponiamo che il tuo computer abbia l'indirizzo IP pubblico di 24.14.181.229 e la persona che cerca di connettersi abbia l'indirizzo IP 10.1.2.3. Questa persona può connettersi aprendo un socket TCP su 24.14.181.229:80. Abbastanza semplice.
Intuitivamente (e erroneamente), la maggior parte delle persone presume che assomigli a questo:
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.
Questo è intuitivo, perché dal punto di vista del client, ha un indirizzo IP e si connette a un server su IP: PORT. Dato che il client si connette alla porta 80, anche la sua porta deve essere 80? Questa è una cosa sensata da pensare, ma in realtà non ciò che accade. Se ciò fosse corretto, potremmo servire solo un utente per indirizzo IP esterno. Una volta che un computer remoto si connette, allora trascina la porta 80 alla connessione alla porta 80 e nessun altro può connettersi.
Tre cose devono essere comprese:
1.) Su un server, un processo è in ascolto su una porta. Una volta ottenuta una connessione, la passa a un altro thread. La comunicazione non ostacola mai la porta di ascolto.
2.) Le connessioni sono identificate in modo univoco dal sistema operativo dalle seguenti 5 tuple: (IP locale, porta locale, IP remoto, porta remota, protocollo). Se qualsiasi elemento nella tupla è diverso, si tratta di una connessione completamente indipendente.
3.) Quando un client si connette a un server, seleziona una porta sorgente di ordine superiore casuale e inutilizzata . In questo modo, un singolo client può avere fino a ~ 64k connessioni al server per la stessa porta di destinazione.
Quindi, questo è davvero ciò che viene creato quando un client si connette a un server:
Local Computer | Remote Computer | Role
-----------------------------------------------------------
0.0.0.0:80 | <none> | LISTENING
127.0.0.1:80 | 10.1.2.3:<random_port> | ESTABLISHED
Guardando cosa succede realmente
Per prima cosa, usiamo netstat per vedere cosa sta succedendo su questo computer. Useremo la porta 500 invece di 80 (perché un sacco di cose stanno accadendo sulla porta 80 poiché è una porta comune, ma funzionalmente non fa differenza).
netstat -atnp | grep -i ":500 "
Come previsto, l'output è vuoto. Ora iniziamo un server web:
sudo python3 -m http.server 500
Ora, ecco l'output di eseguire nuovamente netstat:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN -
Quindi ora c'è un processo che è attivamente in ascolto (Stato: LISTEN) sulla porta 500. L'indirizzo locale è 0.0.0.0, che è il codice per "ascoltare tutti gli indirizzi IP". Un semplice errore da commettere è ascoltare solo sulla porta 127.0.0.1, che accetterà solo connessioni dal computer corrente. Quindi questa non è una connessione, significa solo che un processo ha richiesto di bind () alla porta IP, e quel processo è responsabile della gestione di tutte le connessioni a quella porta. Questo suggerisce la limitazione che può esserci un solo processo per computer in ascolto su una porta (ci sono modi per aggirare questo problema usando il multiplexing, ma questo è un argomento molto più complicato). Se un server web è in ascolto sulla porta 80, non può condividere quella porta con altri server web.
Quindi ora colleghiamo un utente alla nostra macchina:
quicknet -m tcp -t localhost:500 -p Test payload.
Si tratta di un semplice script ( https://github.com/grokit/quickweb ) che apre un socket TCP, invia il payload ("Test payload." In questo caso), attende alcuni secondi e si disconnette. Facendo di nuovo netstat mentre questo accade, viene visualizzato quanto segue:
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 -
Se ti connetti con un altro client e fai di nuovo netstat, vedrai quanto segue:
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 -
... cioè, il client ha utilizzato un'altra porta casuale per la connessione. Quindi non c'è mai confusione tra gli indirizzi IP.