Escuta na porta que já está listada como porta de origem de uma conexão estabelecida?

4

Se uma conexão estiver em um estado ESTABLISHED com o endereço local 127.0.0.1:45000, será possível que um processo local seja ligado e escute na mesma porta 45000 ou que essa porta seja considerada já em uso e bloqueie a ligação pedido?

    
por Clark 06.11.2014 / 06:14

3 respostas

1

O bind falhará com errno definido como EINVAL . Se você realmente quiser fazer isso, você terá que tcpdump ou outros meios de captura de pacotes para ver o que está acontecendo. strace no processo também seria uma opção, junto com outros diagnósticos do kernel.

    
por 06.11.2014 / 06:36
1

A história completa é "depende do que você quer dizer". Se você gostaria de ouvir exatamente o mesmo IP e porta de um programa existente sobre o qual você não tem controle, então, como outros indicaram, você pode estar sem sorte. Se, no entanto, você:

  • Pode ouvir um endereço IP diferente ou
  • Tenha algum controle sobre o aplicativo original

então você pode estar interessado no restante deste post.

Mesma porta, endereço IP diferente

Quando um programa usa a chamada de sistema bind (2) para atribuir um endereço para um soquete, esse endereço (no caso de um soquete AF_INET) especifica a porta e o endereço IP. Dois endereços com a mesma porta, mas diferentes endereços IP são diferentes e podem ser atribuídos separadamente sem conflito. Por exemplo, usando socat eu posso vincular a porta 9000 no endereço IP para minha interface de loopback em uma concha:

 socat TCP4-LISTEN:9000,bind=127.0.0.1 STDOUT

e liga-se à mesma porta, mas no meu endereço IP externo em outro:

socat TCP4-LISTEN:9000,bind=10.0.2.15 STDOUT

Ambos os processos podem aceitar conexões que entram no endereço IP & porta eles estão ouvindo. Observe, no entanto, que se alguém estiver ouvindo o endereço wildcar 0.0.0.0, você não poderá se vincular a um endereço mais específico, pois o primeiro processo está vinculado a cada IP no sistema.

Mesma porta, mesmo IP

Por padrão, dois processos não podem ligar dois descritores de arquivos diferentes ao mesmo endereço. No Linux, tentar fazer isso resultará em EADDRINUSE sendo retornado de bind(2) :

socat TCP4-LISTEN:9000,bind=127.0.0.1 STDOUT
2014/11/07 00:10:13 socat[21202] E bind(3, {AF=2 127.0.0.1:9000}, 16): Address already in use

Dada sua pergunta e acompanhamento, acredito que você não tenha muito controle sobre o programa que está usando a porta desejada. Se você fez, no entanto, é possível que um processo tenha uma conexão estabelecida em um endereço IP + porta enquanto outro está escutando no mesmo endereço. Por exemplo, muitos aplicativos de servidor fazem o seguinte:

  • Ter um processo principal bind (), listen () e accept () uma conexão
  • Bifurque um novo processo para manipular a conexão aceita, com o processo principal voltando para tentar aceitar () quaisquer novas conexões de entrada.

Nesse caso, você veria um processo filho com uma conexão ESTABLISHED na porta e o processo pai com um soquete LISTENing na mesma porta.

Em kernels Linux muito recentes, é possível que dois processos completamente não relacionados se liguem ao mesmo endereço usando a opção de soquete SO_REUSEPORT. Se um processo definir a opção SO_REUSEPORT no soquete, outros processos com o mesmo UID efetivo do primeiro processo também poderão definir a opção SO_REUSEPORT e vincular-se ao mesmo endereço.

Infelizmente, minha versão de socat parece ter um bug que torna difícil dar um exemplo fácil de TCP; no entanto, forneci um exemplo de programa curto e mal escrito abaixo. Se você executar esse programa como o mesmo usuário em dois shells diferentes, ambos serão vinculados () sem um problema:

State    Recv-Q Send-Q  Local Address:Port  Peer Address:Port
LISTEN   0      128     127.0.0.1:9000        *:*     users:(("bind_tcp_reusep",pid=21254,fd=3))
LISTEN   0    128 127.0.0.1:9000           *:*      users:(("bind_tcp_reusep",pid=21253,fd=3))

O objetivo é oferecer às pessoas que escrevem servidores de rede uma nova ferramenta para criar aplicativos que possam lidar com um grande número de conexões simultâneas.

O seguinte artigo do LWN tem uma boa visão geral do caso de uso para esta opção:

link

Assistindo tráfego em uma conexão estabelecida

Como robbat2 mencionou, se você quiser espionar o tráfego existente tcpdump é a melhor aposta.

Exemplo de programa SO_REUSEPORT

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
#include <errno.h>


int main() {
  struct sockaddr_in bind_addr;
  struct sockaddr peer_addr;
  int optval = 1;
  int tcp_socket;
  int err;
  int addr_len = sizeof(struct sockaddr);

  memset(&bind_addr, 0, sizeof(struct sockaddr_in));
  memset(&peer_addr, 0, sizeof(struct sockaddr));
  bind_addr.sin_family = AF_INET;
  bind_addr.sin_port = htons(9000);

  if (inet_pton(AF_INET, "127.0.0.1", &(bind_addr.sin_addr)) != 1) {
    perror("inet_pton");
    exit(1);
  }

  tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
  setsockopt(tcp_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
  err = bind(tcp_socket, (const struct sockaddr *)&bind_addr, sizeof(struct sockaddr));

  if (err != 0) {
    perror("bind failed");
    exit(1);
  }

  err = listen(tcp_socket, 256);
  if (err != 0) {
    perror("listen failed");
    exit(1);
  }
  accept(tcp_socket, &peer_addr, &addr_len);
}
    
por 07.11.2014 / 01:49
0

Tentei fazer isso sozinha iniciando um servidor Tomcat local e ajustando a configuração para vincular a uma porta que já estava listada como o endereço de origem de uma conexão ESTABLISHED. Permitia que o servidor se ligasse à porta em um estado LISTEN enquanto havia outra conexão ESTABLISHED já usando essa porta como o endereço local.

    
por 06.11.2014 / 07:06

Tags