Como são determinadas as portas de origem e como forçá-lo a usar uma porta específica

26

Quando me conecto a https://www.google.co.uk, isso muda para 216.58.198.228:443. Em seguida, uma conexão comigo é aberta em [Meu endereço IP]: 63998.

Minha pergunta é como a porta 63998 é escolhida e existe uma maneira de forçá-la a ser 63999.

TheGathron
fonte
9
existe uma maneira de forçá-lo a ser 63999 Você tem algum motivo para tentar fazer isso?
AL
1
Se você estiver escrevendo um aplicativo, poderá abrir qualquer porta de origem (não usada) que desejar. Mas não é uma boa ideia e não está claro por que você quer isso?
Pjc50
6
@ pjc50 De fato, esta questão parece estar com um problema XY .
Dev
1
Enviei uma edição para alterar o título para dizer "origem" em vez de "local", pois os números de porta de destino são "locais" para a máquina de destino, mas a origem do pacote TCP SYN inicial é inequivocamente a do iniciador de a conexão
Monty Harder

Respostas:

39

Como são determinadas as portas locais

O número da porta é escolhido pelo software de implementação TCP a partir de um intervalo de números de portas chamado Portas Efêmeras .

O mecanismo exato para escolher o número da porta e o intervalo a ser usado depende do sistema operacional.


Existe uma maneira de forçá-lo a ser 63999.

Isso pode ser feito alterando a configuração do software de implementação TCP.

Instruções para configurar o intervalo de portas efêmeras para uma variedade de sistemas operacionais podem ser encontradas em Alterando o intervalo de portas efêmeras .

  • As instruções para Linux e Windows estão incluídas nesta resposta abaixo para referência.

No entanto, não é uma boa ideia restringir o intervalo a uma única porta, por exemplo 63999.

  • De fato, no Windows, isso não é possível como:

    O intervalo mínimo de portas que pode ser definido é 255.


A escala efêmera do porto

Uma conexão TCP / IPv4 consiste em dois pontos finais, e cada ponto final consiste em um endereço IP e um número de porta. Portanto, quando um usuário cliente se conecta a um computador servidor, uma conexão estabelecida pode ser considerada como a tupla de quatro (IP do servidor, porta do servidor, IP do cliente, porta do cliente).

Normalmente, três dos quatro são facilmente conhecidos - a máquina cliente usa seu próprio endereço IP e, ao conectar-se a um serviço remoto, é necessário o endereço IP e o número da porta de serviço da máquina servidor.

O que não é imediatamente evidente é que, quando uma conexão é estabelecida, o lado do cliente da conexão usa um número de porta. A menos que um programa cliente solicite explicitamente um número de porta específico, o número da porta usado é um número de porta efêmero.

Portas efêmeras são portas temporárias atribuídas pela pilha IP de uma máquina e são atribuídas a partir de um intervalo designado de portas para esse fim. Quando a conexão termina, a porta efêmera está disponível para reutilização, embora a maioria das pilhas IP não reutilize esse número de porta até que todo o conjunto de portas efêmeras tenha sido usado.

Portanto, se o programa cliente se reconectar, será atribuído um número de porta efêmero diferente para o lado da nova conexão.

Fonte A Faixa de Portas Efêmeras


Alterando o intervalo de portas efêmeras

Linux:

O Linux permite visualizar e alterar o intervalo de portas efêmeras, simplesmente usando o arquivo /proc/sys/net/ipv4/ip_local_port_range. Por exemplo, isso mostra a configuração padrão em um sistema kernel 2.2:

$ cat /proc/sys/net/ipv4/ip_local_port_range 
1024 4999

Para alterar isso para o intervalo preferido, você pode fazer (como superusuário):

# echo "49152 65535" > /proc/sys/net/ipv4/ip_local_port_range 

Observe que você precisaria fazer isso sempre que o sistema inicializar; portanto, adicione uma linha a um script de inicialização do sistema, /etc/rc.local para que seu intervalo seja sempre usado.

Observe também que o kernel do Linux 2.4 padronizará o intervalo de 32768 a 61000 se houver memória suficiente do kernel disponível; portanto, a alteração do intervalo pode não ser necessária nos sistemas Linux mais recentes.

Por fim, observe também que você poderá usar a sysctlinterface para alterar as configurações, em vez de usar o /procsistema de arquivos. O nome do sysctlparâmetro é "net.ipv4.ip_local_port_range". Edite o /etc/sysctl.confarquivo, se houver, ou faça com que um script de inicialização execute o sysctlcomando manualmente, se desejar alterar esse parâmetro usando sysctl.

Windows Vista / Windows Server 2008 e mais recente:

A partir do Windows Vista e Windows Server 2008, o Windows agora usa uma grande variedade (49152-65535) por padrão, de acordo com o Artigo 929851 da Base de Conhecimento Microsoft . Esse mesmo artigo também mostra como você pode alterar o intervalo, se desejar, mas o intervalo padrão agora é suficiente para a maioria dos servidores.

Origem Alterando o intervalo de portas efêmeras

Você pode exibir o intervalo de portas dinâmicas em um computador executando o Windows Vista ou Windows Server 2008 usando os seguintes netshcomandos:

netsh int ipv4 show dynamicport tcp
netsh int ipv4 show dynamicport udp
netsh int ipv6 show dynamicport tcp
netsh int ipv6 show dynamicport udp 

Notas:

  • O intervalo é definido separadamente para cada transporte e para cada versão do IP.
  • O intervalo de portas agora é realmente um intervalo com um ponto de partida e um ponto de extremidade.
  • Os clientes da Microsoft que implantam servidores executando o Windows Server 2008 podem ter problemas com a comunicação RPC entre servidores se firewalls forem usados ​​na rede interna.
  • Nestes casos, recomendamos que você reconfigurar os firewalls para permitir o tráfego entre servidores no intervalo de porta dinâmica do 49152 meio 65535.
  • Esse intervalo é um acréscimo às portas conhecidas que são usadas por serviços e aplicativos.
  • Ou, o intervalo de portas usado pelos servidores pode ser modificado em cada servidor.

Você ajusta esse intervalo usando o netshcomando, da seguinte maneira:

netsh int <ipv4|ipv6> set dynamic <tcp|udp> start=number num=range

Este comando define o intervalo de portas dinâmicas para TCP. A porta inicial é o número e o número total de portas é o intervalo. A seguir, são apresentados exemplos de comandos:

netsh int ipv4 set dynamicport tcp start=10000 num=1000
netsh int ipv4 set dynamicport udp start=10000 num=1000
netsh int ipv6 set dynamicport tcp start=10000 num=1000
netsh int ipv6 set dynamicport udp start=10000 num=1000

Esses comandos de amostra configuram o intervalo de portas dinâmicas para iniciar na porta 10000 e terminar na porta 10999(1000 portas).

Notas:

  • O intervalo mínimo de portas que pode ser definido é 255.
  • A porta inicial mínima que pode ser configurada é 1025.
  • A porta final máxima (com base no intervalo que está sendo configurado) não pode exceder 65535.
  • Para duplicar o comportamento padrão do Windows Server 2003, use 1025como a porta inicial e, em seguida, use 3976como o intervalo para TCP e UDP. Isso resulta em uma porta inicial 1025e uma porta final de 5000.

Artigo 929851 da Base de Conhecimento Microsoft de origem :

Windows XP e mais antigo:

Para sistemas operacionais Windows mais antigos (Windows XP e versões mais antigas), o Windows usa o intervalo BSD tradicional de 1024 a 4999 para seu intervalo efetivo de portas. Infelizmente, parece que você só pode definir o limite superior do intervalo de portas efêmeras. Aqui estão informações extraídas do artigo 196271 do Microsoft Knowledgebase :

  • Inicie o Editor do Registro ( Regedt32.exe).
  • Localize a seguinte chave no registro:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

  • No menu "Editar", clique em "Adicionar valor" e adicione o seguinte valor do Registro:

    Nome do valor: MaxUserPortTipo de dados: REG_DWORDValor: 65534(por exemplo)

    Intervalo válido: 5000-65534(decimal) Padrão: 0x1388(5000 decimal)

    Descrição: este parâmetro controla o número máximo de portas usado quando um aplicativo solicita qualquer porta de usuário disponível do sistema. Normalmente, portas efêmeras (ou seja, de curta duração) são alocadas entre os valores de 1024e 5000inclusive.

  • Feche o Editor do Registro.

Nota: Há outro artigo relevante da KB ( 812873 ) que afirma permitir a definição de um intervalo de exclusão, o que pode significar que você pode excluir portas 1024-9999(por exemplo) para ter o intervalo efetivo de portas 10000-65534. No entanto, não conseguimos fazer isso funcionar (em outubro de 2004).

Origem Alterando o intervalo de portas efêmeras

DavidPostill
fonte
1
Pelo menos para o Windows, parece que é possível restringir todo o sistema de alcance de portas. Na maioria dos casos esta é provavelmente uma má idéia, especialmente restringindo-à uma porta seria: Ver KB 929851 , os comandos listados pelo menos trabalho no Windows 7.
Seth
@ Sim Sim. Eu estava relutante em falar isso desde o OP não mencionou seu OS e eu não queria expandir a resposta para cobrir sistemas operacionais N ...
DavidPostill
Você está certo sobre isso. Afinal, existem muitos sistemas operacionais. É apenas algo que me deparei enquanto originalmente tentava responder a essa pergunta. Como sua resposta foi mais rápida, pensei em adicioná-la. É uma resposta muito bem escrita! :) Apenas o adicionei como uma dica de que às vezes alterar a configuração é suficiente, em vez de reprogramar (talvez meu entendimento seja apenas diferente - para mim, isso parece recompilar).
Seth
1
De fato, no Linux também é muito simples: basta fazer eco de "49152 65535"> / proc / sys / net / ipv4 / ip_local_port_range . É tão simples que pode ser feito por comando .
MariusMatutiae
2
Em vez de alterar o intervalo de portas efêmeras, seria muito melhor que o aplicativo chamasse a chamada do bindsistema antes de ligar connect. Alguns aplicativos têm uma opção para fazer isso, outros não.
precisa saber é o seguinte
9

A resposta de David Postill está perfeitamente correta. Gostaria apenas de acrescentar, enfatizando que alterar o intervalo de portas efêmeras no Linux é tão simples que o OP tem uma resposta afirmativa.

Você altera o EPR da seguinte maneira:

echo "40000 60000" > /proc/sys/net/ipv4/ip_local_port_range 

e você pode selecionar a porta 50000 (como exemplo) com o seguinte script:

OLD_RANGE=$(cat /proc/sys/net/ipv4/ip_local_port_range)
MY_PORT=50000
echo "$MY_PORT $MY_PORT" > /proc/sys/net/ipv4/ip_local_port_range
sudo -u SomeUser SomeApplication  & 
echo $OLD_RANGE" > /proc/sys/net/ipv4/ip_local_port_range 

Uma ressalva aqui: como existe uma única porta no intervalo, outro aplicativo pode arrancá-la de você entre a execução da terceira e quarta linhas acima; Além disso, mesmo se não houver condição de corrida, você paralisará todos os outros aplicativos até restaurar um EPR grande, motivo pelo qual restaurei o intervalo original o mais rápido possível.

Portanto, se o sistema operacional dos OPs fosse Linux, a resposta seria que isso poderia ser feito com facilidade.

Surpreendentemente, isso não é tão simples nos BSDs, alguns dos quais nem têm uma configuração de kernel de tempo de execução para o EPR. MacOS X, FreeBSD e OpenBSD requerem a modificação do arquivo /etc/sysctl.conf , mas eles têm opções diferentes para o EPR.

Independentemente do exposto e do sistema operacional, o fato de que algo pode ser feito não significa que deve ser feito: por que diabos você precisa disso? Não consigo pensar em um único caso de uso.

MariusMatutiae
fonte
Para o exemplo Linux +1.
DavidPostill
Ele Ele. O BSD / OS requer a recompilação do kernel :)
DavidPostill
1
@DavidPostill Essa é uma grande chatice.
MariusMatutiae
Existe uma falha no seu exemplo de código. Seu tipo de elenco é muito fora de lugar. Além disso, seria uma boa idéia tornar BIND_PORTopcional, de modo que o código ainda possa ser usado exatamente da mesma maneira que o original. Eu acho htons(bind_port_env ? atoi(bind_port_env) : 0)que faria a coisa certa.
kasperd
1

Vale acrescentar que o kernel Linux também tem

net.ipv4.ip_local_reserved_ports

botão que funciona de maneira oposta, mas, no entanto, pode ser muito útil, pois dessa maneira você pode "perfurar um buraco" para serviços que abrem portas específicas em uma faixa efêmera de portas.

Breve trecho dos documentos :

Especifique as portas reservadas para aplicativos de terceiros conhecidos. Essas portas não serão usadas pelas atribuições automáticas de portas (por exemplo, ao chamar connect () ou bind () com o número da porta 0). O comportamento explícito da alocação de portas não é alterado.

O formato usado para entrada e saída é uma lista de intervalos separados por vírgula (por exemplo, "1,2-4,10-10" para as portas 1, 2, 3, 4 e 10). A gravação no arquivo limpará todas as portas reservadas anteriormente e atualizará a lista atual com a fornecida na entrada.

poige
fonte