Comprensione dei socket

Introduzione

I socket sono un modo per abilitare la comunicazione tra processi tra programmi in esecuzione su un server o tra programmi in esecuzione su server separati. La comunicazione tra server si basa sui socket di rete, che utilizzano il Protocollo Internet (IP) per incapsulare e gestire l’invio e la ricezione di dati.

I socket di rete su entrambi i client e i server sono indicati dal loro indirizzo del socket. Un indirizzo è una combinazione univoca di un protocollo di trasporto come il Transmission Control Protocol (TCP) o User Datagram Protocol (UDP), un indirizzo IP e un numero di porta.

In questo tutorial imparerai i seguenti diversi tipi di socket utilizzati per la comunicazione tra processi:

  • Socket di flusso, che utilizzano TCP come protocollo di trasporto sottostante
  • Socket di datagrammi, che utilizzano UDP come protocollo di trasporto sottostante
  • Socket di dominio Unix, che utilizzano file locali per inviare e ricevere dati invece di interfacce di rete e pacchetti IP.

In ciascuna sezione di questo tutorial imparerai anche come enumerare i rispettivi tipi di socket su un sistema Linux. Esaminerai ogni tipo di socket utilizzando una varietà di strumenti a riga di comando.

Prerequisiti

Gli esempi in questo tutorial sono stati convalidati su un server Ubuntu 20.04. Puoi seguire questo tutorial utilizzando la maggior parte delle moderne distribuzioni Linux su un computer locale o su un server remoto, purché tu abbia installato la versione equivalente di ciascuno degli strumenti richiesti per la tua distribuzione.

Per iniziare a utilizzare Ubuntu 20.04, avrai bisogno di un server che sia stato configurato seguendo la nostra guida Configurazione Iniziale del Server per Ubuntu 20.04.

Avrai anche bisogno di alcuni altri pacchetti per esaminare le prese sul tuo sistema. Assicurati che la cache dei pacchetti del tuo sistema sia aggiornata utilizzando il comando apt update:

  1. sudo apt update

Quindi installa i pacchetti richiesti utilizzando questo comando:

  1. sudo apt install iproute2 netcat-openbsd socat

Il pacchetto iproute2 contiene l’utilità ss, che è ciò che utilizzeremo per ispezionare le prese. Utilizzeremo il pacchetto netcat-openbsd per installare netcat. Nota che netcat è abbreviato in nc quando viene invocato dalla riga di comando. Infine, utilizzeremo il pacchetto socat per creare esempi di prese.

Cos’è una Presa di Flusso?

I socket di flusso sono orientati alla connessione, il che significa che i pacchetti inviati e ricevuti da un socket di rete sono consegnati dal sistema operativo host per essere elaborati da un’applicazione. I socket di flusso basati su rete utilizzano tipicamente il Protocollo di Controllo della Trasmissione (TCP) per incapsulare e trasmettere dati su un’interfaccia di rete.

Il TCP è progettato per essere un protocollo di rete affidabile che si basa su una connessione stateful. I dati inviati da un programma utilizzando un socket di flusso basato su TCP saranno ricevuti con successo da un sistema remoto (a condizione che non ci siano problemi di routing, firewall o connettività). I pacchetti TCP possono arrivare su un’interfaccia di rete fisica in qualsiasi ordine. Nel caso in cui i pacchetti arrivino fuori sequenza, l’adattatore di rete e il sistema operativo host si assicureranno che vengano riassemblati nella sequenza corretta per essere elaborati da un’applicazione.

A typical use for a TCP-based stream socket would be for a web server like Apache or Nginx handling HTTP requests on port 80, or HTTPS on port 443. For HTTP, a socket address would be similar to 203.0.113.1:80, and for HTTPS it would be something like 203.0.113.1:443.

Creazione di socket di flusso basati su TCP

Nell’esempio seguente si utilizzerà il comando socat (abbreviazione di SOcket CAT) per emulare un server web in ascolto di richieste HTTP sulla porta 8080 (la porta HTTP alternativa). Successivamente si esaminerà il socket utilizzando i comandi ss e nc.

Innanzitutto, eseguire i seguenti comandi socat per creare due socket basati su TCP che ascoltano le connessioni sulla porta 8080, utilizzando le interfacce IPv4 e IPv6:

  1. socat TCP4-LISTEN:8080,fork /dev/null&
  2. socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null&
  • Gli argomenti TCP4-LISTEN:8080 e TCP6-LISTEN:8080 sono il tipo di protocollo e il numero di porta da utilizzare. Dicono a socat di creare socket TCP sulla porta 8080 su tutte le interfacce IPv4 e IPv6, e di ascoltare ogni socket per connessioni in ingresso. socat può ascoltare su qualsiasi porta disponibile su un sistema, quindi qualsiasi porta da 0 a 65535 è un parametro valido per l’opzione socket.
  • L’opzione fork viene utilizzata per garantire che socat continui a funzionare dopo aver gestito una connessione, altrimenti uscirebbe automaticamente.
  • Il percorso /dev/null viene utilizzato al posto di un indirizzo socket remoto. In questo caso, dice a socat di stampare qualsiasi input in arrivo sul file /dev/null, che lo scarta silenziosamente.
  • Il flag ipv6only=1 viene utilizzato per il socket IPv6 per dire al sistema operativo che il socket non è configurato per inviare pacchetti agli indirizzi IPv4 mappati su IPv6. Senza questo flag, socat si legherebbe sia agli indirizzi IPv4 che IPv6.
  • Il carattere & istruisce la shell di eseguire il comando in background. Questo flag assicurerà che socat continui a funzionare mentre si invocano altri comandi per esaminare il socket.

Riceverai un output simile al seguente, che indica i due ID processo socat che stanno funzionando in background nella sessione della tua shell. I tuoi ID processo saranno diversi da quelli evidenziati qui:

Output
[1] 434223 [2] 434224

Ora che hai due processi socat in ascolto sulla porta TCP 8080 in background, puoi esaminare i socket utilizzando le utility ss e nc.

Esaminare i Socket di Stream basati su TCP

Per esaminare i socket TCP su un sistema Linux moderno utilizzando il comando ss, eseguilo con le seguenti opzioni per limitare l’output:

  • Le bandiere -4 e -6 indicano a ss di esaminare solo i socket IPv4 o IPv6 rispettivamente. Omettendo questa opzione verranno visualizzati entrambi i set di socket.
  • La bandiera t limita l’output ai socket TCP. Per default, lo strumento ss visualizzerà tutti i tipi di socket in uso su un sistema Linux.
  • La bandiera l limita l’output ai socket in ascolto. Senza questa bandiera, verrebbero visualizzate tutte le connessioni TCP, incluse cose come SSH, client che potrebbero essere connessi a un web server o connessioni che il tuo sistema potrebbe avere con altri server.
  • La bandiera n garantisce che vengano visualizzati i numeri di porta invece dei nomi dei servizi.

Per prima cosa, esegui il comando ss -4 -tln per esaminare i socket TCP IPv4 in ascolto per le connessioni sul tuo sistema:

  1. ss -4 -tln

Riceverai un output simile al seguente:

Output
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . LISTEN 0 1 0.0.0.0:8080 0.0.0.0:* . . .

Potrebbero esserci altre righe con altre porte nel tuo output a seconda dei servizi in esecuzione sul tuo sistema. La porzione evidenziata 0.0.0.0:8080 dell’output indica che il socket TCP IPv4 è in ascolto su tutte le interfacce IPv4 disponibili sulla porta 8080. Un servizio che è in ascolto solo su un indirizzo IPv4 specifico mostrerà solo quell’IP nel campo evidenziato, ad esempio 203.0.113.1:8080.

Ora esegui di nuovo lo stesso comando ss ma con il flag -6:

  1. ss -6 -tln

Riceverai un output simile al seguente:

Output
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . LISTEN 0 5 [::]:8080 [::]:* . . .

Potrebbero esserci altre righe con altre porte nel tuo output a seconda dei servizi in esecuzione sul tuo sistema. La porzione evidenziata [::]:8080 dell’output indica che il socket TCP IPv6 è in ascolto su tutte le interfacce IPv6 disponibili sulla porta 8080 (come indicato dai caratteri ::, che sono la notazione IPv6 per un indirizzo composto interamente da zeri). Un servizio che è in ascolto solo su un indirizzo IPv6 specifico mostrerà solo quell’IP nel campo evidenziato, ad esempio [2604:a880:400:d1::3d3:6001]:8080.

Connessione a Socket di Flusso Basati su TCP

Fino ad ora hai imparato come creare ed enumerare i socket TCP su entrambe le interfacce IPv4 e IPv6. Ora che hai due socket in ascolto per le connessioni, puoi sperimentare connettendoti ai socket usando l’utilità netcat.

L’utilizzo di netcat per testare le connessioni TCP a socket locali e remoti è una tecnica di risoluzione dei problemi molto utile che può aiutare ad isolare problemi di connettività e firewall tra sistemi.

Per connettersi al socket IPv4 sull’indirizzo di loopback locale usando netcat, eseguire il seguente comando:

  1. nc -4 -vz 127.0.0.1 8080
  • Il flag -4 dice a netcat di utilizzare IPv4.
  • Il flag -v viene utilizzato per stampare output dettagliato sul terminale.
  • L’opzione -z assicura che netcat si connetta solo a un socket, senza inviare dati.
  • Viene utilizzato l’indirizzo IP di loopback locale 127.0.0.1 poiché il sistema avrà il suo indirizzo IP univoco. Se conosci l’IP del tuo sistema, puoi testare anche utilizzandolo. Ad esempio, se l’indirizzo IP pubblico o privato del tuo sistema è 203.0.113.1, potresti utilizzarlo al posto dell’IP di loopback.

Riceverai un output simile al seguente:

Output
Connection to 127.0.0.1 (127.0.0.1) 8080 port [tcp/http-alt] succeeded!

La riga evidenziata è l’output di netcat. Indica che netcat si è connesso al socket TCP in ascolto sull’indirizzo IPv4 di loopback 127.0.0.1 sulla porta 8080. Puoi ignorare la seconda riga, è dal processo socat in esecuzione in background nel tuo terminale.

Ora puoi ripetere lo stesso test di connessione ma usando IPv6. Esegui il seguente comando netcat:

  1. nc -6 -vz ::1 8080

Dovresti ricevere un output simile al seguente:

Output
Connection to ::1 8080 port [tcp/http] succeeded!

La riga evidenziata è l’output di netcat. Indica che netcat si è connesso al socket TCP in ascolto sull’indirizzo IPv6 di loopback ::1 sulla porta 8080. Di nuovo, puoi ignorare la seconda riga di output.

Per pulire i tuoi socket, dovrai eseguire il comando fg (foreground) per ogni processo socat che hai creato. Successivamente utilizzerai CTRL+C per chiudere ogni socat. fg porterà i processi in primo piano nel tuo terminale nell’ordine inverso in cui li hai eseguiti, quindi quando lo esegui, la seconda istanza di socat sarà quella con cui interagirai per prima.

Esegui fg per portare la seconda istanza di socat IPv6 in primo piano nel tuo terminale. Quindi esegui CTRL+C per chiuderla.

  1. fg

Riceverai un output simile al seguente:

Output
socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null

Premi CTRL+C per interrompere il processo.

Ora esegui nuovamente fg per pulire il primo socket IPv4. Dovresti ottenere un output simile al seguente:

Output
socat TCP4-LISTEN:8080,fork /dev/null

Premi CTRL+C per interrompere il processo.

Hai ora creato, esaminato e connesso socket IPv4 e IPv6 sul tuo sistema. Queste tecniche e strumenti funzioneranno su sistemi di sviluppo locali o server di produzione remoti, quindi prova a sperimentare con ciascuno strumento per diventare più familiare con il modo in cui possono essere utilizzati per testare e risolvere i problemi dei socket TCP.

Cos’è un Socket Datagramma?

I socket datagrammi sono senza connessione, il che significa che i pacchetti inviati e ricevuti da un socket vengono elaborati singolarmente dalle applicazioni. I socket datagrammi basati su rete utilizzano tipicamente il Protocollo Datagramma Utente (UDP) per incapsulare e trasmettere i dati.

UDP non codifica le informazioni di sequenza negli header dei pacchetti e non è presente alcuna correzione degli errori integrata nel protocollo. I programmi che utilizzano le prese di rete basate su datagrammi devono integrare la propria gestione degli errori e la logica di ordinamento dei dati per garantire una trasmissione dati riuscita.

Le prese di rete UDP sono comunemente utilizzate dai server del Sistema di Nomi a Dominio (DNS). Per impostazione predefinita, i server DNS utilizzano la porta 53 per inviare e ricevere query per i nomi di dominio. Un esempio di indirizzo di presa di rete UDP per un server DNS sarebbe simile a 203.0.113.1:53.

Nota: Anche se il protocollo non è incluso nella versione leggibile dall’utente dell’indirizzo di presa di rete, i sistemi operativi differenziano gli indirizzi di presa di rete includendo i protocolli TCP e UDP come parte dell’indirizzo. Quindi un indirizzo di presa di rete leggibile dall’utente come 203.0.113.1:53 potrebbe utilizzare qualsiasi protocollo. Strumenti come ss e la vecchia utility netstat vengono utilizzati per determinare quale tipo di presa di rete viene utilizzata.

Il Protocollo di Tempo di Rete (NTP) utilizza una presa di rete UDP sulla porta 123 per sincronizzare gli orologi tra i computer. Un esempio di presa di rete UDP per il protocollo NTP sarebbe 203.0.113.1:123.

Creazione di prese di rete a datagrammi

Come nell’esempio precedente di socket TCP, in questa sezione userai nuovamente socat per emulare un server NTP in ascolto delle richieste sulla porta UDP 123. Successivamente esaminerai i socket che crei utilizzando i comandi ss e nc.

Per prima cosa, esegui i seguenti comandi socat per creare due socket UDP in ascolto delle connessioni sulla porta 123, utilizzando interfacce IPv4 e IPv6:

  1. sudo socat UDP4-LISTEN:123,fork /dev/null&
  2. sudo socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null&

Riceverai un output simile al seguente, che indica i due ID processo socat in esecuzione in background nella sessione della tua shell. I tuoi ID processo saranno diversi rispetto a quelli evidenziati qui:

Output
[1] 465486 [2] 465487
  • Ogni comando è preceduto da sudo, perché le porte 0 a 1024 sono riservate sulla maggior parte dei sistemi. sudo esegue un comando con permessi amministrativi, che consente a socat di associarsi a qualsiasi porta nell’intervallo riservato.
  • Gli argomenti UDP4-LISTEN:123 e UDP6-LISTEN:123 sono il tipo di protocollo e la porta da utilizzare. Dicono a socat di creare socket UDP sulla porta 123 sia su interfacce IPv4 che IPv6, e di ascoltare i dati in ingresso. Di nuovo, qualsiasi porta nell’intero intervallo da 0 a 65535 è un parametro valido per i socket UDP.
  • Gli argomenti fork, ipv6only=1 e /dev/null vengono utilizzati allo stesso modo come descritto nell’esempio precedente di TCP.

Ora che hai due processi socat in ascolto sulla porta UDP 123, puoi esaminare i socket utilizzando le utility ss e nc.

Esaminare i Socket Datagramma

Per esaminare i socket UDP su un sistema Linux moderno usando il comando ss, eseguirlo con i seguenti flag -4, -6 e uln per limitare l’output:

Il flag u limita l’output ai socket UDP. Gli altri flag sono gli stessi utilizzati nell’esempio precedente del TCP.

Prima eseguire il comando ss -4 -uln per esaminare i socket UDP IPv4 che sono in ascolto per le connessioni sul tuo sistema:

  1. ss -4 -uln

Riceverai un output simile al seguente:

Output
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . UNCONN 0 0 0.0.0.0:123 0.0.0.0:* . . .

Potrebbero esserci altre righe con altre porte nel tuo output a seconda dei servizi in esecuzione sul tuo sistema. La porzione evidenziata 0.0.0.0:123 dell’output indica che il socket UDP IPv4 è disponibile su tutte le interfacce IPv4 sulla porta 123. Un servizio disponibile solo su un indirizzo IPv4 specifico mostrerà solo quell’IP nel campo evidenziato, ad esempio 203.0.113.1:123.

Ora esegui lo stesso comando ss di nuovo ma con il flag -6:

  1. ss -6 -uln

Riceverai un output simile al seguente:

Output
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . UNCONN 0 0 [::]:123 [::]:* . . .

Potrebbero esserci altre righe con altre porte nel tuo output a seconda dei servizi in esecuzione sul tuo sistema. La porzione evidenziata [::]:123 dell’output indica che il socket TCP IPv6 è disponibile su tutte le interfacce IPv6 sulla porta 123 (come indicato dai caratteri ::). Un servizio disponibile solo su un determinato indirizzo IPv6 mostrerà solo quell’IP nel campo evidenziato, ad esempio [2604:a880:400:d1::3d3:6001]:123.

Test dei Socket Datagram

Ora che hai familiarità con la creazione ed enumerazione dei socket UDP su entrambe le interfacce IPv4 e IPv6, puoi sperimentare connettendoti ad essi. Come con i socket TCP, puoi sperimentare con i socket UDP utilizzando l’utilità netcat.

Per connetterti al socket UDP di esempio sulla porta 123 che hai creato nella sezione precedente di questo tutorial, esegui il seguente comando netcat:

  1. nc -4 -u -vz 127.0.0.1 123
  • Il flag -4 indica a netcat di utilizzare IPv4.
  • L’opzione -u istruisce netcat ad utilizzare UDP invece di TCP.
  • Il flag -v viene utilizzato per stampare un output dettagliato sul terminale.
  • L’opzione -z assicura che netcat si connetta solo a un socket, senza inviare alcun dato.
  • L’indirizzo IP loopback locale 127.0.0.1 viene utilizzato poiché il sistema avrà il proprio indirizzo IP unico. Se conosci l’IP del tuo sistema, puoi testare anche utilizzandolo. Ad esempio, se l’indirizzo IP pubblico o privato del tuo sistema è 203.0.113.1, potresti usarlo al posto dell’IP loopback.

Riceverai un output simile al seguente:

Output
Connection to 127.0.0.1 123 port [udp/ntp] succeeded!

L’output indica che netcat non ha ricevuto un errore dal socket UDP in ascolto sull’indirizzo IPv4 loopback 127.0.0.1 sulla porta 123. Questa mancanza di risposta di errore è utilizzata per inferire che il socket su 127.0.0.1:123 sia disponibile. Questo comportamento è diverso dai socket TCP, che devono scambiare pacchetti per confermare se un socket è disponibile.

Nota: Se il socket in questo esempio non fosse disponibile, il sistema remoto restituirebbe un messaggio ICMP di tipo 3 (Destinazione non raggiungibile) con un codice 3, indicando che la porta non è raggiungibile sull’host remoto.

Inferrare che un socket sia disponibile in base alla mancanza di risposta di errore assume che non ci siano firewall o problemi di connettività che blocchino il traffico ICMP. Senza inviare, ricevere e verificare i dati dell’applicazione su un socket UDP, non c’è garanzia che una porta UDP remota sia aperta e accetti pacchetti.

Ora puoi ripetere lo stesso test di connessione ma usando IPv6. Esegui il seguente comando netcat:

  1. nc -6 -u -vz ::1 123

Dovresti ricevere un output simile al seguente:

Output
Connection to ::1 123 port [udp/ntp] succeeded!!

L’output indica che netcat non ha ricevuto un errore dal socket UDP in ascolto sull’indirizzo loopback IPv6 ::1 alla porta 123. Ancora una volta, questa mancanza di risposta di errore viene utilizzata per dedurre che il socket a ::1:123 sia disponibile.

Per pulire i tuoi socket, dovrai eseguire il comando fg (foreground) per ogni processo socat che hai creato. Quindi userai CTRL+C per chiudere ogni socat.

Esegui fg per portare il secondo istanza di socat IPv6 in primo piano sul tuo terminale. Quindi esegui CTRL+C per chiuderlo.

  1. fg

Riceverai un output come il seguente:

Output
sudo socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null

Premi CTRL+C per fermare il processo.

Ora esegui nuovamente fg per pulire il primo socket IPv4. Avrai un output come il seguente:

Output
sudo socat UDP4-LISTEN:123,fork /dev/null

Premi CTRL+C per fermare il processo.

Hai ora creato, esaminato e testato socket UDP IPv4 e IPv6 sul tuo sistema. Prova a sperimentare con ogni strumento per diventare più familiare con come possono essere utilizzati per testare e risolvere i problemi dei socket UDP.

Cos’è un Socket di Dominio Unix?

I programmi che girano sullo stesso server possono anche comunicare tra loro utilizzando i Socket di Dominio Unix (UDS). I Socket di Dominio Unix possono essere basati su flussi o datagrammi. Quando si utilizzano i socket di dominio, i dati vengono scambiati tra i programmi direttamente nel kernel del sistema operativo tramite file sul filesystem dell’host. Per inviare o ricevere dati utilizzando i socket di dominio, i programmi leggono e scrivono nel loro file socket condiviso, bypassando completamente i socket e i protocolli basati su rete.

I Socket di Dominio Unix sono ampiamente utilizzati dai sistemi di database che non necessitano di essere connessi a un’interfaccia di rete. Ad esempio, MySQL su Ubuntu di default utilizza un file chiamato /var/run/mysqld/mysql.sock per la comunicazione con i client locali. I client leggono e scrivono sul socket, così come fa il server MySQL stesso.

PostgreSQL è un altro sistema di database che utilizza un socket per la comunicazione locale, non di rete. Tipicamente, di default utilizza /run/postgresql/.s.PGSQL.5432 come suo file socket.

Creazione dei Socket di Dominio Unix

Nelle sezioni precedenti hai esplorato come TCP venga utilizzato con socket di flusso e come UDP venga utilizzato con socket di datagrammi. In questa sezione utilizzerai socat per creare sia socket basati su flusso che basati su datagrammi nel Dominio Unix senza utilizzare TCP o UDP per incapsulare i dati da inviare tramite reti. Successivamente esaminerai i socket che crei utilizzando i comandi ss e nc. Infine, imparerai a testare i socket del Dominio Unix utilizzando netcat.

Per iniziare, esegui i seguenti comandi socat per creare due file di socket:

  1. socat unix-listen:/tmp/stream.sock,fork /dev/null&
  2. socat unix-recvfrom:/tmp/datagram.sock,fork /dev/null&
  • Il primo comando istruisce socat a creare un socket utilizzando il tipo di indirizzo unix-listen, che creerà un UDS basato su flusso.
  • Il secondo comando specifica unix-recvfrom come tipo di socket, che creerà un UDS basato su datagrammi
  • Entrambi i comandi specificano un nome file dopo il separatore :. Il nome del file è l’indirizzo del socket stesso. Per il primo esempio di flusso è /tmp/stream.sock e per il secondo esempio di datagrammi è /tmp/datagram.sock. Nota che il nome di un socket è arbitrario ma aiuta se è descrittivo quando si risolvono problemi.
  • Gli argomenti fork e /dev/null vengono utilizzati nello stesso modo descritto nelle sezioni degli esempi di socket di flusso e datagrammi.

Ora che hai creato i tuoi due socket UDS, puoi esaminarli utilizzando le utilità ss e nc.

Esaminare i Socket del Dominio Unix

Per elencare tutti i Socket del Dominio Unix in ascolto, eseguire il comando ss -xln. Il flag x assicura che vengano visualizzati solo i socket di dominio.

  1. ss -xln

Riceverai un output simile al seguente:

Output
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . u_str LISTEN 0 5 /tmp/stream.sock 436470 * 0 u_dgr UNCONN 0 0 /tmp/datagram.sock 433843 * 0 . . .

Nota la parte evidenziata u_str della riga /tmp/stream/sock. Questo campo indica che il tipo di socket è basato su flussi UDS. La seconda riga mostra che il tipo è u_dgr il che significa che il tipo di socket è basato su datagrammi.

Poiché i Socket del Dominio Unix sono file, le usuali autorizzazioni utente e gruppo di Linux e i controlli di accesso possono essere utilizzati per limitare chi può connettersi al socket. È anche possibile utilizzare strumenti del filesystem come ls, mv, chown e chmod per esaminare e manipolare i file UDS. Strumenti come SELinux possono anche essere utilizzati per etichettare i file UDS con contesti di sicurezza diversi.

Per verificare se un file è un socket UDS, utilizzare gli strumenti ls, file o stat. Tuttavia, è importante notare che nessuno di questi strumenti può determinare se un UDS è basato su flussi o datagrammi. Utilizzare lo strumento ss per ottenere le informazioni più complete su un Socket del Dominio Unix.

Per esaminare un socket sul filesystem, l’utilità stat mostra le informazioni più rilevanti. Eseguila sui socket che hai creato in precedenza:

  1. stat /tmp/stream.sock /tmp/datagram.sock

Riceverai un output simile al seguente:

Output
File: /tmp/stream.sock Size: 0 Blocks: 1 IO Block: 131072 socket Device: 48h/72d Inode: 1742 Links: 1 Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2021-03-01 18:10:25.025755168 +0000 Modify: 2021-03-01 18:10:25.025755168 +0000 Change: 2021-03-01 18:22:42.678231700 +0000 Birth: - File: /tmp/datagram.sock Size: 0 Blocks: 1 IO Block: 131072 socket Device: 48h/72d Inode: 1743 Links: 1 Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2021-03-01 18:10:25.025755168 +0000 Modify: 2021-03-01 18:10:25.025755168 +0000 Change: 2021-03-01 18:10:25.025755168 +0000 Birth: -

Nota che per ciascun file, il tipo è socket (evidenziato alla destra dell’output) e la modalità di accesso ha un carattere s precedente i permessi del file.

Il comando ls indicherà anche se un file è un socket. Esegui ls -l per esaminare i file:

  1. ls -l /tmp/stream.sock /tmp/datagram.sock

Riceverai un output simile al seguente. Di nuovo, nota che per i socket, la modalità del file include il carattere s prima dei campi di permessi del file:

Output
srwxr-xr-x 1 root root 0 Mar 1 18:10 /tmp/datagram.sock srwxr-xr-x 1 root root 0 Mar 1 18:10 /tmp/stream.sock

Ora che hai creato Socket del Dominio Unix e imparato come esaminarli usando il comando ss e vari strumenti basati sul filesystem, il prossimo passo è testare i socket usando uno strumento come netcat.

Test dei Socket del Dominio Unix

Netcat può essere usato per connettersi a Socket del Dominio Unix, così come a socket TCP e UDP che hai già imparato in precedenza in questo tutorial. Per connetterti ai socket di esempio che hai creato, dovrai specificare un flag aggiuntivo -U quando esegui il comando netcat. Questo flag indica a netcat di connettersi a un UDS, invece che a un socket di rete basato su TCP o UDP.

Inoltre, se il socket è basato su datagrammi, userai il flag -u per istruire netcat a utilizzare datagrammi come abbiamo appreso nella sezione Socket Datagram di questo tutorial.

Iniziamo esaminando le socket UDS connettendoci alla socket basata su stream con il seguente comando:

  1. nc -U -z /tmp/stream.sock

Il -U dice a netcat che si sta connettendo a una Unix Domain Socket.
L’opzione -z assicura che netcat si connetta solo a una socket, senza inviare dati.
/tmp/stream.sock è l’indirizzo della socket nel filesystem.

Non riceverai alcun output da netcat quando esegui il comando. Tuttavia, se una socket non è disponibile, netcat restituirà un messaggio di errore come il seguente:

Output
nc: unix connect failed: No such file or directory nc: /tmp/stream.sock: No such file or directory

Quindi l’assenza di output da netcat durante il test di una socket UDS basata su stream significa che la connessione è riuscita.

Ripeti il processo di test, questa volta per la UDS basata su datagramma:

  1. nc -uU -z /tmp/datagram.sock

Viene aggiunta l’opzione -u per indicare a netcat che la socket remota è una socket datagram. Di nuovo, non riceverai alcun output se il test è riuscito.

Se non c’è una socket all’indirizzo, riceverai un errore come il seguente:

Output
nc: unix connect failed: No such file or directory nc: /tmp/datagram.sock: No such file or directory

Per pulire le tue socket, dovrai eseguire il comando fg (foreground) per ogni processo socat che hai creato. Quindi userai CTRL+C per chiudere ogni socat.

Esegui fg per portare l’istanza di socat basata su datagramma al primo piano del tuo terminale:

  1. fg

Riceverai un output come il seguente:

Output
socat unix-recvfrom:/tmp/datagram.sock,fork /dev/null

Esegui CTRL+C per chiuderlo. Non riceverai alcun output.

Ora esegui nuovamente fg per pulire la prima socket UDS basata su stream.

Di nuovo dovresti avere un output come il seguente:

Output
socat unix-listen:/tmp/stream.sock,fork /dev/null

Esegui CTRL+C per terminare il processo. Non riceverai alcun output.

Ora hai creato, esaminato e testato i socket Datagram Unix sul tuo sistema. Prova a sperimentare con netcat e socat per diventare più familiare con il modo in cui puoi inviare e ricevere dati su un UDS, così come con il modo in cui puoi testare e risolvere i problemi relativi ai socket di dominio Unix.

Conclusione

In questo tutorial hai esplorato come vengono utilizzati diversi tipi di socket su un sistema Linux. Hai appreso dei socket basati su flussi, che utilizzano tipicamente TCP per la comunicazione di rete. Hai anche appreso dei socket basati su datagrammi, che utilizzano UDP per inviare dati su reti. Infine, hai esplorato come i Socket di Dominio Unix possano essere basati sia su flussi che su datagrammi su un server locale.

In ogni sezione hai utilizzato l’utilità ss per raccogliere informazioni sui socket su un sistema Linux. Hai appreso come i diversi flag forniti dall’utility ss possono aiutarti a limitare l’output a tipi specifici di socket quando stai esaminando i socket su un sistema.

Finalmente, hai utilizzato gli strumenti netcat e socat per creare e connetterti a ciascuno dei tre diversi tipi di socket discussi in questo tutorial. L’utilità netcat è ampiamente utilizzata per connettersi a socket, ma può anche crearli. La sua documentazione (man nc) contiene molti esempi di come può essere utilizzata in entrambe le modalità. L’utilità socat è uno strumento più avanzato che può essere utilizzato per connettersi e a molti tipi di socket diversi non trattati in questo tutorial. Anche la sua documentazione (man socat) contiene numerosi esempi dei diversi modi in cui può essere utilizzata.

Comprendere cosa sono i socket e come funzionano è una competenza fondamentale per l’amministrazione di sistema. Gli strumenti e le tecniche sperimentati in questo tutorial ti aiuteranno a familiarizzare maggiormente con i socket e a risolverli se i tuoi server e le tue applicazioni non comunicano correttamente tra loro.

Source:
https://www.digitalocean.com/community/tutorials/understanding-sockets