AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / server / Perguntas / 1144741
Accepted
TCB13
TCB13
Asked: 2023-09-29 20:06:25 +0800 CST2023-09-29 20:06:25 +0800 CST 2023-09-29 20:06:25 +0800 CST

nftables: NAT hairpin / loopback com IP dinâmico

  • 772

Eu tenho um servidor Debian 12 (IP público 85.xxx.xxx.xxxem enp6s0) executando vários contêineres LXC em uma ponte de rede cbr0.

Como o IP público é dinâmico, tive que configurar forward+ preroutingregras dnatpara que as solicitações recebidas chegassem aos contêineres. Por exemplo. a porta 80/443 é atribuída ao contêiner 10.10.0.1. Aqui estão minhas nftablesregras:

flush ruleset

table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;

    ct state {established, related} accept
    iifname lo accept
    iifname cbr0 accept
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept
  }
  chain forward {
    type filter hook forward priority 0; policy accept;
  }
  chain output {
    type filter hook output priority 0;
  }
}

table ip filter {
  chain forward {
    type filter hook forward priority 0; policy drop;

    oifname enp6s0 iifname cbr0 accept
    iifname enp6s0 oifname cbr0 ct state related, established accept
    # Webproxy
    iifname enp6s0 oifname cbr0 tcp dport 80 accept
    iifname enp6s0 oifname cbr0 udp dport 80 accept
    iifname enp6s0 oifname cbr0 tcp dport 443 accept
    iifname enp6s0 oifname cbr0 udp dport 443 accept
  }
}

table ip nat {

  chain postrouting {
    type nat hook postrouting priority 100; policy accept;
  }

  chain prerouting {
    type nat hook prerouting priority -100; policy accept;
    # Webproxy
    iifname enp6s0 tcp dport 80 dnat to 10.10.0.1:80
    iifname enp6s0 udp dport 80 dnat to 10.10.0.1:80
    iifname enp6s0 tcp dport 443 dnat to 10.10.0.1:443
    iifname enp6s0 udp dport 443 dnat to 10.10.0.1:443
  }

}

Agora o problema é: NAT hairpin. Tenho vários contêineres hospedando sites e às vezes acontece que alguns deles precisam se comunicar com outros contêineres usando nomes de domínio. Quando eles executam uma consulta DNS para esses domínios, eles obtêm o IP do host e a comunicação falha:

grampo de cabelo NAT

Como posso corrigir esta situação sem recorrer a hacks de DNS ? Existe uma maneira de configurar nftableso encaminhamento de solicitação internamente enquanto se tem um IP dinâmico? Como o iifnameacima brinca com isso?

Obrigado.

nat
  • 2 2 respostas
  • 120 Views

2 respostas

  • Voted
  1. Tomek
    2023-09-30T05:18:16+08:002023-09-30T05:18:16+08:00

    O que você provavelmente precisa é de uma 'EXPRESSÃO FIB' na página de manual do nft. Esta é a regra que uso para meu DNAT (você precisará ajustar sua configuração):

        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                iiftype ppp fib daddr type local dnat ip to meta l4proto . th dport map @PRE-DNAT-IPV4
        }
    

    fib daddr type localé a parte que corresponde daddra qualquer endereço correspondente da caixa NAT.

    Observe que talvez você também precise fornecer o mapeamento SNAT apropriado para que isso funcione (já que os pacotes de retorno podem ser enviados diretamente para a interface da ponte com endereço de origem interno que não corresponderá a nenhuma conexão na VM).

    • 1
  2. Best Answer
    TCB13
    2023-10-01T07:24:23+08:002023-10-01T07:24:23+08:00

    Ok, consegui consertar isso e também simplifiquei minha configuração.

    1. A forwardcadeia não precisa aceitar explicitamente o tráfego para portas específicas, posso apenas dizer para encaminhar qualquer coisa que tenha regras dnatespecíficas posteriormente:
    table ip filter {
      chain forward {
        type filter hook forward priority 0; policy drop;
        # cbr0->anywhere (including to itself)
        iifname cbr0 accept
        # publicif->cbr0 only related connections
        iifname enp6s0 oifname cbr0 ct state related, established accept
        # publicif->cbr0 allow fwd for things that have dnat rules
        iifname enp6s0 oifname cbr0 ct status dnat accept
      }
    }
    
    1. Use uma expressão FIB conforme descrito aqui . E certifique-se de que o tráfego dnatpossa vir de ambos enp6s0e cbr0:
    table ip nat {
    
      chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        ip saddr 10.0.0.0/24 masquerade
      }
    
      chain prerouting {
        type nat hook prerouting priority -100; policy accept;
    
        # Webproxy
        iifname { enp6s0, cbr0 } tcp dport { 80, 443 } fib daddr type local dnat to 10.0.0.1
        iifname { enp6s0, cbr0 } udp dport { 80, 443 } fib daddr type local dnat to 10.0.0.1
     
      }
    
    }
    

    Agora tudo parece funcionar, porém há um pequeno detalhe: quando meu contêiner webproxy recebe solicitações da internet ( enp6s0) ele registra o IP real da máquina remota como origem dessas solicitações, porém quando elas vêm de outro contêiner o IP de origem aparece como 10.0 .0.254 que é o IP do host em cbr0.

    • 1

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Você pode passar usuário/passar para autenticação básica HTTP em parâmetros de URL?

    • 5 respostas
  • Marko Smith

    Ping uma porta específica

    • 18 respostas
  • Marko Smith

    Verifique se a porta está aberta ou fechada em um servidor Linux?

    • 7 respostas
  • Marko Smith

    Como automatizar o login SSH com senha?

    • 10 respostas
  • Marko Smith

    Como posso dizer ao Git para Windows onde encontrar minha chave RSA privada?

    • 30 respostas
  • Marko Smith

    Qual é o nome de usuário/senha de superusuário padrão para postgres após uma nova instalação?

    • 5 respostas
  • Marko Smith

    Qual porta o SFTP usa?

    • 6 respostas
  • Marko Smith

    Linha de comando para listar usuários em um grupo do Windows Active Directory?

    • 9 respostas
  • Marko Smith

    O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL?

    • 3 respostas
  • Marko Smith

    Como determinar se uma variável bash está vazia?

    • 15 respostas
  • Martin Hope
    Davie Ping uma porta específica 2009-10-09 01:57:50 +0800 CST
  • Martin Hope
    kernel O scp pode copiar diretórios recursivamente? 2011-04-29 20:24:45 +0800 CST
  • Martin Hope
    Robert ssh retorna "Proprietário incorreto ou permissões em ~/.ssh/config" 2011-03-30 10:15:48 +0800 CST
  • Martin Hope
    Eonil Como automatizar o login SSH com senha? 2011-03-02 03:07:12 +0800 CST
  • Martin Hope
    gunwin Como lidar com um servidor comprometido? 2011-01-03 13:31:27 +0800 CST
  • Martin Hope
    Tom Feiner Como posso classificar a saída du -h por tamanho 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent Como determinar se uma variável bash está vazia? 2009-05-13 09:54:48 +0800 CST

Hot tag

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve