Provare con netstat -anp

La funzione listen serve ad usare un socket in modalità passiva, cioè, come dice il nome, per metterlo in ascolto di eventuali connessioni;9 in sostanza l'effetto della funzione è di portare il socket dallo stato CLOSED a quello LISTEN. In genere si chiama la funzione in un server dopo le chiamate a socket e bind e prima della chiamata ad accept. Il prototipo della funzione, come definito dalla pagina di manuale, è:

    * #include <sys/socket.h>
    * int listen(int sockfd, int backlog)

      Pone un socket in attesa di una connessione. 

La funzione restituisce 0 in caso di successo e -1 in caso di errore. I codici di errore restituiti in errno sono i seguenti:

    * EBADF l'argomento sockfd non è un file descriptor valido.
    * ENOTSOCK l'argomento sockfd non è un socket.
    * EOPNOTSUPP il socket è di un tipo che non supporta questa operazione.

*

La funzione pone il socket specificato da sockfd in modalità passiva e predispone una coda per le connessioni in arrivo di lunghezza pari a backlog. La funzione si può applicare solo a socket di tipo SOCK_STREAM o SOCK_SEQPACKET.

L'argomento backlog indica il numero massimo di connessioni pendenti accettate; se esso viene ecceduto il client al momento della richiesta della connessione riceverà un errore di tipo ECONNREFUSED, o se il protocollo, come accade nel caso del TCP, supporta la ritrasmissione, la richiesta sarà ignorata in modo che la connessione possa venire ritentata.

Per capire meglio il significato di tutto ciò occorre approfondire la modalità con cui il kernel tratta le connessioni in arrivo. Per ogni socket in ascolto infatti vengono mantenute due code:

   1. La coda delle connessioni incomplete (incomplete connection queue che contiene un riferimento per ciascun socket per il quale è arrivato un SYN ma il three way handshake non si è ancora concluso. Questi socket sono tutti nello stato SYN_RECV.
   2. La coda delle connessioni complete (complete connection queue che contiene un ingresso per ciascun socket per il quale il three way handshake è stato completato ma ancora accept non è ritornata. Questi socket sono tutti nello stato ESTABLISHED.

Lo schema di funzionamento è descritto in fig. 15.5: quando arriva un SYN da un client il server crea una nuova voce nella coda delle connessioni incomplete, e poi risponde con il SYN+ACK. La voce resterà nella coda delle connessioni incomplete fino al ricevimento dell'ACK dal client o fino ad un timeout. Nel caso di completamento del three way handshake la voce viene spostata nella coda delle connessioni complete. Quando il processo chiama la funzione accept (vedi sez. 15.2.4) la prima voce nella coda delle connessioni complete è passata al programma, o, se la coda è vuota, il processo viene posto in attesa e risvegliato all'arrivo della prima connessione completa.

 Storicamente il valore del parametro backlog era corrispondente al massimo valore della somma del numero di voci possibili per ciascuna delle due code. Stevens in [?] riporta che BSD ha sempre applicato un fattore di 1.5 a detto valore, e fornisce una tabella con i risultati ottenuti con vari kernel, compreso Linux 2.0, che mostrano le differenze fra diverse implementazioni.

In Linux il significato di questo valore è cambiato a partire dal kernel 2.2 per prevenire l'attacco chiamato syn flood. Questo si basa sull'emissione da parte dell'attaccante di un grande numero di pacchetti SYN indirizzati verso una porta, forgiati con indirizzo IP fasullo10 così che i SYN+ACK vanno perduti e la coda delle connessioni incomplete viene saturata, impedendo di fatto ulteriori connessioni.

Per ovviare a questo il significato del backlog è stato cambiato a indicare la lunghezza della coda delle connessioni complete. La lunghezza della coda delle connessioni incomplete può essere ancora controllata usando la funzione sysctl con il parametro NET_TCP_MAX_SYN_BACKLOG o scrivendola direttamente in /proc/sys/net/ipv4/tcp_max_syn_backlog. Quando si attiva la protezione dei syncookies però (con l'opzione da compilare nel kernel e da attivare usando /proc/sys/net/ipv4/tcp_syncookies) questo valore viene ignorato e non esiste più un valore massimo. In ogni caso in Linux il valore di backlog viene troncato ad un massimo di SOMAXCONN se è superiore a detta costante (che di default vale 128).

La scelta storica per il valore di questo parametro era di 5, e alcuni vecchi kernel non supportavano neanche valori superiori, ma la situazione corrente è molto cambiata per via della presenza di server web che devono gestire un gran numero di connessioni per cui un tale valore non è più adeguato. Non esiste comunque una risposta univoca per la scelta del valore, per questo non conviene specificarlo con una costante (il cui cambiamento richiederebbe la ricompilazione del server) ma usare piuttosto una variabile di ambiente (vedi sez. 2.3.4).

Stevens tratta accuratamente questo argomento in [?], con esempi presi da casi reali su web server, ed in particolare evidenzia come non sia più vero che il compito principale della coda sia quello di gestire il caso in cui il server è occupato fra chiamate successive alla accept (per cui la coda più occupata sarebbe quella delle connessioni completate), ma piuttosto quello di gestire la presenza di un gran numero di SYN in attesa di concludere il three way handshake.

Infine va messo in evidenza che, nel caso di socket TCP, quando un SYN arriva con tutte le code piene, il pacchetto deve essere ignorato. Questo perché la condizione in cui le code sono piene è ovviamente transitoria, per cui se il client ritrasmette il SYN è probabile che passato un po' di tempo possa trovare nella coda lo spazio per una nuova connessione. Se invece si rispondesse con un RST, per indicare l'impossibilità di effettuare la connessione, la chiamata a connect nel client ritornerebbe con una condizione di errore, costringendo a inserire nell'applicazione la gestione dei tentativi di riconnessione, che invece può essere effettuata in maniera trasparente dal protocollo TCP.

[Avanti]  [Indietro]  [Su]  
