Roteamento de caminhos múltiplos em kernels pós-3.6

16

Como todos vocês provavelmente sabem, o cache de rota do ipv4 foi removido na série de kernel 3.6 do Linux, que teve um sério impacto no roteamento de caminhos múltiplos. O código de roteamento IPv4 (diferente do IPv6) seleciona o próximo salto de maneira round-robin; portanto, os pacotes do IP de origem especificado ao IP de destino nem sempre passam pelo mesmo salto seguinte. Antes da versão 3.6, o cache de roteamento estava corrigindo essa situação, pois o próximo salto, uma vez selecionado, permanecia no cache, e todos os pacotes adicionais da mesma fonte para o mesmo destino estavam passando pelo próximo salto. Agora, o próximo salto é re-selecionado para cada pacote, o que leva a coisas estranhas: com 2 rotas padrão de custo igual na tabela de roteamento, cada uma apontando para um provedor de internet, nem consigo estabelecer conexão TCP, porque o SYN inicial e o ACK final percorrer diferentes rotas,

Existe alguma maneira relativamente fácil de restaurar o comportamento normal do roteamento de caminhos múltiplos, para que o próximo salto seja selecionado por fluxo e não por pacote? Existem patches para fazer a seleção do próximo salto do IPv4 baseada em hash, como é para o IPv6? Ou como vocês lidam com isso?

Eugene
fonte
Você tem uma configuração de "acesso dividido" semelhante a esta aqui: lartc.org/howto/lartc.rpdb.multiple-links.html ? Em caso afirmativo, como é o seu conjunto de regras e rotas?
the-wabbit
tente usar "ip route get 173.194.112.247" várias vezes e postar a saída
c4f4t0r
Obrigado pela pergunta saborosa. :) Antes de tudo, você não nos deu um exemplo. Então, suponho que você tenha algo assim ip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5: essa suposição correta?
poige
Sim, isso está correto, mas geralmente é rota ip, adicione 0.0.0.0/0 com vários próximos saltos.
187 Eugene
o wabbit, sim, exatamente assim. "provedor 1" e "provedor2" no meu caso são roteadores de borda conectados à minha rede interna e à rede do provedor e eles originam o NAT. No meu roteador interno, tenho apenas o gateway padrão com 2 saltos apontando para o provedor1 e o provedor2, sem outras rotas. As regras de firewall apenas permitem alguns serviços (como HTTP) para máquinas clientes e bloqueiam todo o resto.
Eugene

Respostas:

8

Se possível, atualize para o Linux Kernel> = 4.4 ....

O roteamento de caminhos múltiplos baseado em hash foi introduzido, o que de muitas maneiras é melhor que o comportamento anterior à 3.6. É baseado no fluxo, utilizando um hash dos IPs de origem e destino (as portas são ignoradas) para manter o caminho estável para conexões individuais. Uma desvantagem é que acredito que havia vários modos de algoritmo / configuração disponíveis antes da versão 3.6, mas agora você recebe o que recebe! Você pode usar afetar a escolha do caminho weight.

Se você estiver na minha situação , realmente deseja o, 3.6 >= behaviour < 4.4mas ele não é mais suportado.

Se você atualizar para> = 4.4, isso deve funcionar, sem todos os outros comandos:

ip route add default  proto static scope global \
nexthop  via <gw_1> weight 1 \
nexthop  via <gw_2> weight 1

Como alternativa por dispositivo:

ip route add default  proto static scope global \
 nexthop  dev <if_1> weight 1 \
 nexthop  dev <if_2> weight 1
bao7uo
fonte
Para quem vem a esta solução - consulte também: net.ipv4.fib_multipath_use_neigh para desativar automaticamente o nexthop / gateway "descartado".
Rostislav Kandilarov 8/11
6

"Relativamente fácil" é um termo difícil, mas você pode

  1. configure tabelas de roteamento para cada um de seus links - uma tabela por link, com um único gateway padrão
  2. use netfilter para carimbar marcas idênticas em todos os pacotes de um único fluxo
  3. use a tabela de regras ip para rotear os pacotes através de diferentes tabelas de roteamento, dependendo da marca
  4. use uma rota ponderada com várias conexões para equilibrar os pacotes da primeira sessão em seus gateways / links.

Houve uma discussão na lista de discussão netfilter sobre este tópico, onde estou roubando as listagens de:

1. Regras de roteamento (RPDB e FIB)

ip route add default via <gw_1> lable link1
ip route add <net_gw1> dev <dev_gw1> table link1
ip route add default via <gw_2> table link2
ip route add <net_gw2> dev <dev_gw2> table link2

/sbin/ip route add default  proto static scope global table lb \
 nexthop  via <gw_1> weight 1 \
 nexthop  via <gw_2> weight 1

ip rule add prio 10 table main
ip rule add prio 20 from <net_gw1> table link1
ip rule add prio 21 from <net_gw2> table link2
ip rule add prio 50 fwmark 0x301 table link1
ip rule add prio 51 fwmark 0x302 table link2
ip rule add prio 100 table lb

ip route del default

2. Regras de firewall (usando o ipset para forçar um modo LB "de fluxo")

ipset create lb_link1 hash:ip,port,ip timeout 1200
ipset create lb_link2 hash:ip,port,ip timeout 1200

# Set firewall marks and ipset hash
iptables -t mangle -N SETMARK
iptables -t mangle -A SETMARK -o <if_gw1> -j MARK --set-mark 0x301
iptables -t mangle -A SETMARK -m mark --mark 0x301 -m set !
--match-set lb_link1 src,dstport,dst -j SET \
          --add-set lb_link1 src,dstport,dst
iptables -t mangle -A SETMARK -o <if_gw2> -j MARK --set-mark 0x302
iptables -t mangle -A SETMARK -m mark --mark 0x302 -m set !
--match-set lb_link2 src,dstport,dst -j SET \
          --add-set lb_link2 src,dstport,dst

# Reload marks by ipset hash
iptables -t mangle -N GETMARK
iptables -t mangle -A GETMARK -m mark --mark 0x0 -m set --match-set
lb_link1 src,dstport,dst -j MARK --set-mark 0x301
iptables -t mangle -A GETMARK -m mark --mark 0x0 -m set --match-set
lb_link2 src,dstport,dst -j MARK --set-mark 0x302

# Defining and save firewall marks
iptables -t mangle -N CNTRACK
iptables -t mangle -A CNTRACK -o <if_gw1> -m mark --mark 0x0 -j SETMARK
iptables -t mangle -A CNTRACK -o <if_gw2> -m mark --mark 0x0 -j SETMARK
iptables -t mangle -A CNTRACK -m mark ! --mark 0x0 -j CONNMARK --save-mark
iptables -t mangle -A POSTROUTING -j CNTRACK

# Reload all firewall marks
# Use OUTPUT chain for local access (Squid proxy, for example)
iptables -t mangle -A OUTPUT -m mark --mark 0x0 -j CONNMARK --restore-mark
iptables -t mangle -A OUTPUT -m mark --mark 0x0 -j GETMARK
iptables -t mangle -A PREROUTING -m mark --mark 0x0 -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark --mark 0x0 -j GETMARK

Você pode seguir a discussão da lista de discussão netfilter para algumas variações dos itens acima.

o wabbit
fonte
Não tenho certeza, mas pode ser mais simples de u32obter parâmetros importantes hash e, em seguida, "rótulo" atribuído para ip rule's
poige
Obrigado, mas isso parece uma solução bastante complexa. O que não entendo direito é qual peça aqui é responsável por "marcar marcas idênticas em todos os pacotes de um único fluxo"? Como é que essa mágica ipset funciona? Eu pensei que ipset é apenas um conjunto de IPs específicos que são hash e podem ser correspondidos em regras.
187 Eugene
Você está certo ipset- apenas cria conjuntos que são preenchidos usando --add-sete comparados com o uso --match-set- mas isso é principalmente para as conexões no estado NOVO. Para conexões de estado ESTABELECIDO, a marca é carimbada nos pacotes usando o --restore-markparâmetro do CONNMARKalvo - esta diretiva está copiando a marca da conexão no pacote. A marca da conexão é definida anteriormente usando-se --save-markna POSTROUTINGcadeia (por onde os pacotes pertencentes a NOVAS conexões passariam). O roteiro parece excessivamente complicado para mim, mas transmite a ideia.
the-wabbit
1
Sim, agora entendi a ideia, acho. A última pergunta: você entende por que os desenvolvedores do kernel não introduzem a seleção do próximo salto baseada em hash para o ipv4? Existe algum motivo para não implementá-lo junto com a remoção do cache de rota? Solução semelhante para ipv6 funciona muito bem. Não é toda essa magia da marca um exagero para uma tarefa tão simples?
Eugene
1
@Eugene, infelizmente, estou longe de estar perto o suficiente do desenvolvimento da pilha de IP (ou desenvolvimento do Linux Kernel em geral) para responder autoritariamente a qualquer uma de suas perguntas, mas especularia que o multipathing usando diferentes provedores com IPv4 era considerado muito uma caixa de canto para colocar mais trabalho nela. O uso de CONNMARKs do netfilter obviamente parece um kludge desagradável, mas pode até ter sido considerado uma "solução alternativa utilizável" na decisão de descartar o código de cache da rota.
the-wabbit 12/06