Carregar o tráfego de rede de balanceamento usando iptables

5

Estou tentando carregar o tráfego de balanceamento da LAN interna em um roteador Linux com dois gateways. Inicialmente eu fui para a implementação do iproute que não equilibrava a carga como esperado, porque as rotas são armazenadas em cache.

Agora estou usando o iptables para marcar cada nova conexão usando o CONNMARK e, em seguida, adicionando regras para rotear essas conexões marcadas por diferentes gateways.

Eth0 - LAN,  Eth1 - ISP1,  Eth2 - ISP2

A seguir está o script que estou usando,

#!/bin/bash

echo 1 >| /proc/sys/net/ipv4/ip_forward
echo 0 >| /proc/sys/net/ipv4/conf/all/rp_filter

#   flush all iptables entries
iptables -t filter -F
iptables -t filter -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t filter -P INPUT ACCEPT
iptables -t filter -P OUTPUT ACCEPT
iptables -t filter -P FORWARD ACCEPT

# initialise chains that will do the work and log the packets
iptables -t mangle -N CONNMARK1
iptables -t mangle -A CONNMARK1 -j MARK --set-mark 1
iptables -t mangle -A CONNMARK1 -j CONNMARK --save-mark
iptables -t mangle -A CONNMARK1 -j LOG --log-prefix 'iptables-mark1: ' --log-level info

iptables -t mangle -N CONNMARK2
iptables -t mangle -A CONNMARK2 -j MARK --set-mark 2
iptables -t mangle -A CONNMARK2 -j CONNMARK --save-mark
iptables -t mangle -A CONNMARK2 -j LOG --log-prefix 'iptables-mark2: ' --log-level info

iptables -t mangle -N RESTOREMARK
iptables -t mangle -A RESTOREMARK -j CONNMARK --restore-mark
iptables -t mangle -A RESTOREMARK -j LOG --log-prefix 'restore-mark: ' --log-level info

iptables -t nat -N SNAT1
iptables -t nat -A SNAT1 -j LOG --log-prefix 'snat-to-192.168.254.74: ' --log-level info
iptables -t nat -A SNAT1 -j SNAT --to-source 192.168.254.74

iptables -t nat -N SNAT2
iptables -t nat -A SNAT2 -j LOG --log-prefix 'snat-to-192.168.253.132: ' --log-level info
iptables -t nat -A SNAT2 -j SNAT --to-source 192.168.253.132

# restore the fwmark on packets that belong to an existing connection
iptables -t mangle -A PREROUTING -i eth0 \
     -m state --state ESTABLISHED,RELATED -j RESTOREMARK


# if the mark is zero it means the packet does not belong to an existing connection
iptables -t mangle -A PREROUTING -m state --state NEW \
     -m statistic --mode nth --every 2 --packet 0 -j CONNMARK1
iptables -t mangle -A PREROUTING -m state --state NEW \
     -m statistic --mode nth --every 2 --packet 1 -j CONNMARK2


iptables -t nat -A POSTROUTING -o eth1 -j SNAT1
iptables -t nat -A POSTROUTING -o eth2 -j SNAT2

if ! cat /etc/iproute2/rt_tables | grep -q '^51'
then
    echo '51     rt_link1' >> /etc/iproute2/rt_tables
fi

if ! cat /etc/iproute2/rt_tables | grep -q '^52'
then
    echo '52     rt_link2' >> /etc/iproute2/rt_tables
fi

ip route flush table rt_link1 2>/dev/null
ip route add 192.168.254.0/24 dev eth1 src 192.168.254.74 table rt_link1
ip route add default via 192.168.254.5 table rt_link1
ip route flush table rt_link2 2>/dev/null
ip route add 192.168.253.0/24 dev eth2 src 192.168.253.132 table rt_link2
ip route add default via 192.168.253.5 table rt_link2

ip rule del from all fwmark 0x1 lookup rt_link1 2>/dev/null
ip rule del from all fwmark 0x2 lookup rt_link2 2>/dev/null
ip rule del from all fwmark 0x2 2>/dev/null
ip rule del from all fwmark 0x1 2>/dev/null

ip rule add fwmark 1 table rt_link1
ip rule add fwmark 2 table rt_link2


ip route flush cache

O uso dessas conexões é roteado nas duas rotas. No entanto, alguns deles são descartados, ou seja, as conexões não passam. Em alguns casos, uma conexão estabelecida é interrompida no meio do caminho.

Estou sentindo falta de algo?

    
por Bhavya 02.12.2014 / 10:48

1 resposta

1

Aqui está outra abordagem. Em vez de marcar as conexões com base na contagem de pacotes e esperar que elas não sejam reinicializadas, duplicadas ou alteradas de alguma outra forma, basta dividir os pacotes pelo IP de origem ou de destino. Para qualquer conjunto suficientemente grande de conexões, você deve ter um spread de 50 a 50.

Estou postando o seguinte como substituto imediato, mas você provavelmente pode acabar com a lógica CONNMARK completamente com um pouco mais de ajustes.

iptables -t mangle -A PREROUTING -m state --state NEW \
    -d 0.0.0.0/0.0.0.1 -j CONNMARK1
iptables -t mangle -A PREROUTING -m state --state NEW \
    -d 0.0.0.1/0.0.0.1 -j CONNMARK2

Você também pode alterar o destino para a origem se houver mais variação nos IPs de origem ou até combiná-los em um colchete. (ímpar / ímpar ou par / par são CONNMARK1, ímpar / par ou par / ímpar são CONNMARK2).

    
por 17.12.2014 / 18:15