Linux non risponde ai messaggi di richiesta ARP se l'indirizzo IP richiesto è associato a un'altra interfaccia (disabilitata)


9

Ho un PC (kernel 3.2.0-23-generico ) che ha 192.168.1.2/24configurato per l' eth0interfaccia e usa anche 192.168.1.1e 192.168.1.2indirizzi per l' tun0interfaccia:

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:~# 

Come visto sopra, tun0è amministrativamente disabilitato ( ip link set dev tun0 down). Ora quando ricevo richieste ARP per 192.168.1.2, il PC non risponde a tali richieste:

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:~#

Solo dopo aver eliminato l' tun0interfaccia ( ip link del dev tun0) il PC risponderà alla richiesta ARP per 192.168.1.2l' eth0interfaccia.

La tabella di routing è esattamente uguale prima e dopo 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:~# 

La voce di routing di seguito viene rimossa già con il ip link set dev tun0 downcomando:

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

Tuttavia, mentre le tabelle di routing sono esattamente uguali prima e dopo il ip link del dev tun0comando, le decisioni di routing effettive che il kernel prenderà non sono:

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:~# 

È un comportamento previsto? Perché il kernel ignora la tabella di routing?


Riesci a incollare l'output di netstat -rn per entrambi i casi? La tabella di routing è in genere il primo posto in cui cercare questo tipo di errori.
Clarus,

@Claris Ho aggiornato il mio post iniziale.
Martin,

Avere lo stesso IP su due interfacce può creare problemi ed è meglio evitarlo, detto ciò dovresti essere in grado di rintracciare il problema. Il prossimo passo è guardare la cache arp, arp -a mostra qualcosa di utile?
Clarus,

@Claris Sembra che la causa principale sia che il kernel ignora la tabella di routing quando l' tun0interfaccia è disabilitata, ma presente. Vedi l'output dei ip route getcomandi nel mio post iniziale aggiornato. Tuttavia, perché il kernel si comporta così?
Martin,

Risposte:


17

La tua tabella di routing non viene ignorata, esattamente. Viene sovrascritto da una tabella di routing con priorità più elevata.

Cosa sta succedendo

La tabella di routing visualizzata durante la digitazione ip route shownon è l'unica tabella di routing utilizzata dal kernel. In effetti, ci sono tre tabelle di routing per impostazione predefinita e vengono cercate nell'ordine mostrato dal ip rulecomando:

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

La tabella con cui hai più familiarità è main, ma la tabella di routing con la priorità più elevata è local. Questa tabella è gestita dal kernel per tenere traccia delle route locali e broadcast: in altre parole, la localtabella indica al kernel come instradare verso gli indirizzi delle proprie interfacce. Sembra qualcosa del genere:

# 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

Dai un'occhiata a quella linea di riferimento tun0. Questo è ciò che sta causando i tuoi strani risultati route get. Dice che 192.168.1.1 è un indirizzo locale, il che significa che se vogliamo inviare una risposta ARP a 192.168.1.1, è facile; lo inviamo a noi stessi. E poiché abbiamo trovato un percorso nella localtabella, smettiamo di cercare un percorso e non ci preoccupiamo di controllare le tabelle maino default.

Perché più tavoli?

Come minimo, è bello poter digitare ip routee non vedere tutti quei percorsi "ovvi" che ingombrano il display (prova a digitare route printsu un computer Windows). Può anche servire da protezione minima contro errori di configurazione: anche se la tabella di routing principale è stata confusa, il kernel sa ancora come parlare con se stesso.

(Perché mantenere le rotte locali in primo luogo? Quindi il kernel può usare lo stesso codice di ricerca per gli indirizzi locali come fa per tutto il resto. Rende le cose più semplici internamente.)

Ci sono altre cose interessanti che puoi fare con questo schema a più tabelle. In particolare, puoi aggiungere le tue tabelle e specificare le regole per quando vengono ricercate. Questo si chiama "routing delle politiche" e se hai mai desiderato instradare un pacchetto in base al suo indirizzo di origine , ecco come farlo in Linux.

Se stai facendo cose particolarmente complicate o sperimentali, puoi aggiungere o rimuovere i localpercorsi specificando table localnel ip routecomando. A meno che tu non sappia cosa stai facendo, probabilmente confonderai il kernel. E, naturalmente, il kernel continuerà comunque ad aggiungere e rimuovere i propri percorsi, quindi devi fare attenzione per assicurarti che i tuoi non vengano sovrascritti.

Infine, se vuoi vedere tutte le tabelle di routing contemporaneamente:

# ip route show table all

Per maggiori informazioni, controlla la ip-rule(8)pagina man o i documenti iproute2 . Potresti anche provare l' HOWTO Advanced Routing and Traffic Control per alcuni esempi di cosa puoi fare.


Grazie! Dopo che ip link set dev tun0 downla local 192.168.1.1 dev tun0 proto kernel scope host src 192.168.1.1regola era effettivamente ancora presente nella localtabella di routing. Una volta eseguita ip link del dev tun0la regola menzionata è stata rimossa. Tuttavia, una domanda: ho ragione che tutti i moderni kernel Linux (2.6.x, 3.x, 4.x) usano RPDB per le ricerche di route e quindi più tabelle?
Martin,

2
Sì, hai ragione e altro ancora. RPDB è sorprendentemente vecchio! "Lo stesso RPDB era parte integrante della riscrittura dello stack di rete nel kernel 2.2 di Linux." E da ip(8): "è ipstato scritto da Alexey N. Kuznetsof e aggiunto in Linux 2.2".
Jander

Questa è una delle migliori spiegazioni delle molteplici tabelle di routing del kernel che ho visto. Grazie!
djluko,

1

La configurazione del filtro per il percorso inverso è probabilmente il problema. RFC3704 - sezione 2.4

Nelle distribuzioni Enterprise Linux (RHEL, CentOS, Scientific Linux, ecc.) Il modo migliore per risolverlo è modificare /etc/sysctl.confconrp_filter = 2

Quando RHEL ha più IP configurati, solo uno è raggiungibile da una rete remota. O perché RHEL ignora i pacchetti quando la route per il traffico in uscita differisce dalla route del traffico in entrata?


Se uso il controllo RPF libero (2) o disabilito il controllo RPF (0) del tutto con for rp_filter_file in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > "$rp_filter_file"; doneil kernel, non uso l' eth0interfaccia per instradare i pacchetti a 192.168.1.1. Solo una volta che cancello l' tun0interfaccia con ip link del dev tun0il kernel inizia a utilizzare l' eth0interfaccia.
Martin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.