Roteamento Multipath em kernels pós-3.6

15

Como todos vocês provavelmente sabem, o cache de rotas do ipv4 foi removido da série de kernel do Linux 3.6, que teve sérios impactos no roteamento de caminhos múltiplos. O código de roteamento IPv4 (ao contrário do IPv6 1) seleciona o próximo salto em uma forma round-robin, de modo que os pacotes do IP de origem fornecido para o IP de destino fornecido nem sempre passam pelo mesmo próximo salto. Antes do 3.6, o cache de roteamento estava corrigindo essa situação, já que o próximo salto, uma vez selecionado, permanecia no cache, e todos os outros pacotes da mesma fonte para o mesmo destino passavam pelo próximo salto. Agora next hop é 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, não consigo nem estabelecer conexão TCP, porque SYN inicial e ACK final percorrer rotas diferentes, e por causa do NAT em cada caminho eles chegam ao destino como pacotes de diferentes fontes.

Existe alguma maneira relativamente fácil de restaurar o comportamento normal do roteamento de vários caminhos, de modo que o próximo salto seja selecionado por fluxo, em vez de por pacote? Existem patches para tornar a seleção de próximo salto do IPv4 baseada em hash, como no IPv6? Ou como todos vocês lidam com isso?

    
por Eugene 04.06.2015 / 17:59

2 respostas

7

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 pré 3.6. Ele é baseado em fluxo, recebendo 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 eu acredito que existiam vários algoritmos / config modos disponíveis pré 3.6, mas agora você recebe o que lhe é dado !. Você pode usar a escolha do caminho por weight .

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

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
    
por 12.12.2016 / 22:56
6

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

  1. configurar tabelas de roteamento para cada um de seus links - uma tabela por link, com um único gateway padrão
  2. use o netfilter para marcar marcas idênticas em todos os pacotes de um único fluxo
  3. use a tabela de regras ip para rotear os pacotes por meio de tabelas de roteamento diferentes, dependendo da marca
  4. use uma rota ponderada de multi-nexthop para equilibrar os pacotes da primeira sessão em seus gateways / links.

Houve uma discussão na lista de discussão do netfilter sobre esse tópico em que estou roubar 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 querer seguir a discussão da lista de discussão do netfilter para algumas variações dos itens acima.

    
por 08.06.2015 / 15:12

Tags