Compreendendo Sockets

Introdução

Os sockets são uma forma de habilitar a comunicação entre processos entre programas em execução em um servidor, ou entre programas em execução em servidores separados. A comunicação entre servidores depende dos sockets de rede, que utilizam o Protocolo de Internet (IP) para encapsular e lidar com o envio e recebimento de dados.

Os sockets de rede tanto nos clientes quanto nos servidores são referenciados por seu endereço de socket. Um endereço é uma combinação única de um protocolo de transporte como o Protocolo de Controle de Transmissão (TCP) ou Protocolo de Datagrama de Usuário (UDP), um endereço IP e um número de porta.

Neste tutorial, você aprenderá sobre os seguintes tipos diferentes de sockets que são utilizados para comunicação entre processos:

  • Sockets de fluxo, que utilizam TCP como seu protocolo de transporte subjacente
  • Sockets de datagrama, que utilizam UDP como seu protocolo de transporte subjacente
  • Sockets de Domínio Unix, que utilizam arquivos locais para enviar e receber dados em vez de interfaces de rede e pacotes IP.

Em cada seção deste tutorial, você também aprenderá como enumerar os tipos de sockets respectivos em um sistema Linux. Você examinará cada tipo de socket usando uma variedade de ferramentas de linha de comando.

Pré-requisitos

Os exemplos neste tutorial foram validados em um servidor Ubuntu 20.04. Você pode seguir este tutorial usando a maioria das distribuições Linux modernas em um computador local ou servidor remoto, desde que tenha a versão equivalente de cada uma das ferramentas necessárias instaladas para sua distribuição.

Para começar a usar o Ubuntu 20.04, você precisará de um servidor configurado seguindo nosso guia Configuração Inicial do Servidor para Ubuntu 20.04.

Você também precisará de alguns outros pacotes para examinar os sockets em seu sistema. Certifique-se de que o cache de pacotes do seu sistema está atualizado usando o comando apt update:

  1. sudo apt update

Em seguida, instale os pacotes necessários usando este comando:

  1. sudo apt install iproute2 netcat-openbsd socat

O pacote iproute2 contém o utilitário ss, que é o que usaremos para inspecionar sockets. Usaremos o pacote netcat-openbsd para instalar o netcat. Note que o netcat é abreviado para nc quando é invocado na linha de comando. Por fim, usaremos o pacote socat para criar sockets de exemplo.

O que é um Socket de Fluxo?

Os sockets de fluxo são orientados a conexão, o que significa que os pacotes enviados para e recebidos de um soquete de rede são entregues pelo sistema operacional hospedeiro para processamento por uma aplicação. Os sockets de fluxo baseados em rede normalmente utilizam o Protocolo de Controle de Transmissão (TCP) para encapsular e transmitir dados por uma interface de rede.

O TCP é projetado para ser um protocolo de rede confiável que depende de uma conexão com estado. Os dados enviados por um programa usando um soquete de fluxo baseado em TCP serão recebidos com sucesso por um sistema remoto (supondo que não haja problemas de roteamento, firewall ou outras questões de conectividade). Pacotes TCP podem chegar em uma interface de rede física em qualquer ordem. No caso de pacotes chegarem fora de ordem, o adaptador de rede e o sistema operacional hospedeiro garantirão que sejam reagrupados na sequência correta para processamento por uma aplicação.

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.

Criando Sockets de Fluxo Baseados em TCP

No exemplo a seguir, você usará o comando socat (abreviação de SOcket CAT) para emular um servidor web ouvindo por solicitações HTTP na porta 8080 (a porta HTTP alternativa). Em seguida, examinará o soquete usando os comandos ss e nc.

Primeiro, execute os seguintes comandos socat para criar dois soquetes baseados em TCP que estão ouvindo conexões na porta 8080, usando interfaces IPv4 e IPv6:

  1. socat TCP4-LISTEN:8080,fork /dev/null&
  2. socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null&
  • Os argumentos TCP4-LISTEN:8080 e TCP6-LISTEN:8080 são o tipo de protocolo e o número da porta a serem usados. Eles dizem ao socat para criar sockets TCP na porta 8080 em todas as interfaces IPv4 e IPv6, e para escutar cada socket por conexões recebidas. O socat pode escutar em qualquer porta disponível em um sistema, então qualquer porta de 0 a 65535 é um parâmetro válido para a opção de socket.
  • A opção fork é usada para garantir que o socat continue em execução depois de manipular uma conexão, caso contrário, ele sairia automaticamente.
  • O caminho /dev/null é usado no lugar de um endereço de socket remoto. Neste caso, ele diz ao socat para imprimir qualquer entrada recebida no arquivo /dev/null, que a descarta silenciosamente.
  • A bandeira ipv6only=1 é usada para o socket IPv6 informar ao sistema operacional que o socket não está configurado para enviar pacotes para endereços IPv4 mapeados para IPv6. Sem esta bandeira, o socat se ligará tanto a endereços IPv4 quanto IPv6.
  • O caractere & instrui o shell a executar o comando em segundo plano. Esta bandeira garantirá que o socat continue em execução enquanto você invoca outros comandos para examinar o socket.

Você receberá uma saída como a seguinte, que indica os dois IDs de processo socat que estão em execução no fundo da sua sessão de shell. Seus IDs de processo serão diferentes dos destacados aqui:

Output
[1] 434223 [2] 434224

Agora que você tem dois processos socat ouvindo na porta TCP 8080 em segundo plano, você pode examinar os sockets usando as utilidades ss e nc.

Examinando os Sockets de Fluxo Baseados em TCP

Para examinar os sockets TCP em um sistema Linux moderno usando o comando ss, execute-o com as seguintes opções para restringir a saída:

  • As opções -4 e -6 dizem ao ss para examinar apenas os sockets IPv4 ou IPv6, respectivamente. Omitir esta opção exibirá ambos os conjuntos de sockets.
  • A opção t limita a saída aos sockets TCP. Por padrão, a ferramenta ss exibirá todos os tipos de sockets em uso em um sistema Linux.
  • A opção l limita a saída aos sockets de escuta. Sem esta opção, todas as conexões TCP seriam exibidas, o que incluiria coisas como SSH, clientes que podem estar conectados a um servidor web ou conexões que seu sistema pode ter com outros servidores.
  • A opção n garante que os números de porta sejam exibidos em vez de nomes de serviço.

Primeiro, execute o comando ss -4 -tln para examinar os sockets TCP IPv4 que estão ouvindo conexões em seu sistema:

  1. ss -4 -tln

Você receberá uma saída como a seguinte:

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:* . . .

Pode haver outras linhas com outras portas na sua saída, dependendo dos serviços em execução no seu sistema. A parte destacada 0.0.0.0:8080 da saída indica que o socket TCP IPv4 está ouvindo em todas as interfaces IPv4 disponíveis na porta 8080. Um serviço que está ouvindo apenas em um endereço IPv4 específico mostrará apenas esse IP no campo destacado, por exemplo, 203.0.113.1:8080.

Agora execute o mesmo comando ss novamente, mas com a flag -6:

  1. ss -6 -tln

Você receberá uma saída como a seguinte:

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

Pode haver outras linhas com outras portas na sua saída, dependendo dos serviços em execução no seu sistema. A parte destacada [::]:8080 da saída indica que o socket TCP IPv6 está ouvindo em todas as interfaces IPv6 disponíveis na porta 8080 (como indicado pelos caracteres ::, que são a notação IPv6 para um endereço composto apenas de zeros). Um serviço que está ouvindo apenas em um endereço IPv6 específico mostrará apenas esse IP no campo destacado, por exemplo, [2604:a880:400:d1::3d3:6001]:8080.

Conectando a Sockets de Fluxo Baseados em TCP

Até agora, você aprendeu como criar e enumerar sockets TCP em interfaces IPv4 e IPv6. Agora que você tem dois sockets ouvindo conexões, pode experimentar conectando-se a eles usando a utilidade netcat.

Usar o netcat para testar conexões TCP com soquetes locais e remotos é uma técnica de solução de problemas muito útil que pode ajudar a isolar problemas de conectividade e firewall entre sistemas.

Para conectar-se ao soquete IPv4 sobre o endereço de loopback local usando o netcat, execute o seguinte comando:

  1. nc -4 -vz 127.0.0.1 8080
  • A bandeira -4 diz ao netcat para usar IPv4.
  • A bandeira -v é usada para imprimir saída detalhada no seu terminal.
  • A opção -z garante que o netcat apenas se conecte a um soquete, sem enviar nenhum dado.
  • O endereço IP de loopback local 127.0.0.1 é usado, pois o seu sistema terá seu próprio endereço IP único. Se você souber o IP do seu sistema, também pode testar usando-o. Por exemplo, se o endereço IP público ou privado do seu sistema for 203.0.113.1, você poderia usar isso em vez do IP de loopback.

Você receberá uma saída como a seguinte:

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

A linha destacada é a saída do netcat. Ela indica que o netcat se conectou ao soquete TCP ouvindo no endereço de loopback 127.0.0.1 IPv4 na porta 8080. Você pode ignorar a segunda linha, ela é do processo socat em execução em segundo plano no seu terminal.

Agora você pode repetir o mesmo teste de conexão, mas usando IPv6. Execute o seguinte comando netcat:

  1. nc -6 -vz ::1 8080

Você deve receber uma saída como a seguinte:

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

A linha destacada é a saída do netcat. Ela indica que o netcat se conectou ao soquete TCP ouvindo no endereço de loopback ::1 IPv6 na porta 8080. Novamente, você pode ignorar a segunda linha de saída.

Para limpar seus sockets, você precisará executar o comando fg (primeiro plano) para cada processo socat que você criou. Em seguida, você usará CTRL+C para fechar cada socat. fg trará os processos para o primeiro plano do seu terminal na ordem inversa em que você os executou, então quando você o executar, a segunda instância socat será aquela com a qual você interagirá primeiro.

Execute fg para trazer a segunda instância IPv6 socat para o primeiro plano do seu terminal. Em seguida, execute CTRL+C para fechá-la.

  1. fg

Você receberá uma saída como a seguinte:

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

Pressione CTRL+C para interromper o processo.

Agora execute fg novamente para limpar o primeiro socket IPv4. Você deverá ter uma saída como a seguinte:

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

Pressione CTRL+C para interromper o processo.

Você agora criou, examinou e conectou-se a sockets IPv4 e IPv6 em seu sistema. Essas técnicas e ferramentas funcionarão em sistemas de desenvolvimento local ou servidores de produção remotos, então experimente cada ferramenta para se familiarizar mais com como elas podem ser usadas para testar e solucionar problemas de sockets TCP.

O que é um Socket de Datagrama?

Os sockets de datagrama são sem conexão, o que significa que pacotes enviados e recebidos de um socket são processados individualmente pelas aplicações. Os sockets de datagrama baseados em rede geralmente usam o Protocolo de Datagrama de Usuário (UDP) para encapsular e transmitir dados.

O UDP não codifica informações de sequência nos cabeçalhos dos pacotes, e não há correção de erro incorporada ao protocolo. Programas que usam soquetes de rede baseados em datagramas devem incluir sua própria lógica de tratamento de erro e ordenação de dados para garantir uma transmissão de dados bem-sucedida.

Os soquetes UDP são comumente usados pelos servidores de Sistema de Nomes de Domínio (DNS). Por padrão, os servidores DNS usam a porta 53 para enviar e receber consultas de nomes de domínio. Um exemplo de endereço de soquete UDP para um servidor DNS seria semelhante a 203.0.113.1:53.

Nota: Embora o protocolo não seja incluído na versão legível por humanos do endereço de soquete, os sistemas operacionais diferenciam os endereços de soquete incluindo os protocolos TCP e UDP como parte do endereço. Portanto, um endereço de soquete legível por humanos como 203.0.113.1:53 pode estar usando qualquer um dos protocolos. Ferramentas como ss e o utilitário mais antigo netstat são usados para determinar qual tipo de soquete está sendo usado.

O Protocolo de Tempo de Rede (NTP) usa um soquete UDP na porta 123 para sincronizar relógios entre computadores. Um exemplo de soquete UDP para o protocolo NTP seria 203.0.113.1:123.

Criando Soquetes de Datagrama

Como no exemplo anterior de socket TCP, nesta seção você usará o socat novamente para simular um servidor NTP ouvindo por requisições na porta UDP 123. Em seguida, você examinará os sockets que criar usando os comandos ss e nc.

Primeiro, execute os seguintes comandos socat para criar dois sockets UDP que estão ouvindo conexões na porta 123, usando interfaces IPv4 e IPv6:

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

Você receberá uma saída semelhante à seguinte, que indica os dois IDs de processo socat que estão em execução em segundo plano na sessão do seu shell. Seus IDs de processo serão diferentes dos destacados aqui:

Output
[1] 465486 [2] 465487
  • Cada comando é prefixado com sudo, porque as portas 0 a 1024 são reservadas na maioria dos sistemas. O sudo executa um comando com permissões de administrador, o que permite que o socat se vincule a qualquer porta no intervalo reservado.
  • Os argumentos UDP4-LISTEN:123 e UDP6-LISTEN:123 são o tipo de protocolo e a porta a serem usados. Eles dizem ao socat para criar sockets baseados em UDP na porta 123 em ambas as interfaces IPv4 e IPv6, e para ouvir dados de entrada. Novamente, qualquer porta no intervalo completo de 0 a 65535 é um parâmetro válido para sockets UDP.
  • Os argumentos fork, ipv6only=1 e /dev/null são usados da mesma maneira que descrito no exemplo TCP anterior.

Agora que você tem dois processos socat ouvindo na porta UDP 123, você pode examinar os sockets usando as utilidades ss e nc.

Examinando Sockets de Datagrama

Para examinar os sockets UDP em um sistema Linux moderno usando o comando ss, execute-o com as seguintes flags -4, -6 e -uln para restringir a saída:

A flag u limita a saída para sockets UDP.
As outras flags são as mesmas que as usadas no exemplo TCP anterior.

Primeiro execute o comando ss -4 -uln para examinar os sockets UDP IPv4 que estão ouvindo conexões em seu sistema:

  1. ss -4 -uln

Você receberá uma saída como a seguinte:

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:* . . .

Pode haver outras linhas com outras portas em sua saída, dependendo de quais serviços estão em execução em seu sistema. A porção destacada 0.0.0.0:123 da saída indica que o socket UDP IPv4 está disponível em todas as interfaces IPv4 na porta 123. Um serviço que está disponível apenas em um endereço IPv4 específico mostrará apenas esse IP no campo destacado, por exemplo 203.0.113.1:123.

Agora execute o mesmo comando ss novamente, mas com a flag -6:

  1. ss -6 -uln

Você receberá uma saída como a seguinte:

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

Pode haver outras linhas com outras portas na sua saída, dependendo dos serviços em execução no seu sistema. A parte destacada [::]:123 da saída indica que o socket TCP IPv6 está disponível em todas as interfaces IPv6 na porta 123 (como indicado pelos caracteres ::). Um serviço que está disponível apenas em um endereço IPv6 específico mostrará apenas esse IP no campo destacado, por exemplo [2604:a880:400:d1::3d3:6001]:123.

Testando Sockets de Datagrama

Agora que você está familiarizado com como criar e enumerar sockets UDP em interfaces IPv4 e IPv6, você pode experimentar conectando-se a eles. Assim como os sockets TCP, você pode experimentar com os sockets UDP usando o utilitário netcat.

Para se conectar ao exemplo de socket UDP na porta 123 que você criou na seção anterior deste tutorial, execute o seguinte comando netcat:

  1. nc -4 -u -vz 127.0.0.1 123
  • A sinalização -4 indica ao netcat para usar IPv4.
  • A opção -u instrui o netcat a usar UDP em vez de TCP.
  • A bandeira -v é usada para imprimir uma saída detalhada no seu terminal.
  • A opção -z garante que o netcat se conecte apenas a um socket, sem enviar nenhum dado.
  • O endereço IP local de loopback 127.0.0.1 é usado já que o seu sistema terá o seu próprio endereço IP único. Se souber o IP do seu sistema, também pode testar usando esse. Por exemplo, se o endereço IP público ou privado do seu sistema for 203.0.113.1, poderia usar isso em vez do IP de loopback.

Você receberá uma saída como a seguinte:

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

A saída indica que o netcat não recebeu um erro do socket UDP escutando no endereço IPv4 de loopback 127.0.0.1 na porta 123. Esta falta de uma resposta de erro é usada para inferir que o socket em 127.0.0.1:123 está disponível. Este comportamento é diferente dos sockets TCP, que precisam trocar pacotes para confirmar se um socket está disponível.

Nota: Se o socket neste exemplo estivesse indisponível, o sistema remoto retornaria uma mensagem ICMP do tipo 3 (Destino Inalcançável) com um Código de 3, indicando que a porta é inalcançável no host remoto.

Inferir que um socket está disponível com base na falta de resposta de erro pressupõe que não há firewalls ou problemas de conectividade que estejam bloqueando o tráfego ICMP. Sem enviar, receber e verificar dados de aplicativo sobre um socket UDP, não há garantia de que uma porta UDP remota esteja aberta e aceitando pacotes.

Agora pode repetir o mesmo teste de conexão, mas usando IPv6. Execute o seguinte comando netcat:

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

Deve receber uma saída como a seguinte:

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

A saída indica que o netcat não recebeu um erro do socket UDP ouvindo no endereço loopback ::1 IPv6 na porta 123. Novamente, essa falta de resposta de erro é usada para inferir que o socket em ::1:123 está disponível.

Para limpar seus sockets, você precisará executar o comando fg (foreground) para cada processo socat que você criou. Em seguida, você usará CTRL+C para fechar cada socat.

Execute fg para trazer a segunda instância do socat IPv6 para o primeiro plano do seu terminal. Em seguida, execute CTRL+C para fechá-la.

  1. fg

Você receberá uma saída como a seguinte:

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

Pressione CTRL+C para interromper o processo.

Agora execute fg novamente para limpar o primeiro socket IPv4. Você terá uma saída como a seguinte:

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

Pressione CTRL+C para interromper o processo.

Você agora criou, examinou e testou sockets UDP IPv4 e IPv6 no seu sistema. Experimente usar cada ferramenta para se familiarizar mais com como elas podem ser usadas para testar e solucionar problemas de sockets UDP.

O que é um Unix Domain Socket?

Programas que são executados no mesmo servidor também podem se comunicar entre si usando Sockets de Domínio Unix (UDS). Os Sockets de Domínio Unix podem ser baseados em fluxo ou baseados em datagrama. Ao usar sockets de domínio, os dados são trocados entre programas diretamente no kernel do sistema operacional via arquivos no sistema de arquivos do host. Para enviar ou receber dados usando sockets de domínio, os programas leem e escrevem em seu arquivo de soquete compartilhado, contornando completamente os sockets e protocolos baseados em rede.

Os Sockets de Domínio Unix são amplamente utilizados por sistemas de banco de dados que não precisam estar conectados a uma interface de rede. Por exemplo, o MySQL no Ubuntu usa por padrão um arquivo chamado /var/run/mysqld/mysql.sock para comunicação com clientes locais. Os clientes leem e escrevem no soquete, assim como o próprio servidor MySQL.

O PostgreSQL é outro sistema de banco de dados que usa um soquete para comunicação local, não de rede. Tipicamente, ele usa por padrão /run/postgresql/.s.PGSQL.5432 como seu arquivo de soquete.

Criando Sockets de Domínio Unix

Nas seções anteriores, você explorou como o TCP é usado com sockets de fluxo e como o UDP é usado com sockets de datagrama. Nesta seção, você usará o socat para criar Sockets de Domínio Unix baseados em fluxo e em datagramas sem usar TCP ou UDP para encapsular dados a serem enviados pela rede. Em seguida, você examinará os sockets que criar usando os comandos ss e nc. Finalmente, você aprenderá sobre testes de Sockets de Domínio Unix usando netcat.

Para começar, execute os seguintes comandos socat para criar dois arquivos de socket:

  1. socat unix-listen:/tmp/stream.sock,fork /dev/null&
  2. socat unix-recvfrom:/tmp/datagram.sock,fork /dev/null&
  • O primeiro comando instrui o socat a criar um socket usando o tipo de endereço unix-listen, que criará um UDS baseado em fluxo.
  • O segundo comando especifica unix-recvfrom como o tipo de socket, que criará um UDS baseado em datagramas
  • Ambos os comandos especificam um nome de arquivo após o separador :. O nome do arquivo é o endereço do próprio socket. No primeiro exemplo de fluxo, é /tmp/stream.sock e, no segundo exemplo de datagrama, é /tmp/datagram.sock. Observe que o nome de um socket é arbitrário, mas ajuda se for descritivo ao solucionar problemas.
  • Os argumentos fork e /dev/null são usados da mesma maneira que descrito nas seções de exemplo de socket de fluxo e datagrama.

Agora que você criou seus dois sockets UDS, você pode examiná-los usando os utilitários ss e nc.

Examinando Sockets de Domínio Unix

Para listar todos os Sockets de Domínio Unix em escuta, execute o comando ss -xln. A flag x garante que apenas os sockets de domínio sejam exibidos.

  1. ss -xln

Você receberá uma saída como a seguinte:

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 . . .

Observe a parte destacada u_str da linha /tmp/stream/sock. Este campo indica que o tipo de socket é baseado em stream UDS. A segunda linha mostra o tipo como u_dgr, o que significa que o tipo de socket é baseado em datagrama.

Como os Sockets de Domínio Unix são arquivos, as permissões usuais de usuário e grupo do Linux e os controles de acesso podem ser usados para restringir quem pode se conectar ao socket. Você também pode usar ferramentas de sistema de arquivos como ls, mv, chown e chmod para examinar e manipular arquivos UDS. Ferramentas como SELinux também podem ser usadas para rotular arquivos UDS com diferentes contextos de segurança.

Para verificar se um arquivo é um socket UDS, use as utilidades ls, file ou stat. No entanto, é importante observar que nenhuma dessas ferramentas pode determinar se um UDS é baseado em stream ou datagrama. Use a ferramenta ss para obter as informações mais completas sobre um Socket de Domínio Unix.

Para examinar um socket no sistema de arquivos, a utilidade stat mostra as informações mais relevantes. Execute-a nos sockets que você criou anteriormente:

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

Você receberá uma saída como a seguinte:

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: -

Observe que para cada arquivo, o tipo é socket (destacado à direita na saída) e o modo de acesso tem um caractere s precedendo as permissões do arquivo.

O utilitário ls também indicará se um arquivo é um socket. Execute ls -l para examinar os arquivos:

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

Você receberá uma saída como a seguinte. Novamente, observe que para sockets, o modo de arquivo inclui o caractere s antes dos campos de permissão do arquivo:

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

Agora que você criou Sockets de Domínio Unix e aprendeu como examiná-los usando o ss e várias ferramentas baseadas em sistema de arquivos, o próximo passo é testar os sockets usando uma ferramenta como o netcat.

Testando Sockets de Domínio Unix

A utilidade netcat pode ser usada para se conectar a Sockets de Domínio Unix, assim como a Sockets TCP e UDP que você já aprendeu anteriormente neste tutorial. Para se conectar aos sockets de exemplo que você criou, você precisará especificar uma flag extra -U ao executar o comando netcat. Esta flag diz ao netcat para se conectar a um UDS, ao contrário de um socket de rede baseado em TCP ou UDP.

Além disso, se o socket for baseado em datagramas, você usará a flag -u para instruir o netcat a usar datagramas, como aprendemos na seção Socket de Datagramas deste tutorial.

Vamos começar examinando os sockets UDS conectando ao socket baseado em stream com o seguinte comando:

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

O -U indica ao netcat que está se conectando a um Unix Domain Socket.
A opção -z garante que o netcat só se conecte ao socket, sem enviar nenhum dado.
O /tmp/stream.sock é o endereço do socket no sistema de arquivos.

Você não receberá nenhuma saída do netcat ao executar o comando. No entanto, se um socket não estiver disponível, o netcat emitirá uma mensagem de erro como a seguinte:

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

Portanto, a ausência de saída do netcat ao testar um socket UDS baseado em stream significa que a conexão foi bem-sucedida.

Repita o processo de teste, desta vez para o UDS baseado em datagrama:

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

A bandeira adicional -u é adicionada para informar ao netcat que o socket remoto é um socket de datagrama. Novamente, você não receberá nenhuma saída se o teste for bem-sucedido.

Se não houver nenhum socket no endereço, você receberá um erro como o seguinte:

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

Para limpar seus sockets, você precisará executar o comando fg (foreground) para cada processo socat que você criou. Em seguida, você usará CTRL+C para fechar cada socat.

Execute fg para trazer a instância do socat baseado em datagrama para o primeiro plano do seu terminal:

  1. fg

Você receberá uma saída como a seguinte:

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

Execute CTRL+C para fechá-lo. Você não receberá nenhuma saída.

Agora execute fg novamente para limpar o primeiro socket UDS baseado em stream.

Novamente, você deverá ter uma saída como a seguinte:

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

Execute CTRL+C para encerrar o processo. Você não receberá nenhuma saída.

Você agora criou, examinou e testou sockets de Datagrama Unix no seu sistema. Experimente usar o netcat e o socat para se familiarizar mais com como você pode enviar e receber dados por meio de um UDS, bem como como pode testar e solucionar problemas com sockets de Domínio Unix.

Conclusão

Neste tutorial, você explorou como diferentes tipos de sockets são usados em um sistema Linux. Você aprendeu sobre sockets baseados em fluxo, que normalmente usam TCP para comunicação em rede. Você também aprendeu sobre sockets baseados em datagrama, que usam UDP para enviar dados pela rede. Finalmente, você explorou como os Sockets de Domínio Unix podem ser baseados em fluxo ou datagrama em um servidor local.

Em cada seção, você usou a utilidade ss para reunir informações sobre sockets em um sistema Linux. Você aprendeu como as diferentes bandeiras que a ferramenta ss fornece podem ajudá-lo a limitar sua saída para tipos específicos de sockets quando você está examinando sockets em um sistema.

Finalmente, você utilizou as ferramentas netcat e socat para criar e conectar-se a cada um dos três diferentes tipos de sockets discutidos neste tutorial. A utilidade netcat é amplamente utilizada para se conectar a sockets, mas também pode criar sockets. Sua documentação (man nc) contém muitos exemplos de como pode ser usada em qualquer modo. A utilidade socat é uma ferramenta mais avançada que pode ser usada para conectar-se a muitos tipos diferentes de sockets que não são abordados neste tutorial. Sua documentação (man socat) também contém numerosos exemplos das diferentes maneiras como pode ser usada.

Entender o que são sockets e como funcionam é uma habilidade fundamental de administração de sistemas. As ferramentas e técnicas que você experimentou neste tutorial ajudarão você a se familiarizar mais com os sockets e como solucioná-los se seus servidores e aplicativos não estiverem se comunicando corretamente.

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