ฉันต้องการแลกเปลี่ยน Ethernet Packet ระหว่างอุปกรณ์แตะสองเครื่อง (สำหรับการนำโปรโตคอล TCP/IP stack ไปใช้ในโหมดผู้ใช้)
ปัญหาที่ฉันพบคือ tap1 และ tap2 สามารถรับแพ็กเก็ตออกอากาศผ่านบริดจ์เท่านั้น แต่ไม่สามารถรับแพ็กเก็ตแบบจุดต่อจุดได้!
ตัวอย่างเช่น เมื่อฉันส่งแพ็กเก็ตจาก tap1 ไปยัง tap2 tcmpdump สามารถจับแพ็กเก็ตบน tap1 ได้ แต่ tap2 ไม่สามารถรับแพ็กเก็ตได้ อย่างไรก็ตาม เมื่อฉันตั้งค่าที่อยู่ปลายทางเป็น "ff:ff:ff:ff:ff:ff" หรืออื่นๆ ที่อยู่ mac ที่ไม่รู้จัก (นี่จะเป็นการส่งสัญญาณทริกเกอร์) tap2 จะได้รับแพ็กเก็ต
การกำหนดค่าของฉัน:
- สร้างอุปกรณ์แตะสองเครื่อง
ip tuntap เพิ่มโหมด tap tun1
ip tuntap เพิ่มโหมด tap tun2
# กำหนดที่อยู่ IP สำหรับการนำโปรโตคอล arp ไปใช้
ip addr เพิ่ม 172.19.16.1 dev tun1
ip addr เพิ่ม 172.19.16.2 dev tun2
ลิงค์ ip ตั้งค่า tun1 ขึ้น
ลิงค์ ip ตั้งค่า tun2 ขึ้น
- สร้างสะพาน
brctl บวกbr br0
brctl addif br0 tun1
brctl addif br0 tun2
ลิงค์ ip ตั้งค่า br0 ขึ้น
ต่อไปนี้คือสถานะของบริดจ์และอินเตอร์เฟสการแตะ:
แม็ค:
พอร์ตไม่มี mac addr อยู่ในเครื่องหรือไม่ ตัวจับเวลาอายุ
2 46:44:6e:55:9b:c5 ใช่ 0.00
2 46:44:6e:55:9b:c5 ใช่ 0.00
1 f2:6b:68:c9:60:6b ใช่ 0.00
1 f2:6b:68:c9:60:6b ใช่ 0.00
สถานะ:
br0
รหัสบริดจ์ 8000.46446e559bc5
กำหนดรูท 8000.46446e559bc5
รูทพอร์ต 0 เส้นทางต้นทุน 0
อายุสูงสุด 20.00 น. อายุสะพานสูงสุด 20.00 น
สวัสดีเวลา 2.00 สะพานสวัสดีเวลา 2.00 น
เดินหน้าล่าช้า 15.00 สะพาน เดินหน้าล่าช้า 15.00 น
อายุการใช้งาน 300.00
สวัสดี จับเวลา 0.00 tcn จับเวลา 0.00
ตัวจับเวลาการเปลี่ยนแปลงโทโพโลยี 0.00 gc ตัวจับเวลา 89.77
ธง
อุโมงค์1 (1)
พอร์ต id 8001 สถานะการส่งต่อ
เส้นทาง root 8000.46446e559bc5 ที่กำหนดราคา 100
บริดจ์ที่กำหนด 8000.46446e559bc5 ตัวจับเวลาอายุข้อความ 0.00
พอร์ตที่กำหนด 8001 ตัวตั้งเวลาหน่วงไปข้างหน้า 0.00
ค่าใช้จ่ายที่กำหนด 0 ตัวจับเวลา 0.00
ธง
ทูนทู (2)
พอร์ต id 8002 สถานะการส่งต่อ
เส้นทาง root 8000.46446e559bc5 ที่กำหนดราคา 100
บริดจ์ที่กำหนด 8000.46446e559bc5 ตัวจับเวลาอายุข้อความ 0.00
พอร์ตที่กำหนด 8002 ตัวตั้งเวลาหน่วงไปข้างหน้า 0.00
ค่าใช้จ่ายที่กำหนด 0 ตัวจับเวลา 0.00
ธง
ต่อไปนี้เป็นรหัสทดสอบของฉัน:
นำเข้าfcntl
นำเข้าระบบปฏิบัติการ
นำเข้า if_tun
ctypes นำเข้า
โครงสร้างการนำเข้า
จากการนำเข้า scapy.all *
จาก if_tun นำเข้า IfReq, TUNSETIFF, IFF_TUN
def register_tun (ชื่อ: str):
fd = os.open("/dev/net/tun",os.O_RDWR)
ถ้า fd < 0:
กลับ fd
r = IfReq()
ctypes.memset(ctypes.byref(r), 0, ctypes.sizeof(r))
r.ifr_ifru.ifru_flags = 0x0002 | 0x1000
r.ifr_ifrn.ifrn_name = name.encode("utf-8")
fcntl.ioctl(fd, TUNSETIFF,r)
กลับ fd
ถ้า __name__ == "__main__":
ชื่อ = อินพุต ("ชื่ออุปกรณ์อินพุต")
fd = register_tun (ชื่อ)
ถ้า fd < 0:
พิมพ์ ("ข้อผิดพลาด")
ถ้าชื่อ == "tun2":
ในขณะที่ทรู:
buf = os.read(fd,1024)
พิมพ์ (f "รับข้อมูล {len (buf)}")
อีเธอร์(ดิบ(บัฟ)).แสดง()
mac1 = "f2:6b:68:c9:60:6b"
mac2 = "46:44:6e:55:9b:c5"
ในขณะที่ทรู:
ประเภท = อินพุต ()
a = อีเธอร์(dst=mac2,src=mac1)/ARP(pdst="172.19.16.1",psrc="172.19.16.2")
การแสดง()
พิมพ์ ("เขียน:")
พิมพ์ (os.write (fd, ดิบ (a)))
หมายเหตุ:
- แม้ว่าชื่ออุปกรณ์จะเรียกว่า tun แต่เป็นประเภท tap
- ฉันรันโค้ดทดสอบสองโค้ดพร้อมกัน โค้ดหนึ่งเชื่อมต่อ tun1 และอีกโค้ดหนึ่งเชื่อมต่อ tun2 ดังนั้นอุปกรณ์สองเครื่องจึงมีสถานะ LOWWER_UP