Linux ไม่ตอบกลับข้อความขอ ARP หากที่อยู่ IP ที่ร้องขอนั้นเชื่อมโยงกับอินเทอร์เฟซอื่น (ปิดใช้งาน)


9

ฉันมีพีซี (เคอร์เนล3.2.0-23-generic ) ซึ่งได้192.168.1.2/24กำหนดค่าให้กับeth0ส่วนต่อประสานและยังใช้192.168.1.1และ192.168.1.2ที่อยู่สำหรับtun0อินเทอร์เฟซ:

root@T42:~# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:41:54:01:93 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 scope global eth0
    inet6 fe80::216:41ff:fe54:193/64 scope link
       valid_lft forever preferred_lft forever
3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
4: irda0: <NOARP> mtu 2048 qdisc noop state DOWN qlen 8
    link/irda 00:00:00:00 brd ff:ff:ff:ff
5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:13:ce:8b:99:3e brd ff:ff:ff:ff:ff:ff
    inet 10.30.51.53/24 brd 10.30.51.255 scope global eth1
    inet6 fe80::213:ceff:fe8b:993e/64 scope link
       valid_lft forever preferred_lft forever
6: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc pfifo_fast state DOWN qlen 100
    link/none
    inet 192.168.1.1 peer 192.168.1.2/32 scope global tun0
root@T42:~# ip route show dev eth0
192.168.1.0/24  proto kernel  scope link  src 192.168.1.2 
root@T42:~# 

ตามที่เห็นด้านบนtun0ถูกปิดใช้งานการบริหาร ( ip link set dev tun0 down) ตอนนี้เมื่อฉันได้รับคำขอ ARP สำหรับ192.168.1.2พีซีจะไม่ตอบกลับคำขอเหล่านั้น:

root@T42:~# tcpdump -nei eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:30:34.875427 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:36.875268 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:39.138651 00:1a:e2:ae:cb:b7 > 00:1a:e2:ae:cb:b7, ethertype Loopback (0x9000), length 60:
^C
3 packets captured
3 packets received by filter
0 packets dropped by kernel
root@T42:~#

แต่หลังจากที่ผมลบtun0อินเตอร์เฟซ ( ip link del dev tun0) เครื่องคอมพิวเตอร์จะตอบกลับการร้องขอ ARP สำหรับ192.168.1.2ในeth0อินเตอร์เฟซ

ตารางเส้นทางดูเหมือนกันก่อนและหลังip link del dev tun0:

root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# ip link del dev tun0
root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# 

รายการการเราต์ด้านล่างถูกลบแล้วด้วยip link set dev tun0 downคำสั่ง:

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.1.2     0.0.0.0         255.255.255.255 UH        0 0          0 tun0

อย่างไรก็ตามในขณะที่ตารางเส้นทางมีความเหมือนกันทั้งก่อนและหลังip link del dev tun0คำสั่งเคอร์เนลการตัดสินใจเส้นทางจริงจะไม่:

T42:~# ip route get 192.168.1.1
local 192.168.1.1 dev lo  src 192.168.1.1 
    cache <local> 
T42:~# ip link del dev tun0
T42:~# ip route get 192.168.1.1
192.168.1.1 dev eth0  src 192.168.1.2 
    cache  ipid 0x8390
T42:~# 

นี่เป็นพฤติกรรมที่คาดหวังหรือไม่? เหตุใดเคอร์เนลจึงไม่สนใจตารางเส้นทาง


คุณสามารถวางเอาต์พุตของ netstat -rn สำหรับทั้งสองกรณีได้หรือไม่? โดยทั่วไปตารางเส้นทางเป็นที่แรกที่จะค้นหาข้อผิดพลาดเหล่านี้
Clarus

@Claris ฉันอัปเดตโพสต์เริ่มต้นแล้ว
Martin

การมี IP เดียวกันบนสองอินเทอร์เฟซสามารถสร้างปัญหาและหลีกเลี่ยงได้ดีที่สุดนั่นคือการบอกว่าคุณควรจะสามารถติดตามปัญหาได้ ขั้นตอนต่อไปคือการดูแคช arp, arp -a แสดงอะไรที่มีประโยชน์หรือไม่
Clarus

@Claris ดูเหมือนว่าสาเหตุหลักคือเคอร์เนลจะละเว้นตารางการเราต์เมื่อtun0อินเตอร์เฟสถูกปิดใช้งาน แต่มีอยู่ ดูผลลัพธ์ของip route getคำสั่งในโพสต์เริ่มต้นที่อัปเดตของฉัน อย่างไรก็ตามทำไมเคอร์เนลจึงมีพฤติกรรมเช่นนั้น
Martin

คำตอบ:


17

ตารางเส้นทางของคุณจะไม่ถูกละเว้น กำลังถูกแทนที่โดยตารางเส้นทางที่มีลำดับความสำคัญสูงกว่า

เกิดอะไรขึ้น

ตารางเส้นทางที่คุณเห็นเมื่อคุณพิมพ์ip route showไม่ใช่ตารางเส้นทางเท่านั้นที่เคอร์เนลใช้ อันที่จริงมีตารางการเราต์อยู่สามตารางโดยค่าเริ่มต้นและจะค้นหาตามลำดับที่แสดงโดยip ruleคำสั่ง:

# ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

ตารางที่คุณกำลังส่วนใหญ่คุ้นเคยกับการเป็นแต่ตารางลำดับความสำคัญสูงสุดคือการกำหนดเส้นทางmain localตารางนี้ได้รับการจัดการโดยเคอร์เนลเพื่อติดตามเส้นทางภายในและการออกอากาศ: ในคำอื่น ๆlocalตารางบอกเคอร์เนลวิธีการกำหนดเส้นทางไปยังที่อยู่ของอินเทอร์เฟซของตัวเอง ดูเหมือนว่า:

# ip route show table local
broadcast 127.0.0.0 dev lo  proto kernel  scope link  src 127.0.0.1
local 127.0.0.0/8 dev lo  proto kernel  scope host  src 127.0.0.1
local 127.0.0.1 dev lo  proto kernel  scope host  src 127.0.0.1
broadcast 127.255.255.255 dev lo  proto kernel  scope link  src 127.0.0.1
broadcast 192.168.1.0 dev eth0  proto kernel  scope link  src 192.168.1.2
local 192.168.1.1 dev tun0  proto kernel  scope host  src 192.168.1.1
local 192.168.1.2 dev eth0  proto kernel  scope host  src 192.168.1.2
broadcast 192.168.1.255 dev eth0  proto kernel  scope link  src 192.168.1.2

ตรวจสอบการอ้างอิงบรรทัดtun0นั้น route getนั่นคือสิ่งที่ก่อให้เกิดผลที่แปลกประหลาดของคุณจาก มันบอกว่า 192.168.1.1 เป็นที่อยู่ในพื้นที่ซึ่งหมายความว่าถ้าเราต้องการส่งการตอบกลับ ARP ไปที่ 192.168.1.1 มันเป็นเรื่องง่าย เราส่งให้เราเอง และเนื่องจากเราพบเส้นทางในlocalตารางเราจึงหยุดค้นหาเส้นทางและไม่ต้องกังวลกับการตรวจสอบmainหรือdefaultตาราง

ทำไมต้องใช้หลายตาราง

อย่างน้อยก็เป็นเรื่องดีที่สามารถพิมพ์ip routeได้และไม่เห็นเส้นทาง "ชัดเจน" เหล่านั้นทั้งหมดที่เกะกะจอแสดงผล (ลองพิมพ์route printบนเครื่อง Windows) นอกจากนี้ยังสามารถทำหน้าที่ป้องกันการกำหนดค่าผิดพลาดน้อยที่สุดแม้ว่าตารางเส้นทางหลักจะผสมกันอยู่เคอร์เนลก็ยังรู้วิธีที่จะพูดคุยกับตัวเอง

(เหตุใดจึงต้องเก็บเส้นทางไว้ในที่แรกดังนั้นเคอร์เนลจึงสามารถใช้รหัสการค้นหาเดียวกันสำหรับที่อยู่ในท้องถิ่นได้เช่นเดียวกับที่ทำเพื่อสิ่งอื่นทุกอย่างทำให้สิ่งต่าง ๆ ง่ายขึ้นภายใน)

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

หากคุณกำลังทำสิ่งที่ยุ่งยากหรือทดลองโดยเฉพาะคุณสามารถเพิ่มหรือลบlocalเส้นทางด้วยตัวคุณเองโดยการระบุtable localในip routeคำสั่ง แม้ว่าคุณจะไม่รู้ว่ากำลังทำอะไรอยู่คุณก็มีแนวโน้มที่จะทำให้เคอร์เนลเกิดความสับสน และแน่นอนเคอร์เนลจะยังคงเพิ่มและลบเส้นทางของตัวเองต่อไปดังนั้นคุณต้องดูเพื่อให้แน่ใจว่าคุณจะไม่ถูกเขียนทับ

สุดท้ายหากคุณต้องการดูตารางเส้นทางทั้งหมดในครั้งเดียว:

# ip route show table all

สำหรับข้อมูลเพิ่มเติมโปรดดูที่ip-rule(8)หน้าคนหรือiproute2 เอกสาร คุณอาจลองใช้การกำหนดเส้นทางขั้นสูงและการควบคุมการจราจร HOWTOเพื่อดูตัวอย่างของสิ่งที่คุณสามารถทำได้


ขอบคุณ! หลังจากกฎเป็นจริงยังคงอยู่ในเส้นทางตาราง เมื่อฉันดำเนินการกฎดังกล่าวถูกลบออก ยังมีอีกคำถามหนึ่งที่ฉันแก้ไขให้ถูกต้องว่าเคอร์เนล Linux สมัยใหม่ทั้งหมด (2.6.x, 3.x, 4.x) ใช้ RPDB สำหรับการค้นหาเส้นทางและทำให้ตารางหลายตาราง? ip link set dev tun0 downlocal 192.168.1.1 dev tun0 proto kernel scope host src 192.168.1.1localip link del dev tun0
Martin

2
ใช่คุณถูกต้องและอื่น ๆ RPDB เก่าอย่างน่าประหลาดใจ! "RPDB นั้นเป็นส่วนสำคัญของการเขียนทับเครือข่ายใน Linux kernel 2.2" และจากip(8): " ipถูกเขียนโดย Alexey N. Kuznetsof และเพิ่มใน Linux 2.2"
Jander

นี่เป็นหนึ่งในคำอธิบายที่ดีที่สุดของตารางการกำหนดเส้นทางเคอร์เนลหลายตัวที่ฉันเคยเห็น ขอบคุณ!
djluko

1

การกำหนดค่าการกรองเส้นทางย้อนกลับของคุณอาจเป็นปัญหา RFC3704 - ส่วน 2.4

ในการแจกแจง Enterprise Linux (RHEL, CentOS, Scientific Linux และอื่น ๆ ) วิธีที่ดีที่สุดในการแก้ไขปัญหานี้คือการแก้ไข/etc/sysctl.confด้วยrp_filter = 2

เมื่อ RHEL มีการกำหนดค่า IP หลายตัวสามารถเข้าถึงได้เพียงเครือข่ายเดียวจากเครือข่ายระยะไกล หรือทำไม RHEL ไม่สนใจแพ็กเก็ตเมื่อเส้นทางสำหรับการรับส่งข้อมูลขาออกแตกต่างจากเส้นทางการรับส่งข้อมูลขาเข้า


หากฉันใช้การตรวจสอบ RPF แบบหลวม (2) หรือแม้กระทั่งปิดการใช้งานการตรวจสอบ RPF (0) พร้อมกับfor rp_filter_file in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > "$rp_filter_file"; doneเคอร์เนลไม่ได้ใช้eth0อินเทอร์เฟซสำหรับการกำหนดเส้นทางแพ็คเก็ตเพื่อ 192.168.1.1 เมื่อฉันลบtun0อินเตอร์เฟสด้วยip link del dev tun0เคอร์เนลก็เริ่มใช้eth0อินเตอร์เฟสได้
มาร์ติน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.