3.6以降のカーネルでのマルチパスルーティング


15

おそらくご存知のように、ipv4ルートキャッシュは3.6 Linuxカーネルシリーズで削除され、マルチパスルーティングに深刻な影響を及ぼしました。IPv4ルーティングコード(IPv6のものとは異なります)はラウンドロビン方式でネクストホップを選択するため、特定の送信元IPから特定の宛先IPへのパケットは常に同じネクストホップを経由するわけではありません。3.6より前では、ルーティングキャッシュはその状況を修正し、一度選択されたネクストホップはキャッシュ内に留まり、同じ送信元から同じ宛先へのすべてのパケットはそのネクストホップを通過していました。今、次のホップが各パケットに対して再選択され、奇妙なことにつながります:ルーティングテーブルに2つの等コストのデフォルトルートがあり、それぞれが1つのインターネットプロバイダーを指しているため、TCP接続を確立することもできません。初期SYNと最終ACK異なるルートを経由して、

マルチホップルーティングの通常の動作を復元する比較的簡単な方法はありますか。そのため、ネクストホップはパケットごとではなくフローごとに選択されますか?IPv6のように、IPv4ネクストホップ選択をハッシュベースにするパッチはありますか?それとも、どうやってそれを処理しますか?


次のような「分割アクセス」の設定はありますか?lartc.org/howto/lartc.rpdb.multiple-links.html?もしそうなら、ルールセットとルートはどのように見えますか?
-wabbit

「ip route get 173.194.112.247」を複数回使用して、出力を投稿して
ください-c4f4t0r

おいしい質問をありがとう。:)まず第一に、あなたは私たちに例を与えませんでした。それで、あなたip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5はそのような正しい仮定のようなものを持っていると思いますか?
poige

はい、それは正しいですが、通常は複数のネクストホップを含むip route add 0.0.0.0/0です。
ユージン

the-wabbit、はい、まさにそのようです。私の場合、「provider 1」と「provider2」は、内部ネットワークとプロバイダーのネットワークに接続されている境界ルーターであり、ソースNATを実行します。内部ルーターには、provider1とprovider2を指す2ホップのデフォルトゲートウェイがあり、他のルートはありません。ファイアウォールルールは、クライアントマシンに対して一部のサービス(HTTPなど)を許可し、他のすべてをブロックします。
ユージン

回答:


8

可能であれば、Linuxカーネル> = 4.4 ...にアップグレードしてください。

ハッシュベースのマルチパスルーティングが導入されました。これは、多くの点で、3.6以前の動作よりも優れています。これはフローベースであり、ソースIPと宛先IPのハッシュを取得して(ポートは無視されます)、個々の接続に対してパスを安定させます。1つの欠点は、3.6より前にさまざまなアルゴリズム/構成モードが利用可能であったと信じていることですが、今では与えられたものが手に入ります!weightただし、パスの選択に影響を与えることができます。

あなたが私の状況にあるなら、あなたは実際に欲しいが3.6 >= behaviour < 4.4、それはもはやサポートされていません。

> = 4.4にアップグレードする場合は、他のすべてのコマンドを使用せずに、これでうまくいくはずです。

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

または、デバイスごと:

ip route add default  proto static scope global \
 nexthop  dev <if_1> weight 1 \
 nexthop  dev <if_2> weight 1

このソリューションを利用する場合は、「ドロップされた」ネクストホップ/ゲートウェイを自動的に無効にするためのnet.ipv4.fib_multipath_use_neighもご覧ください。
ロスチスラフカンディロロフ

6

「比較的簡単」は難しい用語ですが、

  1. リンクごとにルーティングテーブルを設定します-単一のデフォルトゲートウェイを使用して、リンクごとに1つのテーブル
  2. netfilterを使用して、単一ストリームのすべてのパケットに同一のマークをスタンプします
  3. IPルールテーブルを使用して、マークに応じて異なるルーティングテーブルを介してパケットをルーティングします
  4. マルチネクストホップの重み付けされたルートを使用して、ゲートウェイ/リンクでセッションの最初のパケットのバランスを取ります。

このトピックに関するnetfilterメーリングリストで、リストを盗んでいる議論がありました

1.ルーティングルール(RPDBおよび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.ファイアウォールルール(ipsetを使用して「フロー」LBモードを強制する)

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

上記のいくつかのバリエーションについては、netfilterメーリングリストの説明に従ってください。


わからないが、する方が簡単かもしれないu32重要なパラメータは、ハッシュされ、取得するために、その後のために割り当てられた「ラベル」ip ruleさん
poige

ありがとう、しかしそれはかなり複雑な解決策のように見える。私がよく理解していないのは、ここのどの部分が「単一ストリームのすべてのパケットに同一のマークをスタンプする」のかということです。そのipsetマジックはどのように機能しますか?ipsetは、ハッシュされ、ルールで照合できる特定のIPのセットにすぎないと考えました。
ユージン

あなたは正しいですipset-それは単に使用して満たされ、使用--add-setに対して一致するセットを作成しています--match-setが、これは主に新しい状態の接続用です。ESTABLISHED状態の接続の場合--restore-markCONNMARKターゲットのパラメーターを使用してマークがパケットにスタンプされます-このディレクティブは、接続のマークをパケットにコピーします。接続のマークは--save-markPOSTROUTINGチェーン(新しい接続に属するパケットが通過する場所)を使用して事前に設定されます。スクリプトは私には過度に複雑に思えますが、それはアイデアを伝えます。
the-wabbit

1
はい、今、私はアイデアを得たと思います。最後の質問:カーネル開発者がipv4のハッシュベースのネクストホップ選択を導入しない理由を理解していますか?ルートキャッシュの削除とともに実装しない理由はありますか?ipv6の同様のソリューションは非常にうまく機能します。そのような単純なタスクのすべてを魔法で結びつけているのではありませんか?
ユージン

1
@Eugene残念ながら、私はIPスタック開発(または一般的なLinuxカーネル開発)に十分に近づいてあなたの質問に答えることはできませんが、IPv4の異なるプロバイダーを使用したマルチパスは多すぎると考えられますそれ以上の仕事を入れるコーナーケース。netfilter CONNMARKsを使用することは明らかに厄介なことのように見えますが、ルートキャッシュコードを削除する決定において「使用可能な回避策」と見なされることさえありました。
the-wabbit
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.