Acessando o servidor DNAT'ted de dentro da LAN

12

Eu tenho uma pequena rede com um roteador, que mantém uma conexão com a Internet, um servidor e algumas estações de trabalho em uma rede local.

Mapa de rede

O servidor deve ser acessado da Internet e há várias entradas DNAT definidas nas tabelas de ip do roteador, desta forma:

-A PREROUTING -i ppp0 -p tcp -m multiport --dports 22,25,80,443 -j DNAT --to-destination 192.168.2.10

Pacotes externos chegam ao roteador via ppp0interface e os internos passam br-lan, o que inclui o switch e o adaptador WLAN. O problema é que, enquanto o acesso externo funciona bem, a tentativa de acessar o servidor de dentro da LAN por um IP externo resolvido pelo DNS (atribuído a ppp0) falha.

A única solução que consegui inventar é adicionar entradas estáticas aos roteadores que /etc/hostsapontam para o IP interno, mas como não existem curingas (e eu tenho pelo menos três domínios de nível superior atribuídos a esse sistema, sem contar dezenas de subdomínios), isso é bastante crocante e propenso a falhas. Você pode sugerir algo melhor?

Eu só encontrei esta pergunta , que não foi muito útil.

Se isso for relevante, o roteador executa o OpenWRT 10.03 Kamikaze com o dnsmasq.

whitequark
fonte
Qual versão do OpenWRT?
Corey S.
@ Corey 10.03 Estável, mas isso não tem nada a ver com o próprio openwrt, não é?
whitequark

Respostas:

3

Estou surpreso que, após quase 8 anos, ninguém explicou como fazer isso da maneira correta, usando o sistema de configuração UCI usado por padrão no OpenWRT.

A resposta de Steven Monday está correta, mas ele usa iptablescomandos diretamente, que é uma camada inferior ao sistema de configuração UCI, e é melhor deixar intocado pela maioria dos usuários do OpenWRT, se possível.

A maneira correta de acessar servidores internos por meio de seus combos IP / porta públicos de outro host interno em UCI é ativando a opção de configuração reflectionem cada destino DNAT específico no arquivo /etc/config/firewall. Esse comportamento está documentado aqui .

Por exemplo:

config redirect option target 'DNAT' option src 'wan' option dest 'lan' option proto 'tcp' option src_dport '44322' option dest_ip '192.168.5.22' option dest_port '443' option name 'apache HTTPS server' option reflection '1'

Nota: De acordo com a documentação do OpenWRT indicada, reflectioné ativado por padrão. Nos meus testes, esse não foi o caso.

vittorio88
fonte
15

Excluí minha resposta original, porque não estava totalmente confiante de que estava correta. Desde então, tive tempo para configurar uma pequena rede virtual de VMs para simular a rede em questão. Aqui está o conjunto de regras de firewall que funcionaram para mim (em iptables-saveformato, apenas para a nattabela):

-A PREROUTING -d 89.179.245.232/32 -p tcp -m multiport --dports 22,25,80,443 -j DNAT --to-destination 192.168.2.10
-A POSTROUTING -s 192.168.2.0/24 -o ppp0 -j MASQUERADE
-A POSTROUTING -s 192.168.2.0/24 -d 192.168.2.10/32 -p tcp -m multiport --dports 22,25,80,443 -j MASQUERADE

A primeira POSTROUTINGregra é uma maneira direta de compartilhar a conexão da Internet com a LAN. Deixei por completo.

A PREROUTINGregra e a segunda POSTROUTINGregra juntos estabelecem os NATs apropriados, para que as conexões com o servidor através do endereço IP externo possam ocorrer, independentemente de as conexões serem originárias de fora ou de dentro da LAN. Quando os clientes na LAN se conectam ao servidor por meio do endereço IP externo, o servidor vê as conexões como provenientes do endereço IP interno do roteador (192.168.2.1).

Curiosamente, verifica-se que existem algumas variações da segunda regra POSTROUTING que também funcionam. Se o destino for alterado para -j SNAT --to-source 192.168.2.1, o efeito é (sem surpresa) o mesmo que MASQUERADE: o servidor vê as conexões dos clientes locais da LAN como originárias do endereço IP interno do roteador . Por outro lado, se o destino for alterado para -j SNAT --to-source 89.179.245.232, os NATs ainda funcionarão, mas desta vez o servidor verá as conexões dos clientes locais da LAN como originárias do endereço IP externo do roteador (89.179.245.232).

Por fim, observe que o seu original PREROUTING/ DNATregra com -i ppp0não funciona, porque a regra nunca corresponde aos pacotes provenientes dos clientes da LAN (pois eles não entram no roteador pela ppp0interface). Seria possível fazê-lo funcionar adicionando uma segunda PREROUTINGregra apenas para os clientes LAN internos, mas seria deselegante (IMO) e ainda precisaria se referir explicitamente ao endereço IP externo.

Agora, mesmo depois de ter apresentado uma solução "NAT em gancho de cabelo" (ou "loopback NAT", ou "reflexão NAT", ou o que alguém preferir chamá-lo) em detalhes, ainda acredito que uma solução DNS com horizonte dividido - -com clientes externos resolvendo para o IP externo e clientes internos resolvendo para o IP interno --- seria o caminho mais recomendável a seguir. Por quê? Como mais pessoas entendem como o DNS funciona do que o NAT, e uma grande parte da criação de bons sistemas é optar por usar peças que possam ser mantidas. É mais provável que uma configuração de DNS seja entendida e, portanto, mantida corretamente, do que uma configuração arcana de NAT (IMO, é claro).

Steven segunda-feira
fonte
Isso funciona perfeitamente, muito obrigado! Concordo que a configuração do DNS é melhor, mas você não pode encaminhar portas diferentes no mesmo IP externo para máquinas diferentes na LAN com ele. De qualquer forma, sou o único que manterá essa configuração, então tudo bem.
whitequark
Fico feliz em saber que isso funcionou para você!
Steven Monday
O que é "IMO"? Organização Internacional de Meteoros www.imo.net?
precisa
@ macmadness86 IMO == Na minha opinião
Steven segunda-feira
3

Uma solução comum é apontar seus hosts internos para um servidor DNS local que retorne o endereço "interno" correto para esses nomes de host.

Outra solução - e estamos usando isso onde trabalho nos firewalls da Cisco - é reescrever as respostas DNS no firewall que correspondem a esses endereços. Eu não acho que existem ferramentas para Linux que fazem isso agora.

Você deve poder configurar o roteamento no seu gateway para fazer a coisa certa. Pode ser necessário configurar os servidores para conhecer seu endereço IP mapeado externamente (por exemplo, atribuindo-o a uma interface fictícia). Com essa configuração, a comunicação de um sistema interno para outro sistema interno - usando seu endereço "externo" - passaria pelo roteador.

larsks
fonte
Hmm. Então, você está sugerindo adicionar o IP externo às interfaces dos servidores e depois configurar o roteador para que ele encaminhe todos os pacotes para o IP externo vindo de dentro da LAN para esse servidor? Interessante, testarei em breve.
whitequark 23/11
Você pode sugerir a configuração? Eu tentei isso:, ip rule add to 89.179.245.232 dev br-lan table 10; ip route add 89.179.245.232 via 192.168.2.10 dev br-lan table 10e não está funcionando.
whitequark
O que há na tabela de roteamento 10? Nos servidores internos, você provavelmente deseja que eles tenham um endereço 192.168.xx local (para se comunicar localmente) e o endereço público (como um alias) em sua interface principal.
Larsks
2

O que você está pedindo para fazer é chamado NAT Loopbacke requer que você adicione uma regra SNAT para que os pacotes originários da sua LAN para o servidor retornem pelo roteador:

-A POSTROUTING -p tcp -s 192.168.2.0/24 -d 192.168.2.10 -m multiport --dports 22,25,80,443 -j SNAT --to-source 89.179.245.232
SiegeX
fonte
Infelizmente, isso não funciona. Originalmente, eu perdi a -i ppp0opção na minha regra em questão, pois isso foi tratado por outra cadeia; essa regra impediria o roteamento de pacotes provenientes da LAN (e, se eu permitir, os pacotes sairão da fonte errada e serão rejeitados).
whitequark
Tentaste? Isso afetará apenas os pacotes da sua LAN que vão para o IP do servidor nessas portas muito específicas.
SiegeX
Sim eu fiz. (E eu tentei mudar a primeira regra também). Por exemplo, dig envia um pacote para 192.168.2.1 # 53 e, em seguida, obtém uma resposta inesperada de 192.168.2.10 # 53, com ou sem sua regra.
whitequark
0

O comentário de larsks sobre como hospedar uma versão interna do namespace \ domain é geralmente a maneira como lidei com esse problema no passado. Obviamente, você precisa de um servidor DNS internamente para fazer isso.

CurtM
fonte
Sim, eu escrevi que estou usando o dnsmasq. Alguma idéia sobre como configurar a substituição automática?
whitequark
Não sei nada sobre o OpenWRT e o Kamikaze, mas com base no que estou lendo - e se você adicionou o seguinte ao seu /etc/dnsmasq.conf "cname = ext-hostname.domain.com, int-hostname.domain.com"
CurtM
Bem, até onde pude determinar, o dnsmasq cnamenão suporta máscaras e, portanto, não é aplicável a mim devido à contagem de subdomínios.
whitequark
0

Eu vim com a seguinte solução para permitir que minha rede de hóspedes se conectasse às portas que foram encaminhadas da minha rede WAN para LAN. Este script é colocado na minha seção "Rede -> Firewall -> Regras personalizadas":

# lookup the public IP (DDNS resolves to this)
wanip=$(ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}')

# Guest network to LAN
# srcname is the guest network name, this needs to match for iptables
srcname=guest
# CIDR notation of guest and lan networks
srcnet=192.168.15.0/24
tgtnet=192.168.10.0/24
# router (openwrt) IP on lan network
tgtrouter=192.168.10.1
# host on lan network where ports are normally forwarded
tgthost=192.168.10.5
# ports to forward as a list or range
tcpports=8080,9090
udpports=12345

prechain=prerouting_${srcname}_rule
postchain=postrouting_${srcname}_rule

# reset the tables to prevent duplicate rules
iptables -t nat -F ${prechain}
iptables -t nat -F ${postchain}

iptables -t nat -A ${prechain} -s ${srcnet} -d ${wanip}/32 -p tcp -m tcp -m multiport --dports ${tcpports} -m comment --comment "${srcname} NAT reflection TCP DNAT" -j DNAT --to-destination ${tgthost}
iptables -t nat -A ${postchain} -s ${srcnet} -d ${tgthost}/32 -p tcp -m tcp -m multiport --dports ${tcpports} -m comment --comment "${srcname} NAT reflection TCP SNAT" -j SNAT --to-source ${tgtrouter}
iptables -t nat -A ${prechain} -s ${srcnet} -d ${wanip}/32 -p udp -m udp -m multiport --dports ${udpports} -m comment --comment "${srcname} NAT reflection UDP DNAT" -j DNAT --to-destination ${tgthost}
iptables -t nat -A ${postchain} -s ${srcnet} -d ${tgthost}/32 -p udp -m udp -m multiport --dports ${udpports} -m comment --comment "${srcname} NAT reflection UDP SNAT" -j SNAT --to-source ${tgtrouter}

Para dar suporte à reinicialização, eu precisava executar o seguinte na linha de comando ssh no openwrt (caso contrário, acredito que há uma condição de corrida em que algumas regras foram adicionadas e depois liberadas durante a reinicialização):

uci set firewall.@include[0].reload="1"
uci commit firewall

A reflexão NAT é configurada para conexões dentro da rede LAN para si mesma, mas não para outras redes se você tiver criado várias interfaces para isolar o tráfego. Tentei configurar uma regra de encaminhamento a partir da interface da web, mas isso envia todo o tráfego para uma porta da rede de convidados para esse host da LAN. O item acima intercepta apenas solicitações ao IP da WAN em vez de todo o tráfego da rede.

Um DNS interno pode ser usado em vez disso, mas apenas se todas as portas encaminhadas forem para um único host. Se você tiver vários hosts nos quais encaminha diferentes portas, poderá repetir as regras para diferentes portas para diferentes tgthostIPs e portas.

BMitch
fonte
Nos kernels atuais, existe um conntrackmódulo de correspondência. E tudo o que você precisa para resolver o problema é usar a regra única assim:iptables -t nat -A POSTROUTING --dst <lan-net> ! --src <lan-gw-ip> -m conntrack --ctstate DNAT --ctorigdst <wan-gw-ip> -j MASQUERADE
Anton Danilov
@AntonDanilov legal, eu gosto disso. As regras que usei foram baseadas nas regras NAT de reflexão já existentes no OpenWRT para conexões da mesma sub-rede. Não tenho certeza se eles tiveram outras razões para isso além de possivelmente serem escritas antes que o conntrack estivesse disponível.
BMitch 13/05/19