เคอร์เนล Linux ไม่ผ่านแพ็คเก็ต UDP แบบหลายผู้รับ


35

เมื่อเร็ว ๆ นี้ฉันได้ติดตั้ง Ubuntu Server 10.04 ใหม่และพบว่าเซิร์ฟเวอร์ UDP ของฉันไม่สามารถดูข้อมูลแบบหลายผู้รับที่ส่งไปยังอินเทอร์เฟซได้อีกต่อไปแม้หลังจากเข้าร่วมกลุ่มแบบหลายผู้รับแล้ว ฉันได้รับการตั้งค่าเดียวกันบน Ubuntu 8.04.4 LTS สองเครื่องและไม่มีปัญหาในการรับข้อมูลหลังจากเข้าร่วมกลุ่มมัลติคาสต์เดียวกัน

การ์ดอีเธอร์เน็ตคือ Broadcom netXtreme II BCM5709 และไดรเวอร์ที่ใช้คือ:

b $ ethtool -i eth1
driver: bnx2
version: 2.0.2
firmware-version: 5.0.11 NCSI 2.0.5
bus-info: 0000:01:00.1

ฉันใช้ smcroute เพื่อจัดการการลงทะเบียนแบบหลายผู้รับของฉัน

b$ smcroute -d
b$ smcroute -j eth1 233.37.54.71

หลังจากเข้าร่วมกลุ่ม maddr ip แสดงการลงทะเบียนที่เพิ่มเข้ามาใหม่

b$ ip maddr

    1:  lo
        inet  224.0.0.1
        inet6 ff02::1
    2:  eth0
        link  33:33:ff:40:c6:ad
        link  01:00:5e:00:00:01
        link  33:33:00:00:00:01
        inet  224.0.0.1
        inet6 ff02::1:ff40:c6ad
        inet6 ff02::1
    3:  eth1
        link  01:00:5e:25:36:47
        link  01:00:5e:25:36:3e
        link  01:00:5e:25:36:3d
        link  33:33:ff:40:c6:af
        link  01:00:5e:00:00:01
        link  33:33:00:00:00:01
        inet  233.37.54.71 <------- McastGroup.
        inet  224.0.0.1
        inet6 ff02::1:ff40:c6af
        inet6 ff02::1

ดีมากฉันเห็นว่าฉันได้รับข้อมูลสำหรับกลุ่มหลายผู้รับนี้

b$ sudo tcpdump -i eth1 -s 65534 host 233.37.54.71
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65534 bytes
09:30:09.924337 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
09:30:09.947547 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
09:30:10.108378 IP 192.164.1.120.58866 > 233.37.54.71.15574: UDP, length 268
09:30:10.196841 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
...

ฉันยังสามารถยืนยันได้ว่าอินเทอร์เฟซที่ได้รับแพ็คเก็ต mcast

b $ ethtool -S eth1 | grep mcast_pack
rx_mcast_packets: 103998
tx_mcast_packets: 33

ตอนนี้นี่คือปัญหา เมื่อฉันพยายามจับภาพทราฟฟิกโดยใช้เซิร์ฟเวอร์ UDP ที่เป็นรูบี้แบบง่ายฉันจะได้รับข้อมูลเป็นศูนย์! นี่คือเซิร์ฟเวอร์ธรรมดาที่อ่านข้อมูลที่ส่งบนพอร์ต 15572 และพิมพ์อักขระสองตัวแรก สิ่งนี้ใช้ได้กับเซิร์ฟเวอร์ Ubuntu สองตัว 8.04.4 แต่ไม่ใช่เซิร์ฟเวอร์ 10.04

require 'socket'
s = UDPSocket.new
s.bind("", 15572)
5.times do
  text, sender = s.recvfrom(2)
  puts text
end

ถ้าฉันส่งแพ็กเก็ต UDP ที่สร้างขึ้นในทับทิมไปยังโลคอลโฮสต์เซิร์ฟเวอร์จะรับและพิมพ์อักขระสองตัวแรก ดังนั้นฉันรู้ว่าเซิร์ฟเวอร์ด้านบนทำงานได้อย่างถูกต้อง

irb(main):001:0> require 'socket'
=> true
irb(main):002:0> s = UDPSocket.new
=> #<UDPSocket:0x7f3ccd6615f0>
irb(main):003:0> s.send("I2 XXX", 0, 'localhost', 15572)

เมื่อฉันตรวจสอบสถิติโปรโตคอลฉันเห็นว่า InMcastPkts ไม่เพิ่มขึ้น ขณะที่อยู่บนเซิร์ฟเวอร์อื่น ๆ 8.04 บนเครือข่ายเดียวกันได้รับหลายพันแพ็กเก็ตใน 10 วินาที

b $ netstat -sgu ; sleep 10 ; netstat -sgu
IcmpMsg:
    InType3: 11
    OutType3: 11
Udp:
    446 packets received
    4 packets to unknown port received.
    0 packet receive errors
    461 packets sent
UdpLite:
IpExt:
    InMcastPkts: 4654 <--------- Same as below
    OutMcastPkts: 3426
    InBcastPkts: 9854
    InOctets: -1691733021
    OutOctets: 51187936
    InMcastOctets: 145207
    OutMcastOctets: 109680
    InBcastOctets: 1246341
IcmpMsg:
    InType3: 11
    OutType3: 11
Udp:
    446 packets received
    4 packets to unknown port received.
    0 packet receive errors
    461 packets sent
UdpLite:
IpExt:
    InMcastPkts: 4656  <-------------- Same as above
    OutMcastPkts: 3427
    InBcastPkts: 9854
    InOctets: -1690886265
    OutOctets: 51188788
    InMcastOctets: 145267
    OutMcastOctets: 109712
    InBcastOctets: 1246341

ถ้าฉันพยายามบังคับให้อินเตอร์เฟสเข้าสู่โหมด promisc ไม่มีอะไรเปลี่ยนแปลง

ณ จุดนี้ฉันติดอยู่ ฉันยืนยันว่าการกำหนดค่าเคอร์เนลเปิดใช้งานมัลติคาสต์แล้ว อาจมีตัวเลือกการกำหนดค่าอื่น ๆ ที่ฉันควรตรวจสอบหรือไม่

b $ grep CONFIG_IP_MULTICAST /boot/config-2.6.32-23-server
CONFIG_IP_MULTICAST=y

ความคิดใดที่จะไปจากที่นี่?


ไปคิด ฉันไปที่ป้อนคำถามใหม่อัลกอริธึมที่เกี่ยวข้องแสดงคำถามนี้ให้ฉันอย่างมีความสุข แต่ก็ไม่มีคำตอบที่มีความหมาย Boo :(.
VxJasonxV

ฉันไม่แน่ใจว่าฉันจะได้รับรางวัลอย่างแน่นอน เพื่อนร่วมงานพบปัญหาและฉันพบว่าทำไมมันเกิดขึ้นเมื่อมันเกิดขึ้น ฉันยินดีที่จะให้คำแนะนำเกี่ยวกับวิธีการรับรางวัล
VxJasonxV

คุณยังอยู่แถวนั้นเหรอ? ฉันมีคำถามสำหรับคุณ
VxJasonxV

ฉันมีปัญหานี้เช่นกัน เรียน buecking คุณแก้ปัญหาได้หรือไม่

สำหรับผู้อื่นที่มีปัญหานี้ - อ่านคำตอบทั้งหมดสำหรับคำถามนี้เนื่องจากมีการตั้งค่า 2-3 O / S ที่จำเป็นต้องแก้ไข เราได้รับการแก้ไขปัญหานี้โดยการเปลี่ยนrp_filterและ/proc/sys/net/ipv4/icmp_echo_ignore_broadcastsแล้วก็เริ่มทำงาน
Sam Goldberg

คำตอบ:


35

ในตัวอย่างของเราปัญหาของเราได้รับการแก้ไขโดยพารามิเตอร์ sysctl ซึ่งแตกต่างจาก Maciej

โปรดทราบว่าฉันไม่ได้พูดสำหรับ OP (buecking) ฉันมาที่โพสต์นี้เนื่องจากปัญหาเกี่ยวกับรายละเอียดพื้นฐาน (ไม่มีการรับส่งข้อมูลแบบหลายผู้รับในผู้ใช้)

เรามีแอปพลิเคชั่นที่อ่านข้อมูลที่ส่งไปยังที่อยู่แบบมัลติคาสต์สี่แห่งและพอร์ตที่ไม่ซ้ำกันต่อที่อยู่แบบหลายผู้รับจากอุปกรณ์ที่เชื่อมต่อโดยตรงกับอินเทอร์เฟซบนเซิร์ฟเวอร์ที่รับ (ปกติ)

เราพยายามปรับใช้ซอฟต์แวร์นี้ในเว็บไซต์ของลูกค้าเมื่อล้มเหลวอย่างลึกลับโดยไม่มีเหตุผลที่ทราบ ความพยายามในการดีบักซอฟต์แวร์นี้ส่งผลให้ตรวจสอบทุกการโทรของระบบในที่สุดพวกเขาทั้งหมดก็บอกเราในสิ่งเดียวกัน:

ซอฟต์แวร์ของเราขอข้อมูล

ตัวนับแพ็คเก็ตมัลติคาสต์เพิ่มขึ้น tcpdump แสดงการรับส่งข้อมูลถึงกล่อง / อินเทอร์เฟซเฉพาะ แต่เราไม่สามารถทำอะไรกับมันได้ SELinux ถูกปิดใช้งาน iptables กำลังทำงานอยู่ แต่ไม่มีกฎในตารางใด ๆ

นิ่งงันเราเป็น

ในการสุ่มวนรอบเราเริ่มคิดเกี่ยวกับพารามิเตอร์ของเคอร์เนลที่ sysctl จัดการ แต่ไม่มีคุณลักษณะของเอกสารที่เกี่ยวข้องอย่างใดอย่างหนึ่งหรือถ้าพวกเขาเกี่ยวข้องกับการรับส่งข้อมูลแบบหลายผู้รับพวกเขาถูกเปิดใช้งาน โอ้และ ifconfig ทำรายการ "MULTICAST" ในบรรทัดคุณสมบัติ (ขึ้น, ออกอากาศ, วิ่ง, มัลติคาสต์) /etc/sysctl.confจากความอยากรู้เรามองที่ แท้จริงและดูเถิดรูปฐานของลูกค้ารายนี้มีการเพิ่มบรรทัดสองบรรทัดที่ด้านล่าง

net.ipv4.all.rp_filter = 1ในกรณีของเราลูกค้าได้ตั้ง rp_filter เป็นตัวกรองเส้นทางของเส้นทางซึ่ง (ตามที่ฉันเข้าใจ) ปฏิเสธการรับส่งข้อมูลทั้งหมดที่อาจไม่ถึงช่องนี้ เครือข่ายซับเน็ตกระโดดความคิดที่ว่า IP ต้นทางกำลังถูกปลอมแปลง

เซิร์ฟเวอร์นี้อยู่ในเครือข่ายย่อย 192.168.1 / 24 และที่อยู่ IP ของอุปกรณ์สำหรับการรับส่งข้อมูลแบบหลายผู้รับนั้นอยู่ในเครือข่าย 10 * ดังนั้นตัวกรองจึงป้องกันไม่ให้เซิร์ฟเวอร์ทำสิ่งใดที่มีความหมายกับทราฟฟิก

การปรับแต่งสองอย่างที่ได้รับอนุมัติจากลูกค้า net.ipv4.eth0.rp_filter = 1และnet.ipv4.eth1.rp_filter = 0เราก็วิ่งอย่างมีความสุข


2
สิ่งนี้ได้ผล! rp_filterสำหรับการเชื่อมต่อเครือข่ายของเรา 10 Gb ถูกทิ้งทั้งหมดของ UDP แพ็คเก็ตของเราหลายผู้รับ การปิดตัวกรองจะทำให้ทุกอย่างไหลผ่าน
chrisaycock

เราประสบปัญหาเมื่อตั้งค่าการสตรีมมิ่งผ่าน AMT มัลติคาสต์ผ่านอุปกรณ์รับสัญญาณบนเครื่องรับของ Ubuntu และเราสามารถเห็นแพ็คเก็ตที่ส่งไปยังอุปกรณ์ผ่าน tcpdump แต่แอปพลิเคชันไม่ต้องการสตรีม โพสต์นี้ช่วยเราได้!
วิศวกรซอฟต์แวร์

2
ทำงานบน Ubuntu 14.04 นี่ใช้ได้สำหรับฉันเท่านั้นหลังจากฉันตั้งค่าnet.ipv4.all.rp_filter = 0แล้ว โดยเฉพาะกับข้อมูลหลายผู้รับมาถึงบน eth2 ผมต้องตั้งค่าทั้งและnet.ipv4.eth2.rp_filter = 0 net.ipv4.all.rp_filter = 0
T-Hawk

4

TL / DRตรวจสอบให้แน่ใจว่ามัลติคาสต์ของคุณไม่ได้มาจาก vlan tcpdump -eจะช่วยตรวจสอบว่าพวกเขาทำ

ในความเป็นธรรมทุกคนควรสร้างหน้าด้วยรายการตรวจสอบของสิ่งที่สามารถป้องกันไม่ให้ผู้รับหลายผู้รับเข้าถึงผู้ใช้ ฉันดิ้นรนกับสิ่งนั้นมาสองสามวันแล้วโดยธรรมชาติฉันก็ไม่สามารถหาสิ่งใดบนเว็บได้

ไม่เพียง แต่ฉันจะเห็นแพ็คเก็ตในtcpdumpแต่ฉันสามารถรับแพ็คเก็ตหลายผู้รับอื่น ๆ สำหรับผู้ผลิตรายอื่นได้จากอินเทอร์เฟซอื่น คำสั่งที่ฉันใช้ในการทดสอบว่าฉันสามารถรับ multicast ได้หรือไม่:

$ GRP=224.x.x.x # set me to the group
$ PORT=yyyy # set me to the receiving port
$ IFACE=mmmm # set me to the name or IP address of the interface
$ strace -f socat -  UDP4-DATAGRAM:$GRP:$PORT,ip-add-membership=$GRP:$IFACE,bind=0.0.0.0:$PORT,multicast-loop=0

เหตุผลที่ทำให้straceที่นี่เป็นที่ที่จริงผมไม่สามารถทำให้socatพิมพ์ออกมาแพ็คเก็ตที่ stdout แต่ในstraceการส่งออกคุณสามารถเห็นได้ชัดเจนถ้าsocatได้รับข้อมูลที่เกิดขึ้นจริงจากซ็อกเก็ตที่ถูกผูกไว้ (มันจะเป็นใบ้มิฉะนั้นหลังจากที่สองของการเริ่มต้นselectสาย)

  • rp_filtersysctl - ใช้ไม่ได้ระบบอยู่ในเครือข่าย IP เดียวกัน (ฉันตั้งให้0เหมือนกันทั้งหมดดูเหมือนว่า1เป็นการตั้งค่าเริ่มต้นตอนนี้อย่างน้อยสำหรับ Ubuntu)
  • ไฟร์วอลล์ / ฯลฯ - ระบบที่รับเป็นไฟร์วอลล์ฟรี (ฉันไม่คิดว่าแพ็คเก็ตจะปรากฏขึ้นใน tcpdump หากพวกเขาถูกไฟร์วอลล์ แต่ฉันเดาว่ามันเป็นไปได้ถ้าไฟร์วอลล์เป็นเรื่องตลก)
  • การกำหนดเส้นทาง IP / Multicast และอินเทอร์เฟซหลายรายการ - ฉันเข้าร่วมกลุ่มอย่างชัดเจนบนอินเทอร์เฟซที่ถูกต้อง
  • ฮาร์ดแวร์เครือข่ายที่แปลกประหลาด - นี่เป็นทางเลือกสุดท้ายของฉัน แต่การเปลี่ยนแล็ปท็อปไปเป็น Intel NUC ก็ไม่ได้ช่วยอะไร นี่เป็นเรื่องที่ฉันเริ่มเคี้ยวข้อศอกและโพสต์สิ่งนี้ไปยัง SE
  • ปัญหาในกรณีของฉันคือการใช้ VLANs โดยฮาร์ดแวร์พิเศษที่ผลิตแพ็กเก็ตมัลติคาสต์เหล่านั้น หากต้องการดูว่านี่เป็นปัญหาของคุณหรือไม่โปรดรวมการ-eตั้งค่าสถานะไว้tcpdumpและตรวจสอบแท็ก vlan จะต้องกำหนดค่าอินเทอร์เฟซลงใน vlan ที่ถูกต้องก่อนที่ผู้ใช้จะสามารถรับแพ็กเก็ตเหล่านั้นได้ ของแถมสำหรับฉันจริงๆแล้วคือผู้ผลิตมัลติคาสต์จะไม่ปิง แต่จะไม่ได้เข้าไปในแคช ARP แม้ว่าฉันจะเห็นการตอบกลับ ARP ชัดเจน

หากต้องการให้มันทำงานด้วย VLAN ลิงก์นี้อาจมีประโยชน์ในการกำหนดค่าการกำหนดเส้นทางแบบหลายผู้รับ (น่าเสียดายที่ฉันใหม่สำหรับเรื่องนี้ดังนั้นชื่อเสียงไม่อนุญาตให้ฉันเพิ่มคำตอบดังนั้นการแก้ไขนี้)

นี่คือสิ่งที่ฉันทำ (ใช้ sudo ถ้าจำเป็น):

ip link add link eth0 name eth0_100 type vlan id 100
ip addr add 192.168.100.2/24 brd 192.168.100.255 dev eth0_100
ip link set dev eth0_100 up
ip maddr add 01:00:5e:01:01:01 dev eth0_100
route -n add -net 224.0.0.0 netmask 240.0.0.0 dev eth0_100

วิธีนี้เป็นอินเตอร์เฟสเพิ่มเติมหากสร้างขึ้นสำหรับการรับส่งข้อมูล vlan ด้วย vlan id 100 vlan ip อาจไม่จำเป็น จากนั้นมัลติคาสต์แอดเดรสจะถูกกำหนดค่าสำหรับอินเทอร์เฟซใหม่ (01: 00: 5e: 01: 01: 01 เป็นลิงค์เลเยอร์ที่อยู่สำหรับ 239.1.1.1) และการรับส่งข้อมูลมัลติคาสต์ขาเข้าทั้งหมดจะถูกผูกไว้กับ eth0_100 ฉันยังทำตามขั้นตอนทั้งหมดที่เป็นไปได้ในคำตอบข้างต้น (ตรวจสอบ iptables, rp_filter ฯลฯ )


@Gero: การเพิ่มมัลติคาสต์เส้นทางตั้งค่ามัลติคาสต์ขาออกไม่ใช่มัลติคาสต์ขาเข้า คุณไม่ควรผูกที่อยู่ IP แบบหลายผู้รับกับอินเทอร์เฟซโดยตรงเว้นแต่ว่าคุณกำลังทำสิ่งที่ขี้ขลาดมันเป็นงานของแอปพลิเคชัน
Pawel Veselov

2

คุณอาจต้องการลองดูการตั้งค่าเหล่านี้:

proc

echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

sysctl.conf

sed -i -e 's|^net.ipv4.icmp_echo_ignore_broadcasts =.*|net.ipv4.icmp_echo_ignore_broadcasts = 0|g' /etc/sysctl.conf

สิ่งเหล่านี้ถูกใช้เพื่อเปิดใช้งานมัลติคาสต์ใน RHEL

คุณอาจต้องการตรวจสอบให้แน่ใจว่าไฟร์วอลล์ของคุณอนุญาตการรับส่งข้อมูล mutlicast อีกครั้งกับ RHEL ฉันได้เปิดใช้งานต่อไปนี้:

# allow anything in on multicast addresses
-A INPUT -s 224.0.0.0/4 -j ACCEPT
-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT
# needed for multicast ping responses
-A INPUT -p icmp --icmp-type 0 -j ACCEPT

ตัวเลือก "ออกอากาศ" ใช้กับ "มัลติคาสต์" ด้วยหรือไม่
Raedwald

0

คุณใช้สวิตช์ที่จัดการหรือไม่ บางตัวเลือกมีการป้องกัน 'การแพร่กระจายของพายุ' หรือปัญหามัลติคาสต์อื่น ๆ ซึ่งจะทำให้พวกเขาป้องกันแพ็กเก็ตบางประเภท ฉันขอแนะนำให้ดูที่เอกสารสวิทช์ของคุณ


0
s.bind("", 15572)

แน่ใจเกี่ยวกับ "" ทำไมไม่ใช้ multicast IP-address เพื่อผูกไว้?


ที่อยู่โฮสต์ที่ว่างเปล่าโดยทั่วไปหมายถึง "อินเทอร์เฟซทั้งหมด"
VxJasonxV
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.