Loopback para o endereço IP público encaminhado da rede local - Hairpin NAT

45

Esta é uma pergunta canônica sobre o Hairpin NAT (Loopback NAT).

A forma genérica desta pergunta é:

Temos uma rede com clientes, um servidor e um roteador NAT. Há encaminhamento de porta no roteador para o servidor, portanto alguns de seus serviços estão disponíveis externamente. Temos DNS apontando para o IP externo. Os clientes da rede local não conseguem se conectar, mas funcionam externamente.

  • Por que isso falha?
  • Como posso criar um esquema de nomeação unificado (nomes DNS que funcionam local e externamente)?

Esta pergunta tem respostas mescladas de várias outras perguntas. Eles originalmente fizeram referência ao FreeBSD, D-Link, Microtik e outros equipamentos. No entanto, todos estão tentando resolver o mesmo problema.

adoptilot
fonte
1
Se seu objetivo é testar o acesso da Internet, não há motivo para mexer com as rotas do roteador e / ou com as configurações de DNS de qualquer maneira, na melhor das hipóteses, pelo lado de dentro você verificaria se a parte interna do roteador funciona. Eu sugiro que você use um servidor proxy em algum lugar do lado de fora.

Respostas:

16

O que você está procurando é chamado de "hairpin NAT". As solicitações da interface interna para um endereço IP atribuído à interface externa devem ter NAT, como se tivessem vindo da interface do lado externo.

Eu não tenho nenhuma familiaridade com o FreeBSD, mas lendo o manual "pf" para o OpenBSD ( http://www.openbsd.org/faq/pf/rdr.html ) as soluções propostas para DNS de horizonte dividido, usando um A rede DMZ ou proxy TCP me leva a acreditar que "pf" não suporta NAT hairpin.

Eu gostaria de seguir a rota do DNS com horizonte dividido e não usar endereços IP em URLs internamente, mas usar nomes.

Evan Anderson
fonte
Corri por esse tópico enquanto tentava resolver o mesmo problema, e embora seja verdade que o FreeBSD não suporta hairpin nat imediatamente, existem maneiras de redirecionar e NAT o tráfego interno -> externo -> interno.
carmesim-Garça
Por exemplo: no nat on $int_if proto tcp from $int_if to $int_net , nat on $int_if proto tcp from $int_net to $hairpin_int port $hairpin_ports -> $int_if, rdr on $int_if proto tcp from $int_net to $ext_if port $hairpin_ports -> $hairpin_int
carmesim-Garça
48

Como essa foi considerada a pergunta canônica no NAT hairpin , pensei que provavelmente deveria ter uma resposta mais válida em geral do que a atualmente aceita, que (embora excelente) se relaciona especificamente ao FreeBSD.

Esta pergunta se aplica aos serviços fornecidos pelos servidores nas redes IPv4 endereçadas pelo RFC1918, que são disponibilizados aos usuários externos pela introdução do NAT de destino (DNAT) no gateway. Usuários internos tentam acessar esses serviços através do endereço externo. O pacote sai do cliente para o dispositivo de gateway, que reescreve o endereço de destino e o injeta imediatamente na rede interna. É essa mudança acentuada que o pacote produz no gateway que dá origem ao nome hairpin NAT , por analogia com a curva hairpin .

O problema surge quando o dispositivo de gateway reescreve o endereço de destino, mas não o endereço de origem. O servidor recebe um pacote com um endereço de destino interno (próprio) e um endereço de origem interno (do cliente); sabe que pode responder diretamente a esse endereço, e assim o faz. Como essa resposta é direta, ela não passa pelo gateway, o que, portanto, nunca tem a chance de equilibrar o efeito do NAT de destino de entrada no pacote inicial, reescrevendo o endereço de origem do pacote de retorno.

O cliente envia um pacote para um endereço IP externo , mas obtém uma resposta de um endereço IP interno . Não tem idéia de que os dois pacotes façam parte da mesma conversa; portanto, nenhuma conversa acontece.

A solução é que os pacotes que requerem esse NAT de destino e que alcançam o gateway da rede interna também executem o NAT de origem (SNAT) no pacote de entrada, geralmente reescrevendo o endereço de origem como o do gateway. O servidor então pensa que o cliente é o próprio gateway e responde diretamente a ele. Isso, por sua vez, dá ao gateway a chance de equilibrar os efeitos do DNAT e do SNAT no pacote de entrada, reescrevendo os endereços de origem e de destino no pacote de retorno.

O cliente pensa que está falando com um servidor externo. O servidor acha que está falando com o dispositivo de gateway. Todas as festas são felizes. Um diagrama pode ser útil neste momento:

insira a descrição da imagem aqui

Alguns dispositivos de gateway do consumidor são brilhantes o suficiente para reconhecer os pacotes para os quais a segunda etapa NAT é necessária, e provavelmente funcionarão imediatamente em um cenário NAT em gancho. Outros não são e, portanto, não são, e é improvável que possam ser feitos para funcionar. Uma discussão sobre quais dispositivos de nível de consumidor são os que não são relacionados à falha do servidor.

Dispositivos de rede adequados geralmente podem ser instruídos a funcionar, mas - porque eles não estão tentando adivinhar seus administradores - eles precisam ser instruídos a fazê-lo. O Linux iptablescostuma fazer o DNAT assim:

iptables -t nat -A PREROUTING  -p tcp --dport 80 -j DNAT --to-destination 192.168.3.11

que habilitará o DNAT simples para a porta HTTP para um servidor interno ativado 192.168.3.11. Mas para habilitar o hairpin NAT, seria necessário também uma regra como:

iptables -t nat -A POSTROUTING -d 192.168.3.11 -p tcp --dport 80 -j MASQUERADE

Observe que essas regras precisam estar no lugar certo nas cadeias relevantes para funcionar corretamente e, dependendo das configurações da filtercadeia, podem ser necessárias regras adicionais para permitir o fluxo do tráfego NAT. Todas essas discussões estão fora do escopo desta resposta.

Mas, como outros já disseram, habilitar o NAT com gancho de cabelo corretamente não é a melhor maneira de lidar com o problema. O melhor é o DNS com horizonte dividido , em que sua organização fornece respostas diferentes para a pesquisa original, dependendo da localização do cliente solicitante, tendo servidores físicos diferentes para usuários internos e externos ou configurando o servidor DNS para responder de maneira diferente, de acordo com o endereço do cliente solicitante.

MadHatter apoia Monica
fonte
Estou pensando um pouco sobre os endereços nos pacotes trocados entre gateway e servidor. Não seria mais consistente se o servidor visse o endereço IP público do roteador como o IP do cliente? Tecnicamente, ambos podem funcionar, mas, para permanecer consistente com a forma como outros servidores veem os clientes, ele precisaria usar o IP público.
kasperd
1
Estou assumindo que você está se referindo ao último caso, "NAT hairpin adequado". O importante é reescrever o endereço de origem no pacote de entrada de forma que ele volte ao roteador, que pode reverter o DNAT e o SNAT e, assim, evitar o problema. Qual dos muitos endereços que o roteador usa para fazer isso é mais um ponto de gosto e, se você está fazendo isso iptables, certamente é algo que pode ser configurado, se assim o desejar.
MadHatter apoia Monica
1
Muitos administradores, inclusive eu, consideram o DNS com horizonte dividido uma cura pior que a doença. Se um SNAT adicional puder ser chamado de doença. Um DNS de exibição dividida confunde os humanos e facilita a vida dos roteadores. Este tópico seria melhor tratado por uma pergunta / resposta separada do ServerFault.
Kubanczyk
Minha resposta é muito sobre NAT hairpin. Eu posso ver os prós e os contras de abrir uma pergunta canônica de "DNS com horizonte dividido": os profissionais incluem ter uma pergunta dedicada aos usos e problemas do SHDNS, mas os contras são que essa pergunta já teve muitas outras questões relacionadas a ele se fundiu a ele, de modo que também poderia acontecer com sua pergunta. Se fosse eu, levantaria a questão sobre a meta e buscaria consenso. Se essa pergunta for escrita, espero ler sua resposta!
MadHatter apoia Monica
@MadHatter Onde devo escrever o comando iptables? no cliente ou gateway ou servidor?
Rocky Balboa
9

O problema aqui é que o seu roteador não NAT o endereço do seu cliente interno. Portanto, o handshake TCP falha.

Vamos assumir os seguintes IPs

  • Cliente: 192.168.1.3
  • Servidor: 192.168.1.2
  • Roteador interno: 192.168.1
  • Roteador externo: 123.123.123.1

Eis aqui o que está acontecendo:

  1. O cliente (192.168.1.3) envia o TCP-SYN para o seu IP externo, porta 80 (123.123.123.1:80)
  2. O roteador vê a regra de encaminhamento de porta e encaminha o pacote para o servidor (192.168.1.2:80) sem alterar o IP de origem (192.168.1.3)
  3. O cliente aguarda um SYN-ACK do IP externo
  4. O servidor envia sua resposta de volta ao cliente diretamente, porque está na mesma sub-rede. Ele não envia o pacote ao roteador, o que reverteria o NAT.
  5. O cliente recebe um SYN-ACK de 192.168.1.2 em vez de 123.123.123.1. E descarta.
  6. O cliente ainda aguarda um SYN-ACK de 123.123.123.1 e atinge o tempo limite.
PEra
fonte
4

Por que não usar DNS de horizonte dividido em vez de codificar endereços IP em qualquer lugar? Você teria ext.yourdomain apontando para 217.xxx por fora e depois 192.xxx por dentro.

Ryaner
fonte
1
Se você tiver um momento, poderá expandir o que é o DNS Split-Horizon, como ele funciona e as principais desvantagens. Esta é uma pergunta canônica agora e seria bom ter uma resposta mais completa.
Chris S
2

Se for um roteador D-Link original (ou seja, não Rev. D / Firmware versão 1.00VG da Virgin Media), você poderá ajustar as configurações para solucionar esse problema. (No entanto, concordo com a sugestão do DD-WRT do pôster anterior por muitas outras razões!)

  1. Faça login na interface da web do roteador
  2. Clique na guia Avançado na parte superior
  3. Clique na guia Configurações do firewall à esquerda
  4. Clique no botão de opção Endpoint Independent em TCP Endpoint Filtering , como mostra a captura de tela abaixo (ou veja o emulador de roteador no site da D-Link)
  5. Salve as alterações; Você Terminou

Captura de tela da interface da web do roteador D-Link

Esta captura de tela é do modelo Rev. C; o seu pode ser um pouco diferente.

David
fonte
2

Respondeu recentemente uma pergunta semelhante: o NAT estático da Cisco não está funcionando no lado da LAN e acabou de perceber que esta é uma pergunta canônica. Então, permita-me resumir a solução aqui.

Primeiro de tudo: esqueça o NAT (se você puder) - a questão não é sobre configurar o NAT. Trata-se de acessar um servidor colocado atrás do NAT pela Internet e pela LAN. Empregar duas zonas DNS é uma alternativa viável, mas nem sempre é a solução. Mas a solução existe e é incrivelmente simples (embora não seja perfeita, provavelmente):

(1) no servidor: adicione o endereço IP público como um endereço IP secundário na interface de rede do servidor com a máscara 255.255.255.255 (serviço da Web ou o que você quiser no servidor também deve escutar esse endereço IP); todos os sistemas operacionais modernos permitirão que você faça isso (ou uma interface de loopback com o endereço IP público atribuído a ela pode ser usada em vez de adicionar um IP secundário à interface principal).

(2) nos hosts da LAN: adicione uma rota de host para o endereço IP público, por exemplo, para hosts do Windows, use o seguinte comando: route -p add 203.0.113.130 mask 255.255.255.255 192.168.1.11 (você também pode usar o DHCP " rota estática "para distribuir a rota). Ou, se houver (s) comutador (es) L3 / roteador (s) entre os clientes e o roteador voltado para a Internet, configure a rota do host nesse (s) comutador (es) intermediário (s) / roteador (s), não nos clientes.

Para aqueles que se referem ao handshake de três vias TCP: ele funcionará bem na configuração proposta.

Por favor, forneça feedback (pelo menos, vote).

Sergio
fonte
Exigência # 2 faz com que este não funcione bem em BYOD redes ...
Michael
1

Responderei às minhas perguntas apenas para ampliar horizontes para aqueles com problemas semelhantes.

Fiz contato com meu provedor de serviços de Internet e pedi que tentassem resolver meus problemas. O que eles me ofereceram é outro endereço IP público apenas para servidor, agora eu tenho tráfego local no lado WAN do FreeBSD e fizemos tubos específicos para uma taxa de transferência mais rápida do tráfego local para o IP público do servidor

adoptilot
fonte
2
Esta solução implementa uma rede de perímetro ou DMZ e é uma boa alternativa para o Hairpin NAT e o Split-Horizon DNS.
Chris S
1

Do ponto de vista técnico, a melhor solução para esse problema é ativar o IPv6 na sua rede. Quando o IPv6 está ativado, você precisa criar um registro AAAA para o seu domínio. Mantenha o registro A existente apontando para o IPv4 externo do roteador . Crie um registro AAAA apontando para o endereço IPv6 do servidor .

O IPv6 possui endereços suficientes para evitar o NAT; portanto, você não precisará do NAT hairpin para IPv6. E depois de ativar o IPv6 e criar registros AAAA, qualquer cliente que suporte o RFC 8305 tentará o IPv6 antes do IPv4. Isso significa que você também não precisa de NAT hairpin para IPv4, porque os clientes não o usarão.

Você ainda precisará do seu NAT IPv4 existente para conexões de saída e encaminhamento de porta para conexões de entrada até que a maior parte do mundo tenha habilitado o IPv6 também.

Também é mais rápido.

O uso do IPv6 oferece um desempenho melhor do que o NAT hairpin.

Com o hairpin NAT, seu cliente enviará um pacote através de um comutador para o roteador, o roteador executará duas rodadas de tradução e finalmente enviará o pacote através do comutador para o servidor. Pacotes do servidor para o cliente percorrerão todo o caminho ao contrário.

Com o IPv6, você evita o NAT; em vez disso, os pacotes são enviados diretamente pelo comutador entre cliente e servidor. Isso significa que, em uma viagem de ida e volta, você reduz o número de passagens pelo switch de 4 para 2 e evita 2 viagens pelo roteador e as 4 traduções que o roteador teria realizado. Isso se traduz em melhor desempenho.

Isso é verdade mesmo se você usar um switch incorporado na mesma caixa do roteador.

E se o ISP não tiver IPv6?

Se você estiver usando um provedor de serviços de Internet que não suporte IPv6, perguntarei se você deveria hospedar servidores nessa rede. Estas são minhas sugestões sobre o que fazer se o provedor de serviços de Internet não suportar atualmente o IPv6.

Primeiro diga ao ISP que você precisa do IPv6. E talvez lembrá-los de que o protocolo IPv6 existe há 20 anos e, portanto, eles estão atrasados ​​em seu suporte. Se isso não for suficiente para o ISP levar você a sério, comece a procurar outros ISPs.

Se você encontrar um ISP com suporte ao IPv6, poderá executar os dois por um período de transição. No roteador conectado ao novo ISP, você pode desativar o IPv4 no lado da LAN e, em seguida, conectar os lados da LAN dos dois roteadores ao mesmo switch. IPv4 e IPv6 são dois protocolos independentes e, como tal, não é problema se essas conexões passam por roteadores diferentes. Como benefício colateral, ele oferece uma certa redundância se uma das conexões tiver uma interrupção.

Se você não conseguir encontrar um ISP com suporte ao IPv6, considere mudar o servidor para um recurso de hospedagem. Com um servidor em uma instalação de hospedagem, você fica menos dependente da localização geográfica e, por esse motivo, há mais concorrência entre os provedores, o que ajudará a garantir que exista um que atenda às suas necessidades.

Mover o servidor para um recurso de hospedagem não dará IPv6 a seus clientes, mas mover o servidor significa que você não precisa mais do NAT hairpin para alcançá-lo.

O que você não deve fazer

Não ative o IPv6 e crie registros AAAA se você não tiver uma maneira de rotear o tráfego IPv6. Se o seu provedor de serviços de Internet não suportar IPv6, mas você optar por ativar o IPv6 na sua LAN de qualquer maneira (talvez usando endereços RFC 4193) e criar registros AAAA, ele funcionará para clientes na sua LAN que acessam o servidor na sua LAN. Mas a comunicação entre sua LAN e o mundo externo tentaria primeiro o IPv6 (o que não funcionaria) e você confiaria em voltar ao IPv4, que na melhor das hipóteses é um pouco mais lento ou, na pior das hipóteses, não acontece.

Kasperd
fonte
0

Como também fiz essa pergunta (consulte Como faço para acessar um serviço de rede NAT por trás de um firewall usando seu IP externo? ) E fui redirecionado aqui, mas as respostas aqui não forneceram uma solução (ao contrário de explicações genéricas ) forneça minha iptablessolução Linux ( específica) aqui para economizar a todos algumas horas de experimentação. Este arquivo está no iptables-restoreformato e pode ser lido diretamente no iptables (depois de editar os endereços IP, é claro). Isso é para um servidor Web (porta 80) e apenas para IPv4 - as regras para IPv6 e SSL (porta 443) são análogas.


# Port forwarding for VM / Container access with „hairpin NAT“.
*nat
:PREROUTING ACCEPT [3:205]
:INPUT ACCEPT [59:670]
:OUTPUT ACCEPT [16:172]
:POSTROUTING ACCEPT [20:257]

# This was simple port forwarding - access works from outside but not from inside
#-A PREROUTING  -4 -p tcp -i eth0 --dport 80 -j DNAT --to web.local:80

# This is real hairpin NAT which allows „web.local“ to access itself via the VM hosts external IP.
# First we need to masquerade any traffic going out the external interface:
-A POSTROUTING -o eth0 -j MASQUERADE

# Then we need to reroute incoming traffic on the public IP to the local IP:
-A PREROUTING  -4 -p tcp -d web.public.com --dport  80 -j DNAT --to web.local:80

# And finally we need to tell the router that the source IP of any traffic
# coming from the LAN must be source-rewritten when going to the web server:
-A POSTROUTING -4 -p tcp -s lan.local/24 -d web.local --dport  80 -j SNAT --to-source web.public.com:80

COMMIT

Substituir lan.local, web.locale web.public.comcom a sua rede local (eg. 10.0.x.0 / 24), IP local do seu servidor web (por exemplo, 10.0.1.2) e IP público do seu roteador (por exemplo. 4.5.6.7). Isso -4é apenas para permitir regras IPv6 e IPv4 no mesmo arquivo (linhas ignoradas por ip6tables). Além disso, lembre-se de colocar endereços IPv6 entre [colchetes] quando eles incluem declarações de porta, por exemplo [fe0a:bd52::2]:80.

Essas foram todas as coisas que me levaram a arrancar os cabelos ao tentar implementar as explicações nesta pergunta. Espero não ter deixado nada de fora.

Jens
fonte
O MASQUERADE na interface wan geralmente é útil, mas não está relacionado à questão "NAT hairpin". A resposta canônica propõe o MASQUERADE na interface LAN e você propõe um SNAT (o SNAT é aproximadamente o mesmo que o MASQUERADE ). Você força o IP de origem um tanto estranho: a substituição da porta.
Kubanczyk
0

Vou adicionar uma resposta aqui, pois os comentários aqui não abordaram meu problema específico. Eu suspeito que é porque eu acertei um bug do kernel do linux desagradável. A configuração é:

internet <--> modem 1.1.1.1/30 <--> switch <---> LAN 10.1.1.0/24
                                      ^
        +----------------------+      |
        |              /--eth0 o <----/
        |              |       |           
        | 10.1.1.1/24 br0      |           v (antenna)
        |  1.1.1.2/30  |       |           |
        |              \-wlan0 o ----------/
        +----------------------+ 

Apesar da imagem complexa, a única alteração relevante nas situações abordadas em outros comentários é a adição da ponte de software, br0. Está lá porque a caixa de gateway também é um ponto de acesso sem fio para a LAN.

Nossa caixa de gateway ainda está executando tarefas de NAT para as máquinas na LAN. Por ter apenas 1 porta Ethernet, é forçado a fazer NAT hairpin. Eu suspeito que ele deveria funcionar apenas com as regras do iptables fornecidas em outros comentários aqui, mas no kernel Linux 4.9, pelo menos, não. Em 4.9, enquanto nossa caixa de gateway pode acessar a Internet, as máquinas na LAN que tentam acessá-lo via NAT não podem.

tcpdumpmostra respostas aos pacotes recebidos atingindo eth0, mas eles não saem de br0. A execução deste comando corrige que:

ebtables -t brouter -A BROUTING -d 01:00:00:00:00:00/01:00:00:00:00:00 -j ACCEPT
ebtables -t brouter -A BROUTING -p IPv4 --ip-dst 10.1.1.0/24 -j ACCEPT
ebtables -t brouter -A BROUTING -p IPv4 --ip-src 10.1.1.0/24 -j ACCEPT
ebtables -t brouter -A BROUTING -p IPv4 -j DROP

Antes da execução desse comando, os pacotes recebidos são processados ​​de acordo com o comportamento padrão do kernels, que é entregá-los à ponte e depois passar os módulos de roteamento do kernel. O comando força os pacotes que não são da LAN a contornar a ponte e ir diretamente para o roteamento, o que significa que a ponte não tem chance de descartá-los. Os endereços de difusão e multicast devem ter uma ponte, caso contrário, coisas como DHCP e mDNS não funcionarão. se você estiver usando o IPv6, também deverá adicionar regras para ele.

Você pode ficar tentado a corrigir o problema usando este:

brctl hairpin br0 eth0 on
brctl hairpin br0 wlan0 on

Eu certamente estava tão tentado - foi minha primeira tentativa. Assim que eu fiz isso, as máquinas na LAN obtiveram acesso à Internet, então funcionaram por um tempo. Ocorreu o seguinte (e não me importei em repetir o experimento):

  1. Os tempos de ping na LAN para o gateway dobraram em intervalos de 10 segundos, passando de 0,1 ms para 0,2 ms, 0,4 ms, 0,8 ms, 2 ms e assim por diante até que a caixa do gateway estivesse inacessível pela LAN. Cheirava como uma tempestade de pacotes, mas o STP estava ligado em todos os lugares.
  2. Pouco depois de todos os pontos de acesso sem fio terem morrido.
  3. Enquanto tentavam diagnosticar o que estava acontecendo com a rede sem fio, todos os telefones IP foram reiniciados.
  4. Pouco tempo depois, as máquinas com fio perderam todo o contato com a LAN.

A única saída era reiniciar todas as máquinas do prédio. A única exceção foram os comutadores de hardware, que não puderam ser reinicializados. Eles tinham que ser desligados e desligados.

Russell Stuart
fonte
0

Como é uma pergunta canônica. Eu responderei se você tiver um roteador Sonicwall.

A expressão a saber é política de loopback NAT

Este documento descreve como um host em uma LAN da SonicWall pode acessar um servidor na LAN da SonicWall usando o endereço IP público do servidor no FQDN. Imagine uma rede NSA 4500 (SonicOS Enhanced) na qual a sub-rede da LAN principal é 10.100.0.0 / 24 e o IP da WAN principal é 3.3.2.1. Digamos que você tenha um site para seus clientes e seu nome de host seja. Você já escreveu as políticas e regras necessárias para que pessoas de fora possam acessar o site, mas ele está realmente rodando em um servidor do lado privado 10.100.0.2. Agora imagine que você é uma pessoa usando um laptop no lado privado, com IP de 10.100.0.200. Você deseja acessar o servidor usando seu nome público, porque faz o mesmo quando o laptop está com você na estrada. Se você se sentar no lado privado e solicitar http://www.example.com>, loopback é o que torna possível que isso funcione, mesmo que o servidor esteja realmente próximo a você em um endereço IP local.

Para permitir essa funcionalidade, você precisará criar uma política de loopback NAT, também conhecida como reflexão ou gancho de cabelo NAT.

Política de loopback usando o endereço IP da interface WAN

Login to the SonicWall Management GUI.
Navigate to Manage | Rules | NAT Policies submenu.
Click on the Add button.
Create the following NAT Policy.
Original Source: LAN Subnets (or Firewalled Subnets if you want hosts in other zones to be included)
Translated Source: WAN Interface IP
Original Destination: WAN Interface IP
Translated Destination: (LAN server object)
Original Service: Any
Translated Service: Original
Inbound Interface: Any
Outbound Interface: Any

O sonicwall reconhecerá o serviço externo que você tentar entrar em contato e reescreverá o endereço de destino para caber no endereço interno do servidor, assim será transparente para o computador.

yagmoth555
fonte
-2

No FreeBSD usando PF é fácil como (no seu arquivo pf.conf):

extif = "tun0"
intif = "em0"
{other rules}...
nat on $intif from any to 192.168.20.8 port 80 -> ($extif)

192.168.20.8 seria o servidor da web interno.

Otto
fonte