Sockets
Liens et ressources
- https://ops.tips/blog/how-linux-creates-sockets/ Un article que je reprend ici.
- http://n8on.free.fr/hackzines/counterstrike/3/rawsockets.html Un truc sur les sockets RAW
- https://www.networkworld.com/article/3327557/using-the-linux-ss-command-to-examine-network-and-socket-connections.html Un truc sur sockstat
- https://www.tecmint.com/ss-command-examples-in-linux/ Des exemples de commande ss
Qu'est-ce qu'un Socket ?
Les sockets sont des objets permettant à des processus situés sur différentes machines de communiquer entre eux via un réseau sous-jacent; ils peuvent également permettre à plusieurs processus situés sur la même machine de communiquer entre eux via des sockets UNIX.
On peut donc voir les sockets comme les portes d'une maison (le kernel), dans laquelle le processus serait un occupant. Pour chaque porte, un client peut arriver frapper, ce qui correspond à l'envoi d'un paquet SYN. La maison répond alors avec une réponse (SYN/ACK) : c'est le handshake TCP. Pendant que le processus est en attente, les clients sont organisés en deux files d'attente : une pour ceux avec qui le kernel est toujours en train de faire son handshake, et une pour ceux avec qui c'est fait.
Pour les clients avec qui le handshake est fini, la communication peut alors s'établir. Pour ce faire, le kernel crée un socket client (une porte privée, en quelque sorte), et permet au processus de dialoguer avec son client.
Et dans mon OS ?
On va désormais se demander où se trouvent les sockets, combien il y'en, dans quel état ils sont et comment ils sont créés.
Imaginons un programme qui créée un socket et n'en fais rien. Je reprends ici l'exemple de l'article ops.tips situé dans les liens qui est en C. <source lang="C"> // socket.c - creates a socket and then sleeps.
- include <stdio.h>
- include <sys/socket.h>
/**
* Creates a TCP IPv4 socket and then just * waits. */
int main(int argc, char** argv) { // The `socket(2)` syscall creates an endpoint for communication // and returns a file descriptor that refers to that endpoint. // // It takes three arguments (the last being just to provide greater // specificity): // - domain (communication domain) // AF_INET IPv4 Internet protocols // // - type (communication semantics) // SOCK_STREAM Provides sequenced, reliable, // two-way, connection-based byte // streams. int listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (err == -1) { perror("socket"); return err; }
// Just wait ... sleep(3600);
return 0; } </source>
Des informations sur les sockets
En interne, l'appel système de création de socket provoque plusieurs méthodes internes; celles-ci peuvent nous laisser voir des informations dans :
- /proc/<pid>/net/tcp
- /proc/<pid>/fd
- /proc/<pid>/net/sockstat
/proc/<pid>/net/fd : fichiers ouvert par le processus
Le répertoire fd nous donne une liste des fichiers ouverts par le process. Par exemple, ici avec Varnish:
<source> root@gate:/proc/4179698/fd# ls -lah total 0 dr-x------ 2 root root 0 Nov 19 17:47 . dr-xr-xr-x 9 vcache varnish 0 Nov 19 17:47 .. lrwx------ 1 root root 64 Nov 19 17:47 0 -> /dev/null lrwx------ 1 root root 64 Nov 19 17:47 1 -> 'socket:[24908688]' l-wx------ 1 root root 64 Nov 19 17:47 11 -> 'pipe:[24908763]' lr-x------ 1 root root 64 Nov 19 17:47 12 -> 'pipe:[24908764]' lr-x------ 1 root root 64 Nov 19 17:47 14 -> 'pipe:[24908765]' lr-x------ 1 root root 64 Nov 19 17:47 16 -> /var/lib/varnish/gate/_.vsm_child lrwx------ 1 root root 64 Nov 19 17:47 2 -> 'socket:[24908688]' lrwx------ 1 root root 64 Nov 19 17:47 3 -> 'socket:[24908709]' lrwx------ 1 root root 64 Nov 19 17:47 4 -> 'socket:[24908710]' lrwx------ 1 root root 64 Nov 19 17:47 5 -> /var/nish/varnish_storage.bin l-wx------ 1 root root 64 Nov 19 17:47 6 -> /var/lib/varnish/gate/_.pid lr-x------ 1 root root 64 Nov 19 17:47 7 -> /var/lib/varnish/gate/_.vsm_mgt lrwx------ 1 root root 64 Nov 19 17:47 8 -> 'socket:[24908761]' lrwx------ 1 root root 64 Nov 19 17:47 9 -> 'socket:[24908762]' </source>
/proc/<pid>/net/tcp : informations sur les connexions actives
Toujours avec Varnish, nous avons des informations sur l'état des connexion TCP dans le namespace réseau de notre process :
<source> root@gate:/proc/4179698/net# cat tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode 0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 14539 1 00000000e68e62f0 100 0 1 10 0 1: 00000000:0051 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 24908709 1 000000001333672c 100 0 0 10 0 2: 00000000:20D4 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 14528 1 00000000a1a3a11a 100 0 1 10 0 3: 00000000:01BB 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 14540 1 00000000593430e6 100 0 1 10 0 4: 00000000:00DC 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 839035 1 00000000128a12ea 100 0 0 10 0 5: 00000000:199C 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 13703 1 0000000025d2d4ad 100 0 0 10 0 6: 0100007F:17C2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 24908761 1 0000000009c5c214 100 0 0 10 0 7: 0200000A:199C 0400000A:E5F8 06 00000000:00000000 03:00000880 00000000 0 0 0 3 000000006a58b6a3 8: ECBA825E:00DC FA4E4152:D3AC 01 00000034:00000000 01:00000015 00000000 0 0 121402388 4 000000008d80e568 21 5 31 10 -1 9: ECBA825E:01BB FA4E4152:E7DA 01 00000000:00000000 00:00000000 00000000 106 0 121410090 1 000000006e54dbe1 21 4 25 10 -1 10: 0200000A:9EC6 0300000A:0050 01 00000000:00000000 00:00000000 00000000 106 0 121413050 1 00000000c38a7689 20 4 26 10 -1 11: ECBA825E:01BB C64F0C31:DE44 06 00000000:00000000 03:0000043E 00000000 0 0 0 3 000000003cf315ac 12: 0200000A:9B00 0500000A:0BB8 01 00000000:00000000 00:00000000 00000000 106 0 121413061 1 00000000ce9ec671 20 4 22 10 -1
</source> C'est peu lisible par un humain !
/proc/<pid>/net/sockstat : Résumé concernant le socket
Varnish, encore une fois. <source> sockets: used 156 TCP: inuse 10 orphan 0 tw 8 alloc 13 mem 1 UDP: inuse 2 mem 2 UDPLITE: inuse 0 RAW: inuse 0 FRAG: inuse 0 memory 0 </source> Nous avons ici:
- TCP : Connexion utilisées, orphelines (donc plus attachées à un descripteur de fichier), en timewait, allouées (de tout type); et mem, la mémoire totale utilisée pour le socket.
- UDP : Connexions utilisée, mémoire totale
- UDPLITE : Un protocole décrit dans la RFC 3828, un genre d'UDP adapté aux connexions peu fiables (les paquets endommagés sont quand même délivrés).
- RAW : Socket RAW, soit des sockets où les en-têtes sont écrites à la main (sans protocole spécifique attaché). Utile pour coder un truc comme Nmap par exemple.
- FRAG : Fragmentés.
ss : la commande dédiée aux infos sur les sockets
Cette commande, dont le nom est un raccourci de "sockstat", donne beaucoup d'informations sur les connexions en cours. C'est une superbe alternative à lsof et netstat. Un lancement simple de la commande affiche toutes les connexions en cours, sockets UNIX compris : <source> u_str ESTAB 0 0 * 14478 * 13625 u_str ESTAB 0 0 /run/dbus/system_bus_socket 12976 * 12975 u_str ESTAB 0 0 /run/systemd/journal/stdout 13625 * 14478 u_str ESTAB 0 0 * 14425 * 14426 tcp ESTAB 0 52 94.130.186.236:220 82.65.78.250:54188 tcp ESTAB 0 0 10.0.0.2:47436 10.0.0.5:3000 tcp ESTAB 0 0 94.130.186.236:https 82.65.78.250:59366 tcp ESTAB 0 0 10.0.0.2:48398 10.0.0.3:http </source>
Elle offre beaucoup de possibilités. Deux trois exemples ci-dessous, mais il existe plein d'autres choses.
Liste des socket tcp actuellements en mode écoute
ss -tl: t pour tcp, l pour listening <source> root@gate:/proc/4179698/net# ss -tl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 4096 0.0.0.0:http 0.0.0.0:* LISTEN 0 1024 0.0.0.0:81 0.0.0.0:* LISTEN 0 4096 0.0.0.0:8404 0.0.0.0:* LISTEN 0 4096 0.0.0.0:https 0.0.0.0:* LISTEN 0 128 0.0.0.0:220 0.0.0.0:* LISTEN 0 64 0.0.0.0:6556 0.0.0.0:* LISTEN 0 10 127.0.0.1:6082 0.0.0.0:* LISTEN 0 1024 [::]:81 [::]:* LISTEN 0 4096 *:ssh *:* LISTEN 0 128 [::]:220 [::]:* </source>
Liste des sockets UDP en écoute
ss -lu <source> root@gate:/proc/4179698/net# ss -tl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 4096 0.0.0.0:http 0.0.0.0:* LISTEN 0 1024 0.0.0.0:81 0.0.0.0:* LISTEN 0 4096 0.0.0.0:8404 0.0.0.0:* LISTEN 0 4096 0.0.0.0:https 0.0.0.0:* LISTEN 0 128 0.0.0.0:220 0.0.0.0:* LISTEN 0 64 0.0.0.0:6556 0.0.0.0:* LISTEN 0 10 127.0.0.1:6082 0.0.0.0:* LISTEN 0 1024 [::]:81 [::]:* LISTEN 0 4096 *:ssh *:* LISTEN 0 128 [::]:220 [::]:* </source>