![Nftables DNAT não parece estar funcionando](https://rvso.com/image/1615273/Nftables%20DNAT%20n%C3%A3o%20parece%20estar%20funcionando.png)
Estou tentando configurar um DNAT no meu novo centos 8 usando nftables. Este utilitário (e o centos 8) é novo para mim, uso iptables (centos até 6) há muito tempo.
Minha suposição é que não configurei algo corretamente para o DNAT funcionar, mas posso simplesmente não estar usando as ferramentas corretamente. Ou ambos.
De qualquer forma, caso seja importante, aqui está uma pergunta anterior minha sobre alguns problemas de roteamento na mesma caixa:Várias conexões com a Internet, pacotes recebidos na porta NIC errada (problema de roteamento de entrada?)(o problema era um fluxo ARP, resolvido).
Aqui está abaixo um esboço da minha configuração atual e a linha azul marca o que eu quero que aconteça (o "caminho" esperado)
Basicamente, os pacotes chegam da Internet, passam pela interface 2 (ens2), são DNATados através da interface local (ens5, IP local 192.168.1.10) para 192.168.1.2. (Quando estiver funcionando, o mesmo será configurado para os itens 3 e 4, indo para algumas VMs diferentes na mesma LAN)
Verifiquei que os pacotes chegam na interface correta (os gatilhos de log NFT esperados), porém, conntrack -E
não mostram nada.
Além disso, o log do iptables na caixa centos 6 (o alvo real, 192.168.1.2) não mostra nada (o mesmo log implementado há muito tempo estava mostrando a saída esperada na última vez que verifiquei, há alguns meses, então essa caixa deveria, em teoria, estar ok)
Aqui está meu script nftables como está agora, com IPs/IFs traduzidos para corresponder ao esboço.
table ip nat {
chain PREROUTING {
type nat hook prerouting priority -100; policy accept;
iif "ens2" goto PREROUTING_RDS2
iif "ens3" goto PREROUTING_RDS3
}
chain PREROUTING_RDS2 {
tcp dport { http, https } log prefix "RDS2_dnat-3 "
tcp dport { http, https } dnat to IP_6
}
chain PREROUTING_RDS3 {
tcp dport { http, https } log prefix "RDS3_dnat-3 "
tcp dport { http, https } dnat to IP_6
}
}
table inet filter {
chain INPUT {
type filter hook input priority 0; policy drop;
#
iif "lo" accept
#
# allow ping
ip protocol icmp icmp type echo-request limit rate 1/second log prefix "PING "
ip protocol icmp icmp type echo-request limit rate 1/second accept
# following is required and must be BEFORE the ct state established otherwise the ping flooding will not be stopped
ip protocol icmp drop
#
ct state established,related accept
ct status dnat accept
#
iifname "ens5" goto INPUT_LOCAL
#
# now we drop the rest
ct state invalid log prefix "INPUT_STATE_INVALID_DROP: "
ct state invalid drop
log prefix "INPUT_FINAL_REJECT: "
reject with icmpx type admin-prohibited
}
chain FILTER {
type filter hook forward priority 50; policy drop;
iif "ens2" goto FILTER_RDS2
iif "ens3" goto FILTER_RDS3
}
chain INPUT_LOCAL {
tcp dport ssh goto INPUT_LOCAL_ssh
}
chain INPUT_LOCAL_ssh {
ip saddr IP_MY_PC accept
}
chain FILTER_RDS2 {
oifname "ens5" ip daddr IP_6 tcp dport { http, https } accept
}
chain FILTER_RDS3 {
oifname "ens5" ip daddr IP_6 tcp dport { http, https } accept
}
}
Agradeço antecipadamente.
Responder1
Na verdade, esta questão é difícil de responder sem olharmos bem para operguntas/respostas anterioresresolvendo a configuração inicial paracentos8. A solução torna-se muito complexa. Considerando o tipo de configuração que deve ser feita para isso, provavelmente não vale a pena ter um IP por interface, com múltiplas interfaces na mesma LAN, ao invés de todos os IPs na mesma interface, principalmente considerando que está em um ambiente virtual: existe não haverá nenhuma aceleração. Qualquer alteração na configuração deverá ser refletida ao longo dos comandos abaixo, portanto será difícil gerenciar isso corretamente.
centos8roteador
Como para resolver o problema de múltiplas interfaces na mesma LAN existem tabelas de roteamento adicionais, agora que neste Q/Acentos8estiver agindo como um roteador, mais entradas de rota deverão ser duplicadas da tabela principal para as tabelas de roteamento adicionais:
# ip route add 192.168.1.0/24 dev ens5 table 1001 src 192.168.1.10
# ip route add 192.168.1.0/24 dev ens5 table 1002 src 192.168.1.10
# ip route add 192.168.1.0/24 dev ens5 table 1003 src 192.168.1.10
# ip route add 192.168.1.0/24 dev ens5 table 1004 src 192.168.1.10
caso contrário, qualquer pacote recebido emens1,ens2,ens3ouens4enãoatravésens5vai falharfiltro de caminho reversojá que não há rota atravésens5nessas mesas.
Claro que isso não é suficiente: não há informação nos pacotes de resposta (por exemplo: voltando decentos6) sobre qual interface foi usada e deve ser reutilizada ao contrário. Então essa informação tem que ser memorizada por fluxo, usando o conntrack do netfilter. Nas regras do nftables, exclua a ip nat
tabela inteira:
# nft delete table ip nat
e substitua-o por esta nova tabela ip markandnat
:
# nft -f - << 'EOF'
table ip markandnat {
map iif2mark {
type iface_index : mark;
elements = {
ens1 : 101,
ens2 : 102,
ens3 : 103,
ens4 : 104
}
}
map mark2daddr {
type mark : ipv4_addr;
elements = {
102 : 192.168.1.2,
103 : 192.168.1.2, # same IP, as per OP's config
104 : 192.168.1.4 # some other VM
}
}
chain premark {
type filter hook prerouting priority -150; policy accept;
meta mark set ct mark meta mark != 0 return
meta mark set iif map @iif2mark meta mark != 0 ct mark set meta mark
}
chain prenat {
type nat hook prerouting priority -100; policy accept;
tcp dport { http, https } dnat to meta mark map @mark2daddr
}
}
EOF
Isto irá mapear interface => mark => dnat destination, enquanto salva a marca como marca do conntrack (veja o link no final sobremarca de conexãouso). Agora esta marca estará disponível e utilizada pela pilha de roteamento adicionando as regras abaixo, para apontar para as mesmas tabelas de roteamento adicionais:
# ip rule add pref 11001 fwmark 101 table 1001
# ip rule add pref 11002 fwmark 102 table 1002
# ip rule add pref 11003 fwmark 103 table 1003
# ip rule add pref 11004 fwmark 104 table 1004
mas ainda falta uma parte: novamente sobre o filtro de caminho reverso. Quando as marcas estão em uso, o filtro de caminho reverso não verifica novamente usando as novas rotas alteradas pelas marcas e geralmente falha na verificação. Na verdade há umrecurso não documentado, adicionado no kernel 2.6.33/2.6.32.8 em 2009/2010, o que resolve esse problema, sem a necessidade de usar o modo de caminho reverso solto: src_valid_mark
.
# sysctl -w net.ipv4.conf.ens1.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens2.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens3.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens4.src_valid_mark=1
centos6servidor
Se você quiser usar um gateway alternativo temporariamente, mesmo que isso adicione novamente complexidade e provavelmente efeitos colaterais sutis imprevistos, é possível, novamente usando marcas. Como é o CentOS 6,nftáveisnão está disponível, entãotabelas de ipserá usado.
Vou considerar que ocentos6VM tem IP 192.168.1.2/24 na interface (exclusiva)eth0e padrão gw 192.168.1.1. Vamos adicionar uma nova tabela de roteamento e regra para o gateway alternativo 192.168.1.10:
# ip route add table 10 default via 192.168.1.10
# ip rule add fwmark 10 lookup 10
Coloque otabelas de ipregras (aqui apenas omangletabela é necessária):
# iptables-restore << 'EOF'
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -j CONNMARK --restore-mark
-A PREROUTING -m mark ! --mark 0 -j RETURN
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j MARK --set-mark 10
-A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j MARK --set-mark 10
-A PREROUTING -m mark ! --mark 0 -j CONNMARK --save-mark
-A OUTPUT -m connmark ! --mark 0 -j CONNMARK --restore-mark
COMMIT
EOF
Agora qualquer fluxo recebido nas portas 80 ou 443 marcará os pacotes recebidos e suas respostas. Esta marca será usada pela pilha de roteamento para alterar o gateway para 192.168.1.10 para entrada e respostas (mangle/SAÍDAaciona uma verificação de redirecionamento, veja o segundo link abaixo).
Parece que não há necessidade de usar src_valid_mark
neste caso, apenas configure ou configure rp_filter=2
se não funcionar. Esta configuração não permitirá receber tambémnãotráfego direcionado através de 192.168.1.1.
Alguns links:
Responder2
A julgar pelos comentários, a omissão mais imediata e importante é desativar o encaminhamento de IP. Apenas:
echo 1 > /proc/sys/net/ipv4/ip_forward
e verifique se agora os pacotes DNATted chegam ao IP6.
A segunda questão é o roteamento assimétrico. Os pacotes DNATted chegam ao IP6 através de 192.168.1.10 (IP5) onde são modificados (o endereço de destino é alterado). Os pacotes de retorno passarão pelo gateway padrão da LAN (182.168.1.1) e não serão modificados no caminho até a origem da conexão. Eles provavelmente manterão seu endereço RFC1918 ou receberão SNAT para algo diferente em 192.168.1.1 e nunca corresponderão a nenhuma conexão em seu destino e provavelmente serão descartados.
EDITAR:
Então, para abordar a cadeia FORWARD, eu a reescreveria da seguinte forma (IMHO muito mais simples):
table inet filter {
:
chain FORWARD {
type filter hook forward priority 0; policy drop;
ct state established,related accept
ct status dnat accept
}
:
}