Multipath routing ใน 3.6 kernels


16

อย่างที่คุณคงทราบกันแล้วว่าเส้นทาง IPv4 cache นั้นถูกลบออกไปในชุดเคอร์เนล 3.6 Linux ซึ่งมีผลกระทบร้ายแรงต่อการกำหนดเส้นทางแบบหลายเส้นทาง รหัสการกำหนดเส้นทาง IPv4 (ไม่เหมือนกับ IPv6 หนึ่ง) เลือกการกระโดดแบบถัดไปในแบบปัด - โรบินดังนั้นแพ็กเก็ตจาก IP ต้นทางที่กำหนดไปยัง IP ปลายทางที่กำหนดไม่เสมอไปในการข้าม Hop ครั้งถัดไป ก่อน 3.6 3.6 การกำหนดเส้นทางแคชกำลังแก้ไขสถานการณ์ดังกล่าวเนื่องจาก hop ถัดไปเมื่อเลือกแล้วยังคงอยู่ในแคชและแพ็กเก็ตเพิ่มเติมจากแหล่งเดียวกันไปยังปลายทางเดียวกันนั้นจะผ่าน hop ในครั้งถัดไป ต่อไปนี้ hop ถูกเลือกใหม่สำหรับแต่ละแพ็คเก็ตซึ่งนำไปสู่สิ่งที่แปลก: ด้วย 2 เส้นทางเริ่มต้นที่มีค่าใช้จ่ายเท่ากันในตารางเส้นทางแต่ละชี้ไปที่ผู้ให้บริการอินเทอร์เน็ตรายหนึ่งฉันไม่สามารถสร้างการเชื่อมต่อ TCP ได้เนื่องจาก SYN เริ่มต้นและ ACK สุดท้าย ใช้เส้นทางอื่น

มีวิธีใดที่ค่อนข้างง่ายในการกู้คืนพฤติกรรมปกติของการกำหนดเส้นทางแบบหลายเส้นทางดังนั้นการเลือก hop ต่อไปจะถูกเลือกต่อโฟลว์แทนที่จะเป็นต่อแพ็คเก็ตหรือไม่ มีแพทช์รอบ ๆ เพื่อให้การแฮ็กเลือก IPv4 ครั้งต่อไปเหมือนแฮชสำหรับ IPv6 หรือไม่? หรือคุณจัดการกับมันอย่างไร?


คุณมีการตั้งค่า "แบ่งการเข้าถึง" คล้ายกับที่นี่หรือไม่: lartc.org/howto/lartc.rpdb.multiple-links.html ถ้าเป็นเช่นนั้นชุดกฎและเส้นทางของคุณมีลักษณะอย่างไร
the-wabbit

พยายามใช้ "ip route รับ 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 เพิ่ม 0.0.0.0/0 พร้อมกับกระโดดหลายครั้งต่อไป
Eugene

-wabbit ใช่เหมือนกัน "ผู้ให้บริการ 1" และ "ผู้ให้บริการ 2" ในกรณีของฉันคือเราเตอร์เส้นขอบที่เชื่อมต่อกับเครือข่ายภายในของฉันและเครือข่ายของผู้ให้บริการและพวกเขาทำแหล่ง NAT บนเราเตอร์ภายในของฉันฉันเพิ่งมีเกตเวย์เริ่มต้นที่มี 2 ฮ็อปชี้ไปที่ผู้ให้บริการ 1 และผู้ให้บริการ 2 ไม่มีเส้นทางอื่น กฎไฟร์วอลล์อนุญาตให้ใช้บริการบางอย่าง (เช่น HTTP) สำหรับเครื่องไคลเอนต์และบล็อกทุกอย่างอื่น
Eugene

คำตอบ:


8

ถ้าเป็นไปได้อัพเกรดเป็น Linux Kernel> = 4.4 ....

การกำหนดเส้นทางแบบหลายเส้นทางที่ใช้แฮชได้รับการแนะนำซึ่งมีหลายวิธีที่ดีกว่าพฤติกรรม 3.6 ก่อนหน้า มันขึ้นอยู่กับการไหลการแฮชของแหล่งที่มาและ IP ปลายทาง (พอร์ตจะถูกละเว้น) เพื่อให้เส้นทางมั่นคงสำหรับการเชื่อมต่อส่วนบุคคล ข้อเสียอย่างหนึ่งคือฉันเชื่อว่ามีอัลกอริทึม / โหมดการตั้งค่าต่างๆที่พร้อมใช้งานก่อน 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 สำหรับการปิดใช้งาน "หลุด" โดยอัตโนมัติ nexthop / เกตเวย์
Rostislav Kandilarov

6

"ค่อนข้างง่าย" เป็นคำที่ยาก แต่คุณอาจจะ

  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 เพื่อบังคับโหมด "flow" 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's
poige

ขอบคุณ แต่ดูเหมือนว่าโซลูชันที่ซับซ้อนจะสวย สิ่งที่ฉันไม่เข้าใจค่อนข้างมากชิ้นส่วนใดที่นี่มีหน้าที่รับผิดชอบในการ "ทำเครื่องหมายเหมือนกันในทุกแพ็กเกจของสตรีมเดียว" ipset นั้นทำงานอย่างไร ฉันคิดว่า ipset เป็นเพียงชุดของ IP เฉพาะที่ถูกแฮชและสามารถจับคู่กับกฎได้
Eugene

คุณมีความถูกต้องipset- มันเป็นเพียงการสร้างชุดที่เต็มไปด้วยการใช้--add-setและจับคู่กับการใช้--match-set- แต่ส่วนใหญ่สำหรับการเชื่อมต่อในรัฐใหม่ สำหรับการเชื่อมต่อสถานะ ESTABLISHED เครื่องหมายจะถูกประทับบนแพ็กเก็ตโดยใช้--restore-markพารามิเตอร์ของCONNMARKเป้าหมาย - คำสั่งนี้กำลังคัดลอกเครื่องหมายของการเชื่อมต่อไปยังแพ็กเก็ต ก่อนหน้านี้เครื่องหมายของการเชื่อมต่อถูกตั้งค่าโดยใช้--save-markในPOSTROUTINGสายโซ่ (ซึ่งแพ็กเก็ตที่เป็นของการเชื่อมต่อใหม่จะผ่าน) ดูเหมือนว่าสคริปต์จะซับซ้อนเกินไปสำหรับฉัน แต่มันถ่ายทอดความคิด
the-wabbit

1
ใช่ตอนนี้ฉันเข้าใจแล้วฉันคิดว่า คำถามสุดท้าย: คุณเข้าใจหรือไม่ว่าทำไมนักพัฒนาเคอร์เนลจึงไม่แนะนำการเลือก hop ต่อไปแบบแฮชสำหรับ ipv4 มีเหตุผลบางอย่างที่ไม่ใช้พร้อมกับลบแคชเส้นทางหรือไม่ โซลูชันที่คล้ายกันสำหรับ ipv6 ทำงานได้ค่อนข้างดี ไม่ทั้งหมดที่ connmark มายากล overkill เช่นงานง่าย ๆ ?
Eugene

1
@Eugene โชคไม่ดีที่ฉันอยู่ใกล้การพัฒนา IP stack (หรือการพัฒนาเคอร์เนล Linux โดยทั่วไป) เพื่อตอบคำถามใด ๆ ของคุณ แต่ฉันจะคาดเดาว่าการใช้หลายผู้ให้บริการที่หลากหลายด้วย IPv4 นั้นถือว่ามากเกินไป กรณีมุมที่จะนำงานเพิ่มเติมใด ๆ ลงไป เห็นได้ชัดว่าการใช้ netfilter CONNMARK ดูเหมือนว่าน่าขยะแขยง แต่อาจถูกพิจารณาว่าเป็น "วิธีแก้ปัญหาที่ใช้งานได้" ในการตัดสินใจวางรหัสแคชเส้นทาง
the-wabbit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.