web-dev-qa-db-ja.com

iptablesを使用したネットワークトラフィックの負荷分散

2つのゲートウェイを持つLinuxルーターの内部LANからのトラフィックの負荷を分散しようとしています。最初は、ルートがキャッシュされているため、期待どおりに負荷分散されないiproute実装を選択しました。

現在、iptablesを使用して、CONNMARKを使用してすべての新しい接続にマークを付けてから、これらのマークされた接続を異なるゲートウェイにルーティングするルールを追加しています。

Eth0-LAN、Eth1-ISP1、Eth2-ISP2

以下は私が使用しているスクリプトです、

#!/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

この接続を使用すると、両方のルートにルーティングされます。ただし、それらの一部はドロップされます。つまり、接続は通過しません。場合によっては、確立された接続が途中で中断されます。

何か不足していますか?

5
Bhavya

別のアプローチがあります。パケット数に基づいて接続をマークし、再初期化、複製、またはその他の方法で変更されないことを期待する代わりに、送信元または宛先IPでパケットを分割します。十分に大きい接続のセットの場合、約50から50のスプレッドが必要です。

ドロップインの代替として以下を投稿しますが、もう少しいじくり回すことで、おそらくCONNMARKロジックを完全に廃止することができます。

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

ソースIPにさらにばらつきがある場合は、宛先をソースに変更することも、それらをブラケットに結合することもできます。 (奇数/奇数または偶数/偶数はCONNMARK1、奇数/偶数または偶数/奇数はCONNMARK2です)。

1
Hyppy