Quando escrevo o "habitual" aqui, estou pensando no seu roteador WLAN-NAT de consumidor médio com uma configuração sã ou em alguma rede Linux simples com configurações padrão. Como sempre, isso pode ser feito o mais complexo ou complicado possível. Como a pergunta é muito básica, isso parece fazer mais sentido para mim, em vez de ir direto para as soluções NAT de nível empresarial mais complicadas.
Você já aceitou uma resposta, mas deixe-me tentar abordar diretamente a pergunta que você fez:
Como o NAT decide quais conexões são de entrada e quais são de saída?
A base da decisão (para qualquer decisão em um roteador) é um conjunto de regras de alguma forma ou forma. Nesse caso, para cada uma das interfaces envolvidas (ou seja, a interface LAN interna versus a interface WAN / uplink externa), o administrador implementará regras. Essas regras são bem diferentes, ou seja, as regras para uma interface LAN parecem muito diferentes das de uma interface WAN.
Saber de onde um pacote vem e para onde vai é o pão com manteiga do que um roteador faz.
Deixe-me começar com um
Exemplo
A página NAT da Wikipedia possui muito texto sobre esse assunto, mas um caso simples (uma LAN simples da empresa versus um único uplink DSL) é o que acontece:
- O PC cliente tenta iniciar uma conexão HTTP com um servidor baseado na Internet, por exemplo, 198.51.100.20. O próprio PC possui um endereço não roteado como 192.0.2.2. O roteador DSL barato tem duas interfaces, uma interna (192.0.2.1) e uma externa (203.0.113.10, muito provavelmente mudando com freqüência e fornecidas por algum protocolo de link local pelo provedor DLS). Portanto, o PC envia um pacote SYN para 198.51.100.20:80 através de seu gateway padrão, que é 192.0.2.1.
- O roteador pega o pacote na interface 192.0.2.1, como também faria se não houvesse NAT envolvido. Ele foi configurado para executar NAT nesta interface, portanto, segue as seguintes ações:
- Invente um novo número de porta, que não está sendo usado até o momento. Por exemplo 12345.
- Altere o endereço "remetente" no cabeçalho IP para 203.0.113.10.
- Lembre-se do número da porta remetente original no cabeçalho TCP (fornecido pelo PC), vamos chamá-lo de 4321.
- Altere o cabeçalho TCP para conter o número da porta do remetente 12345.
- Adicione uma entrada (12345; 192.0.2.2; 4321) em sua tabela de conversão de NAT.
- Envie o pacote no seu caminho alegre para seu próprio uplink / gateway.
- 198.51.100.20 eventualmente recebe o pacote, percebe que é um SYN ("estabelecer nova conexão") e envia uma mensagem SYN-ACK de volta ao remetente. Do seu ponto de vista, este é o endereço IP 203.0.113.10, com a porta de destino TCP 12345.
- O roteador recebe esse pacote em sua interface WAN. A interface WAN foi configurada para resolver endereços NATted como este. O roteador então ...
- ... verifica sua tabela de tradução NAT, encontra a entrada ...
- ... modifica o pacote para um destino 192.0.2.2 ...
- ... corrige a porta de destino TCP de volta para 4321 ...
- ... e envia pelo caminho alegre (na interface da LAN).
- O PC recebe o pacote e não vê nada sobre o procedimento NAT. Os olhares de pacotes apenas como se 198.51.100.20 tinha enviado, como se o roteador NAT não estava lá em tudo.
Em nenhum momento o tópico de uma "conexão" aparece. O roteador NAT (em sua forma mais simples) não precisa se preocupar com o conteúdo das mensagens. Ele se preocupa com os endereços IP e as portas do remetente e do receptor, mas nada mais. (Concedido: isso provavelmente está ignorando todos os tipos de problemas relacionados à segurança e desempenho; mas esse é o princípio muito básico, como o que está em questão nesta questão.)
Então, como o roteador sabe?
O roteador não precisa saber sobre "conexões". De fato, procedimentos semelhantes, como os descritos para o TCP, existem para o protocolo UDP sem conexão (perfuração de furo UDP) ou podem realmente ser implementados para qualquer protocolo que tenha algo como números de porta na camada de transporte.
A razão pela qual o roteador precisa conhecer o protocolo de nível de transporte (TCP, UDP, ...) em relação ao NAT é principalmente porque as próprias portas não fazem parte do IP; e ports são o que torna o "hack" que (esse tipo de) NAT é, facilmente possível.
Então, para sua pergunta:
Como o NAT decide quais conexões são de entrada e quais são de saída?
As conexões de saída são, por definição, aquelas que começam com um pacote SYN (ou um soco UDP inicial no caso de UDP) que aparece na interface da LAN. Chamá-los de "conexão" no caso do NAT é um pouco demais; eles acabam simplesmente como uma entrada temporária em uma tabela de conversão de NAT (mais as adições de segurança / desempenho que o roteador NAT individual também pode empregar).
As conexões de entrada não existem no cenário que usei na resposta até o momento. É claro que existem variantes do NAT que fazem isso; por exemplo, você pode identificar estaticamente uma porta na interface WAN do roteador com um IP: PORT específico na interface da LAN, o que possibilita executar um servidor dentro da sua LAN NAT. Isso também é frequentemente suportado por roteadores DSL / WLAN baratos para consumidores. E com roteadores "reais", você obviamente pode configurá-los da forma que desejar.
Pacotes IP de entrada / saída adicionais não são diferentes dos dados no exemplo. Depois que o handshake SYN inicial for concluído e o roteador tiver a entrada em sua tabela de tradução, ele passará (com a mesma tradução conforme explicada no exemplo) todos os pacotes adicionais nas duas direções.
Se, no contexto de uma conexão TCP assim estabelecida, o servidor deseja enviar dados ao cliente (o que é perfeitamente possível - o TCP é bidirecional), esses são apenas mais pacotes IP, no que diz respeito ao roteador NAT. Realmente não se importará muito com o conteúdo desses pacotes (isto é, se eles contêm determinadas cargas úteis ou são apenas pacotes de "gerenciamento" do TCP ou o que for).
Em nenhum momento o roteador "fecha o tubo" como você o coloca. Obviamente, o roteador terá alguma noção de quando pode limpar a entrada da tabela de conversão (provavelmente quando perceber um handshake FIN que encerra a conexão, ou por algum tempo limite ou algum estado de erro), mas do início ao fim é um caso contínuo.