Routing multipath pada kernel post-3.6

16

Seperti yang Anda semua mungkin tahu, cache rute ipv4 telah dihapus dalam seri kernel Linux 3.6, yang berdampak serius pada routing multipath. Kode routing IPv4 (tidak seperti IPv6 satu) memilih hop berikutnya dengan cara round-robin, jadi paket dari IP sumber yang diberikan ke IP tujuan yang diberikan tidak selalu melalui hop berikutnya yang sama. Sebelum 3.6 cache routing memperbaiki situasi itu, seperti hop berikutnya, setelah dipilih, tetap di cache, dan semua paket lebih lanjut dari sumber yang sama ke tujuan yang sama akan melalui hop berikutnya. Sekarang hop selanjutnya dipilih kembali untuk setiap paket, yang mengarah ke hal-hal aneh: dengan 2 rute default biaya yang sama dalam tabel routing, masing-masing menunjuk ke satu penyedia internet, saya bahkan tidak dapat membuat koneksi TCP, karena SYN awal dan ACK akhir pergi melalui rute yang berbeda,

Apakah ada cara yang relatif mudah untuk mengembalikan perilaku normal dari multipath routing, sehingga hop selanjutnya dipilih per-aliran daripada per-paket? Apakah ada patch di sekitar untuk membuat IPv4 hop berikutnya berbasis hash, seperti untuk IPv6? Atau bagaimana Anda semua menghadapinya?

Eugene
sumber
Apakah Anda memiliki pengaturan "akses terpisah" yang serupa dengan ini di sini: lartc.org/howto/lartc.rpdb.multiple-links.html ? Jika demikian, seperti apa aturan dan rute Anda?
the-wabbit
coba gunakan "ip route get 173.194.112.247" beberapa kali dan posting output
c4f4t0r
Terima kasih atas pertanyaannya. :) pertama-tama, Anda tidak memberi kami contoh. Jadi saya kira Anda memiliki sesuatu seperti ip ro add 8.8.8.8/32 nexthop via 1.2.3.4 nexthop via 1.2.3.5asumsi yang benar?
poige
Ya itu benar, tetapi biasanya ip route add 0.0.0.0/0 dengan beberapa hop berikutnya.
Eugene
si-wabbit, ya, persis seperti itu. "provider 1" dan "provider2" dalam kasus saya adalah router perbatasan yang terhubung ke jaringan internal dan jaringan penyedia saya dan mereka memang sumber NAT. Pada router internal saya, saya hanya memiliki gateway default dengan 2 hop menunjuk ke provider1 dan provider2, tidak ada rute lain. Aturan firewall hanya mengizinkan beberapa layanan (seperti HTTP) untuk mesin klien dan memblokir yang lainnya.
Eugene

Jawaban:

8

Jika memungkinkan, tingkatkan ke Kernel Linux> = 4.4 ....

Routing multipath berbasis hash telah diperkenalkan, yang dalam banyak hal lebih baik daripada perilaku pra 3.6. Berbasis aliran, mengambil hash IP sumber dan tujuan (port diabaikan) untuk menjaga jalur tetap untuk koneksi individu. Satu kelemahannya adalah saya percaya ada berbagai algoritma / mode konfigurasi yang tersedia sebelum 3.6, tetapi sekarang Anda mendapatkan apa yang Anda diberikan !. Anda dapat menggunakan mempengaruhi pilihan jalan weight.

Jika Anda berada dalam situasi saya maka Anda sebenarnya menginginkannya 3.6 >= behaviour < 4.4tetapi itu tidak lagi didukung.

Jika Anda memutakhirkan ke> = 4.4 maka ini akan melakukan trik, tanpa semua perintah lain:

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

Atau dengan perangkat:

ip route add default  proto static scope global \
 nexthop  dev <if_1> weight 1 \
 nexthop  dev <if_2> weight 1
bao7uo
sumber
Untuk siapa pun yang datang ke solusi ini - lihat juga di: net.ipv4.fib_multipath_use_neigh untuk secara otomatis menonaktifkan "terjatuh" nexthop / gateway.
Rostislav Kandilarov
6

"Relatif mudah" adalah istilah yang sulit, tetapi Anda mungkin bisa

  1. mengatur tabel perutean untuk setiap tautan Anda - satu tabel per tautan, dengan satu gateway standar
  2. gunakan netfilter untuk menandai tanda yang identik pada semua paket dari satu aliran
  3. gunakan tabel aturan ip untuk merutekan paket melalui tabel routing yang berbeda tergantung pada tanda
  4. gunakan rute multi-nexthop untuk menyeimbangkan paket pertama-dalam-sesi-di atas gateway / gateway Anda.

Telah ada diskusi di milis netfilter tentang topik ini di mana saya mencuri daftar dari:

1. Aturan perutean (RPDB dan 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. Aturan firewall (menggunakan ipset untuk memaksa mode "aliran" 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

Anda mungkin ingin mengikuti diskusi milis netfilter untuk beberapa variasi di atas.

the-wabbit
sumber
Tidak yakin, tapi mungkin lebih sederhana untuk u32mendapatkan parameter penting hash dan kemudian "label" yang ditugaskan untuk ip rule's
poige
Terima kasih, tapi itu sepertinya solusi yang cukup rumit. Apa yang saya tidak begitu mengerti adalah bagian apa di sini yang bertanggung jawab untuk "cap tanda identik pada semua paket aliran tunggal"? Bagaimana cara kerja ipset magic itu? Saya pikir ipset hanyalah seperangkat IP tertentu yang hash dan dapat dicocokkan dengan aturan.
Eugene
Anda benar tentang ipset- itu hanya membuat set yang diisi menggunakan --add-setdan cocok dengan menggunakan --match-set- tetapi ini sebagian besar untuk koneksi dalam keadaan BARU. Untuk koneksi status ESTABLISHED tanda dicap pada paket menggunakan --restore-markparameter CONNMARKtarget - arahan ini menyalin tanda koneksi ke paket. Tanda koneksi sebelumnya ditetapkan menggunakan --save-markdalam POSTROUTINGrantai (di mana paket-paket milik koneksi BARU akan melewati). Tulisan itu kelihatannya terlalu berbelit-belit bagi saya, tetapi itu menyampaikan gagasan itu.
the-wabbit
1
Ya, sekarang saya punya ide, saya pikir. Pertanyaan terakhir: apakah Anda mengerti mengapa pengembang kernel tidak memperkenalkan seleksi hop berikutnya berbasis hash untuk ipv4? Apakah ada alasan untuk tidak menerapkannya bersamaan dengan penghapusan cache rute? Solusi serupa untuk ipv6 bekerja dengan sangat baik. Bukankah semua sulap itu terlalu berlebihan untuk tugas sesederhana itu?
Eugene
1
@Eugene sayangnya, saya jauh dari cukup dekat dengan pengembangan tumpukan IP (atau pengembangan Kernel Linux secara umum) untuk secara otoritatif menjawab pertanyaan Anda, tetapi saya berspekulasi bahwa multipathing menggunakan penyedia berbeda dengan IPv4 dianggap terlalu banyak dari kasus sudut untuk menempatkan lebih banyak pekerjaan di dalamnya. Menggunakan netfilter CONNMARKs jelas terlihat seperti kludge yang tidak menyenangkan, tetapi bahkan mungkin telah dianggap sebagai "solusi yang dapat digunakan" dalam keputusan menjatuhkan kode cache rute.
wabbit