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
:
Quindi installa i pacchetti richiesti utilizzando questo comando:
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:
- Gli argomenti
TCP4-LISTEN:8080
eTCP6-LISTEN:8080
sono il tipo di protocollo e il numero di porta da utilizzare. Dicono asocat
di creare socket TCP sulla porta8080
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 da0
a65535
è un parametro valido per l’opzione socket. - L’opzione
fork
viene utilizzata per garantire chesocat
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 asocat
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à chesocat
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 ass
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 strumentoss
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:
Riceverai un output simile al seguente:
OutputState 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
:
Riceverai un output simile al seguente:
OutputState 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:
- 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:
OutputConnection 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:
Dovresti ricevere un output simile al seguente:
OutputConnection 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.
Riceverai un output simile al seguente:
Outputsocat 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:
Outputsocat 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:
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 porte0
a1024
sono riservate sulla maggior parte dei sistemi.sudo
esegue un comando con permessi amministrativi, che consente asocat
di associarsi a qualsiasi porta nell’intervallo riservato. - Gli argomenti
UDP4-LISTEN:123
eUDP6-LISTEN:123
sono il tipo di protocollo e la porta da utilizzare. Dicono asocat
di creare socket UDP sulla porta123
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:
Riceverai un output simile al seguente:
OutputState 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
:
Riceverai un output simile al seguente:
OutputState 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:
- 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:
OutputConnection 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:
Dovresti ricevere un output simile al seguente:
OutputConnection 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.
Riceverai un output come il seguente:
Outputsudo 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:
Outputsudo 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:
- 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.
Riceverai un output simile al seguente:
OutputNetid 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:
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:
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:
Outputsrwxr-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:
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:
Outputnc: 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:
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:
Outputnc: 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:
Riceverai un output come il seguente:
Outputsocat 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:
Outputsocat 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