Iptables encaminhando as portas para um IP externo de forma transparente (a extremidade remota deve ver o IP de origem real)

4

A pergunta é simples, mas acho que a resposta pode não ser, já que passei por inúmeros tópicos relacionados sem uma resposta concreta.

Desejo encaminhar uma porta 1234 de x.x.x.x para y.y.y.y (ambos na Internet em diferentes locais, ou seja, y.y.y.y não é um IP interno como 10.a.b.c etc) de forma que y.y.y.y seja capaz de obter o IP original de origem conectando-se a x.x.x.x .

Neste momento, ele vê x.x.x.x como o IP de origem usando as regras normais de SNAT ou MASQUERADE. Se y.y.y.y for algum IP interno (como um contêiner lxc em execução em x.x.x.x ), as mesmas regras funcionarão e o contêiner poderá ver o IP de origem real, mas não se y.y.y.y for externo.

Isso pode ser feito de alguma forma?

    
por Sam 12.09.2018 / 08:00

3 respostas

4

Com apenas NAT - não. Pacotes IP possuem apenas um campo 'fonte'.

  • Se você fizer o iptables manter o endereço original do cliente (somente DNAT), então o yyyy tentará enviar as respostas diretamente para o cliente original (que acha que está falando com xxxx e não esperar quaisquer pacotes de yyyy).

  • Se você fizer o iptables colocar seu endereço como a nova fonte (DNAT + SNAT), então y.y.y.y não saberá o endereço original da fonte.

(Este é realmente o mesmo problema de tentar redirecionar a porta da LAN para a mesma LAN, e o segundo método é chamado de 'NAT hairpinning' ou 'NAT reflection'.)

Para fazer isso funcionar, você precisa de um túnel / VPN entre xxxx e yyyy - embrulhe os pacotes originais que você recebe, sem quaisquer alterações, dentro de outro pacote IP que é enviado para aaaa (que então desembrulhe o pacote tunnelled e veja a fonte original).

Claro, isso significa que você precisa de privilégios de root nos dois sistemas para configurar o encapsulamento. Adicionalmente, o destino (y.y.y.y) precisa suportar "policy routing" - Linux e FreeBSD pf são capazes disso. Ele precisa de uma regra que roteará tudo através da VPN se o endereço de origem for um endereço VPN.

Você ainda precisa da regra DNAT do iptables, mas seu "destino de destino" será o endereço de VPN de y, não o endereço público. Você pode usar qualquer tipo de túnel / VPN para isso, do básico "IP-in-IP" ao GRE ao OpenVPN ao WireGuard. Por exemplo:

  • x.x.x.x

    Abra o túnel:

    ip link add gre-y type gre local x.x.x.x remote y.y.y.y ttl 64
    ip link set gre-y up
    ip addr add 192.168.47.1/24 dev gre-y
    

    Adicione uma regra de encaminhamento de porta, como em uma LAN:

    iptables -t nat -I PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 192.168.47.2
    
  • y.y.y.y

    Abra o túnel:

    ip link add gre-x type gre local y.y.y.y remote x.x.x.x ttl 64
    ip link set gre-x up
    ip addr add 192.168.47.2/24 dev gre-x
    

    Verifique se funciona:

    ping 192.168.47.1
    

    Configure o roteamento de políticas, para que as respostas (e somente as respostas) passem pelo túnel:

    ip route add default via 192.168.47.1 dev gre-x table 1111
    ip rule add pref 1000 from 192.168.47.2 lookup 1111
    

(Para usar outro tipo de túnel / VPN, substitua apenas a parte "Trazer o túnel").

    
por 12.09.2018 / 08:34
3

Não, você não pode conseguir isso. O problema é que o roteamento não funcionará.

O host E (externo) envia um pacote ao Host F (encaminhador). F envia esse pacote com a mesma fonte para hospedar D (destino). Esta parte funciona, seja D seja interna ou externa.

Agora, D deve retornar uma resposta e a envia para o endereço de origem no pacote, que é E .

  • Se D for um host interno e F for o gateway padrão para D , o pacote passa F , onde a origem D no pacote de resposta é alterada para F . O host E vê um pacote vindo de F e está tudo bem.
  • Se D for um host externo, F não será o gateway padrão para D e, portanto, D enviará a resposta diretamente para E . O host E obterá a resposta de D , mas espera uma resposta de F e, portanto, descarta o pacote de D . O host E tentará novamente algumas vezes, descartará novamente a resposta do endereço de origem incorreto e, por fim, atingirá o tempo limite.
por 12.09.2018 / 08:33
2

Você provavelmente não conseguirá isso porque o endereço de origem é usado para o pacote de retorno - assim, se o endereço de origem estiver por trás do NAT, ele não poderá ser acessado pela Internet mais ampla.

Há pelo menos duas soluções alternativas (que exigem software e configuração adicionais) comumente usadas - A primeira é usar uma VPN para ignorar o roteador ou, alternativamente, usar entre o roteador e o destino para que o destino saiba como chegar à fonte.

No caso de HTTP e HTTPS, não use regras de firewall IPTABLES, use um proxy (transparente ou regular) no roteador e peça ao servidor proxy para adicionar um cabeçalho X-FORWARDED-FOR que o aplicativo externo pode acesso e processo.

Dependendo do seu aplicativo e firewall exatos, também pode ser possível marcar um endereço IP interno "relativo" modificando a porta de origem da qual a solicitação está vindo (ela ainda virá do endereço dos roteadores, mas você poderá para obter uma sugestão de qual sistema atrás do roteador enviou com base na porta de origem). Eu não vi isso usado na prática.

    
por 12.09.2018 / 08:27