nftables: ทำซ้ำแพ็กเก็ตออกอากาศระหว่างเซ็กเมนต์
เรามีกล่อง Debian Buster (nftables 0.9.0, kernel 4.19) ที่แนบมากับกลุ่มเครือข่ายที่แตกต่างกันสี่กลุ่ม สามส่วนเหล่านี้เป็นที่ตั้งของอุปกรณ์ที่ใช้ Syncthing ซึ่งเรียกใช้การค้นพบในเครื่องของตัวเองผ่านการออกอากาศไปยังพอร์ต UDP 21027 ดังนั้นอุปกรณ์ทั้งหมดจึงไม่สามารถ "มองเห็น" ซึ่งกันและกันได้เนื่องจากการแพร่ภาพไม่ได้ข้ามส่วน กล่อง Buster เองไม่ได้มีส่วนร่วมในคลัสเตอร์การซิงค์
แม้ว่าเราจะแก้ปัญหานี้ได้ด้วยการเรียกใช้เซิร์ฟเวอร์การค้นพบหรือรีเลย์ของ Syncthing ในกล่อง Buster แต่ก็มีการร้องขอให้เราไม่ใช้มัน (เหตุผลเกี่ยวกับการกำหนดค่าและอุปกรณ์ที่เดินทางไปยังไซต์อื่น) ดังนั้นเรากำลังมองหาโซลูชันที่ใช้ nftables ความเข้าใจของฉันคือปกติแล้วสิ่งนี้ไม่ได้ทำ แต่เพื่อให้ทำงานนี้เราต้อง:
- จับคู่แพ็กเก็ตขาเข้าบน UDP 21027
- คัดลอกแพ็กเก็ตเหล่านั้นไปยังอินเทอร์เฟซเซกเมนต์อื่นที่ต้องการให้เห็น
- เปลี่ยน IP ปลายทางของแพ็กเก็ตใหม่เพื่อให้ตรงกับที่อยู่การออกอากาศของเซ็กเมนต์ใหม่ (ในขณะที่รักษา IP ต้นทางเนื่องจากโปรโตคอลการค้นพบสามารถพึ่งพาได้)
- ปล่อยการออกอากาศใหม่โดยไม่ให้ซ้ำกันอีก
มีเพียงสามกลุ่มที่แนบมาเท่านั้นที่เข้าร่วมกับอุปกรณ์ ทั้งหมดเป็นซับเน็ตมาสก์เป็น / 24
- ไม่ควรส่งต่อส่วน A (eth0, 192.168.0.1)
- เซ็กเมนต์ B (eth1, 192.168.1.1) ควรถูกส่งต่อไปยังเซ็กเมนต์ A เท่านั้น
- ควรส่งต่อส่วน C (eth2, 192.168.2.1) ไปยังทั้ง A และ B
สิ่งที่ใกล้เคียงที่สุดที่เราต้องมีกับกฎการทำงานสำหรับสิ่งนี้คือ (DNAT / MASQ อื่น ๆ และกฎการกรองในพื้นที่ถูกละไว้เพื่อความกะทัดรัด):
table ip mangle {
chain repeater {
type filter hook prerouting priority -152; policy accept;
ip protocol tcp return
udp dport != 21027 return
iifname "eth1" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.1.255 return
iifname "eth0" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.0.255 return
iifname "eth0" ip saddr 192.168.1.0/24 counter ip daddr set 192.168.0.255 return
iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1
iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.1.255 device "eth1" nftrace set 1
iifname "eth1" ip saddr 192.168.1.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1
}
}
ตัวนับแสดงให้เห็นว่ามีการตีกฎแม้ว่าจะไม่มีdaddr set
กฎที่อยู่การออกอากาศจะยังคงเหมือนเดิมในส่วนต้นทาง nft monitor trace
แสดงให้เห็นว่าอย่างน้อยแพ็กเก็ตบางส่วนกำลังเข้าถึงอินเทอร์เฟซที่ต้องการด้วย IP ปลายทางที่ถูกต้อง แต่จากนั้นจะเชื่อมโยงไปถึงในเบ็ดอินพุตสำหรับกล่องเองและอุปกรณ์อื่น ๆ ในเซ็กเมนต์นั้นจะไม่เห็น
ผลลัพธ์ที่เรากำลังมองหาที่นี่เป็นไปได้ในทางปฏิบัติหรือไม่และถ้าเป็นเช่นนั้นกฎใด
คำตอบ
ยังคงเป็นไปได้ที่จะใช้ nftables ในตระกูลnetdev (แทนที่จะเป็นตระกูลip ) สำหรับกรณีนี้เนื่องจากจำเป็นต้องใช้เฉพาะทางเข้าเท่านั้น(nftables ยังไม่มีขาออก ) ลักษณะการทำงานของdup
และfwd
ในการเข้าเบ็ดเป็นเหมือนกับTC-mirred 's และmirror
redirect
ฉันยังกล่าวถึงรายละเอียดเล็กน้อย: เขียนที่อยู่ต้นทางอีเธอร์เน็ตไปยังที่อยู่ MAC ของอินเทอร์เฟซขาออกอีเทอร์เน็ตใหม่เช่นเดียวกับที่เคยทำมาสำหรับแพ็กเก็ตที่กำหนดเส้นทางอย่างแท้จริงแม้ว่าจะเหมาะกับคุณหากไม่มีสิ่งนี้ก็ตาม ดังนั้นจึงต้องทราบที่อยู่ MAC ของอินเทอร์เฟซล่วงหน้า ฉันใส่สองสิ่งที่จำเป็น ( eth0 's และeth1 ' s) ในตัวแปร / นิยามมาโครซึ่งควรแก้ไขด้วยค่าที่ถูกต้อง
define eth0mac = 02:0a:00:00:00:01
define eth1mac = 02:0b:00:00:00:01
table netdev statelessnat
delete table netdev statelessnat
table netdev statelessnat {
chain b { type filter hook ingress device eth1 priority 0;
pkttype broadcast ether type ip ip daddr 192.168.1.255 udp dport 21027 jump b-to-a
}
chain c { type filter hook ingress device eth2 priority 0;
pkttype broadcast ether type ip ip daddr 192.168.2.255 udp dport 21027 counter jump c-to-b-a
}
chain b-to-a {
ether saddr set $eth0mac ip daddr set 192.168.0.255 fwd to eth0 } chain c-to-b-a { ether saddr set $eth1mac ip daddr set 192.168.1.255 dup to eth1 goto b-to-a
}
}
แก้ไข: สำหรับใครก็ตามที่พบสิ่งนี้ในภายหลังคำตอบที่ยอมรับจาก AB จะให้วิธีแก้ปัญหาอย่างหมดจด
ขอบคุณคำแนะนำของ AB ตอนนี้ใช้งานได้โดยใช้ tc แทนที่จะเป็นกฎ nftables ล้วนๆ:
tc qdisc add dev eth2 ingress
tc filter add dev eth2 ingress \
protocol ip u32 \
match ip dst 192.168.2.255 \
match ip protocol 17 0xff \
match ip dport 21027 0xffff \
action nat ingress 192.168.2.255/32 192.168.0.255 \
pipe action mirred egress mirror dev eth0 \
pipe action nat ingress 192.168.0.255/32 192.168.1.255 \
pipe action mirred egress redirect dev eth1
tc qdisc add dev eth1 ingress
tc filter add dev eth1 ingress \
protocol ip u32 \
match ip dst 192.168.1.255 \
match ip protocol 17 0xff \
match ip dport 21027 0xffff \
action nat ingress 192.168.1.255/32 192.168.0.255 \
pipe action mirred egress redirect dev eth0
ความเข้าใจของฉันเกี่ยวกับตัวกรองเหล่านี้คือจับคู่แพ็กเก็ตการออกอากาศขาเข้าสำหรับพอร์ต UDP 21027 NAT กับที่อยู่ออกอากาศสำหรับเครือข่ายย่อยอื่น ๆ ที่ต้องการ ( ingress
เพื่อเปลี่ยน IP ปลายทางแทนที่จะเป็น IP ต้นทางที่nat egress
จะเปลี่ยนแปลง) จากนั้นทำซ้ำ / เปลี่ยนเส้นทาง แพ็กเก็ต NATted ไปยังคิวเอาต์พุตของอินเทอร์เฟซอื่น ๆ
การเป็นมือใหม่ที่มี tc นี่อาจไม่ใช่วิธีที่ดีที่สุดในการแก้ปัญหา แต่ได้ผลในแง่ของการทำให้การประกาศออกอากาศเดินทางข้ามเซกเมนต์ (และการซิงค์กำลังค้นพบโหนดใหม่อย่างมีความสุข)