Eu tenho duas máquinas A e B. A é um VPS que possui endereços IPv4 e IPv6 globalmente roteáveis, B é um servidor físico atrás de um NAT de nível de operadora:
A
:- Endereços IPv4 A1 e A2 (on-link);
- Prefixo IPv6 A3::/56 (roteado).
B
possui apenas um endereço IPv4 B1 no bloco de endereços RFC 6598 100.64.0.0/10.
A e B estão em redes diferentes, em ISPs diferentes, nada em comum, exceto que A1 e A2 são acessíveis a partir de B.
Preciso configurar um túnel entre A e B, de forma que B se comporte como se A2 fosse seu endereço.
Especificamente, preciso ser capaz de:
- receber conexões para A2 na máquina B,
- iniciar novas conexões usando A2 da máquina B e
- execute DNAT em algumas das conexões de entrada e redirecione-as para outras máquinas C1..Cn que estão "atrás" de B.
Como faço isso?
A maioria dos túneis pode lidar com isso da mesma maneira, mas comece configurando um túnel WireGuard simplesmente porque é baseado em UDP e tem maior probabilidade de passar por NAT (CG) do que, por exemplo, GRE bruto. (Como alternativa, GRE-over-IPsec também funcionaria, pois o IPsec usará automaticamente o encapsulamento UDP, fornecendo GRE-ESP-UDP. Acredito que L2TP e VXLAN também podem funcionar bem, ambos baseados em UDP.)
Além disso, será necessário ter algum tipo de keepalive devido ao (CG)NAT, caso contrário, perderá o controle dos fluxos ociosos, e o "PersistentKeepalive" integrado do WireGuard será útil. Habilite o envio de pacotes keepalive de B (no [Peer] que representa A), pois é ele que precisa ser "perfurado".
Depois de montar o túnel:
Para o endereço IP, o roteamento para B é simples; você literalmente roteia esse endereço através da interface do túnel.
É mais importante fazer respostas da rota B através desse túnel também. A melhor maneira de fazer isso é usar "roteamento de política" se B for capaz disso, embora SNAT em A (como visto em situações de "NAT hairpin") possa ser usado em caso de emergência. (O Linux também implementa uma terceira opção mais fácil, rotas específicas de origem, mas apenas para IPv6; não para IPv4.)
"On-link" significa que o servidor original ainda precisa responder às consultas ARP para A2, não há outra diferença. Se A2 não estiver atribuído diretamente a uma interface em A, então A precisará responder em seu nome de qualquer maneira (proxy ARP).
ip neigh add ... proxy
. (Ou oparpd
daemon, se preferir; o que for mais fácil de configurar.)Infelizmente, o [Neighbor] do systemd-networkd não funcionará para substituir 'ip neigh add' - ainda falta o equivalente ao sinalizador 'proxy'.
Nota: Eu não sugeriria usar o proxy_arp "blanket enable" ou IPv4ProxyARP= sysctls - eles são um pouco amplos demais e você não deseja fazer proxy acidental de toda a rede de A de volta para si mesmo.
tcpdump -e -n -i eth0 'arp'
ip route list table X
se possui uma rota 0.0.0.0/0 via wg0 (correspondente a AllowedIPs). Se wg-quick não estiver sendo usado, adicione essa rota manualmente.ip rule add from A2/32 lookup X
ou [RoutingPolicyRule] do systemd-networkd.As etapas seriam muito semelhantes para qualquer tipo de túnel, por exemplo, GRE, menos o negócio "AllowedIPs" (GRE ou IPIP têm apenas um único peer, portanto permitem automaticamente qualquer endereço) e menos as rotas automáticas relacionadas (crie-as manualmente).
Um processo alternativo sem proxy-ARP também é possível, onde A2 permanece atribuído a A, mas A faz um DNAT geral para o endereço do túnel de B. Isso não permite que B "possua" A2, mas mesmo assim é muito comum, como visto, por exemplo, em grandes provedores de nuvem (GCE, EC2, Oracle) que implementam "IPs flutuantes" exatamente dessa maneira, e também visto em gateways domésticos que o chamam "DMZ". Ele ainda permite que B roteie/DNAT os pacotes ainda mais.