quinta-feira, 29 de novembro de 2007

ARP e ARP Flux

O protocolo ARP (Address Resolution Protocol) é utilizado para mapear endereços IP-para-ethernet e é tão utilizado que é quase impossível encontrar redes que utilizem um outro mecanismo para mapear endereços IP-para-ethernet (por exemplo, o mapeamento estático).


Quando uma estação deseja enviar um pacote para outra estação ou gateway de uma rede, é necessário, além de conhecer o endereço IP de destino, saber qual é o endereço ethernet (MAC address) de destino. Neste momento o protocolo ARP é acionado para encontrar a partir de um endereço IP o endereço ethernet correspondente.

Se o host-192-168-0-9 deseja enviar um datagrama IP para o host-192-168-0-100 então é necessário primeiro conhecer o endereço ethernet (mac address), que no exemplo abaixo é "00:0e:35:50:xx:xx":

host-192-168-0-9:~ $ tcpdump -ni en1 arp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on en1, link-type EN10MB (Ethernet), capture size 96 bytes
00:28:34.090647 arp who-has 192.168.0.100 tell 192.168.0.9
00:28:34.094124 arp reply 192.168.0.100 is-at 00:0e:35:50:xx:xx

Até aqui tudo normal. 

Quando um host com linux instalado possui duas ou mais interfaces de rede conectadas a um mesmo segmento de rede, podem ocorrer problemas com o mapeamento entre os endereços de camada 2 (ethernet) e camada 3 (IP). Isso ocorre pois o host responderá uma requisição ARP pelas duas interfaces de rede. Este comportamento pode gerar confusão na tabela de ARP do host que disparou a requisição ARP. Este comportamento é chamado de ARP Flux. É importante ressaltar também que este comportamento somente irá ocorrer quando duas ou mais interfaces estiverem conectadas à um mesmo segmento de rede (mesmo domínio de broadcast).

Um exemplo de ARP Flux:

[root@real-client]# arping -I eth0 -c 3 10.10.20.67
ARPING 10.10.20.67 from 10.10.20.33 eth0
Unicast reply from 10.10.20.67 [00:80:C8:7E:71:D4]  11.298ms
Unicast reply from 10.10.20.67 [00:80:C8:E8:1E:FC]  12.077ms
Unicast reply from 10.10.20.67 [00:80:C8:E8:1E:FC]  1.542ms
Unicast reply from 10.10.20.67 [00:80:C8:E8:1E:FC]  1.547ms
Sent 3 probes (1 broadcast(s))
Received 4 response(s)

Note que para um mesmo endereço IP há duas respostas com dois endereços ethernet distintos. Como não é possível saber qual das respostas será processada primeiro pelo host que disparou a requisição é possível que o endereço errado seja incluído na tabela ARP e a comunicação entre os dois hosts não aconteça.

Há basicamente quatro maneiras diferentes de resolver este problema. No kernel 2.4 pode-se utilizar a opção arp_filter do sysctl. Nos kernels 2.2 é necessário utilizar a opção hidden do systcl. Estas duas opções controlam a forma como são tratadas as requisições ARP por interface. 

As outras soluções envolvem a utilização do a ferramenta ip arp e a opção noarp route flag. A ferramenta ip arp e a filtragem do protocolo ARP está documentada aqui.

Como utilizar a opção arp_filter?

Basicamente a utilização da opção arp_filter (/proc/sys/net/ipv4/conf/$DEV/arp_filter) faz com que um host utilize a tabela de roteamento para encontrar por qual interface o mesmo deve encaminhar a resposta de uma requisição ARP, ao invés da opção padrão de encaminhar a resposta por TODAS as interfaces.

De modo geral, a utilização da opção arp_filter resolve o problema de ARP Flux e pode gerar problemas somente em cenários mais complexos onde é necessário controlar de forma mais detalhada as requisições e respostas do protocolo ARP.

Para alterar esta opção podemos utilizar "o bom e velho" echo, por exemplo, para a interface eth0:

user@host-192-168-0-9:~ $ echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_filter

Para mais informações sobre o protocolo ARP e o problema do ARP Flux, consultar este material (em inglês).

5 comentários:

Anônimo disse...

Gustavo, não entendi muito bem.

Você diz que "Quando um host com linux instalado possui duas ou mais interfaces de rede conectadas a um mesmo segmento de rede, podem ocorrer problemas com o mapeamento entre os endereços de camada 2 (ethernet) e camada 3 (IP). Isso ocorre pois o host responderá uma requisição ARP pelas duas interfaces de rede."

Mas isso só irá acontecer se a máquina possuir as 2 interfaces com o mesmo IP (como você demonstra com o arping).

Desculpe, mas não entendi muito bem onde você quis chegar com seu artigo.
Salvo alguns casos especiais onde duas interfaces possuem o mesmo IP, imagino que não esteja correto que mais do que uma interface possua o mesmo endereço de rede.

Sem interfaces com o mesmo endereço não consigo enxergar os problemas citados po
r você.

Obrigado,
Kon

Gustavo Rodrigues Ramos disse...

Caro Kon,

Talvez a frase "duas ou mais interfaces de rede conectadas a um mesmo segmento de rede" não esteja muito clara, portanto, vamos às explicações. Quando digo SEGMENTO de rede eu não quero dizer mesma rede (endereçamento de camada 3). Vamos utilizar o exemplo do arping para mostrar isso.

Imagine que exista em uma máquina linux duas interfaces: eth0 com endereço IP 10.10.20.67 e uma interface eth1 com endereço 200.122.122.2 e, ainda, por algum motivo estas duas interfaces estão conectadas em um mesmo switch - utilizando a mesma vlan. Neste cenário as duas interfaces estão conectadas à um mesmo domínio de broadcast (camada 2).

Se um outro host da rede, por exemplo o host 10.10.20.33 disparar um arping (é exatamente isso que acontece no exemplo), as requisições de arp serão recebidas e respondidas pelas duas interfaces - que possuem endereços MAC e IP distintos MAS estão no mesmo domínio de broadcast.

Se ainda não estiver claro, por favor avise para que a gente continue conversando...

Um abraço e obrigado pela pergunta! :-)

Gustavo.

Anônimo disse...

Grande Gustavo!

Tive a oportunidade e o desafio de ter que resolver um caso de ARP Flux no meu "lab" (sim, agora são mais de 7 Cobalts em casa rsrs).

As soluções que você propõe são válidas pro Kernel 2.2 e 2.4.

O Kernel 2.6 já endereça este assunto diretamente no /etc/sysctl.conf , basta adicionar :


# Deal with arp flux
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth1.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.eth0.arp_announce=2
net.ipv4.conf.eth1.arp_announce=2


Um forte abraço!
SAULO BRITTO

Anônimo disse...

Ah, um detalhe importante (provavelmente sou eu que estou fazendo ~lamba~):

- Isso funciona muito bem, mas o linux aparentente "elege" uma das interfaces como a principal do sistema. No meu caso, foi a eth0.
(A eth1 está desconectada e a eth2 é a 2a NIC com mesma subnet)

Até ai, confirmei que cada interface está respondendo pelo seu IP independente, maaaas... se você por exemplo retira o cabo da que subiu primeiro (no meu caso a eth0), automaticamente a eth2 deixa de responder.

Isso só se resolve se você entrar na máquina e der um ifconfig eth0 down !

Gustavo, onde estou errando? :-S

Abrcs!
SAULO GUÉGS

Guégs disse...

Hmmm!

A tabela de roteamento me respondeu!!!

[root@vendetta2 ~]# netstat -anr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth2
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0

Quem me responde como Default gateway? A eth0! ou seja, ela é o "caminho de volta", sempre!

Logo, se ela está link down, por onde os pacotes vão voltar? Só desablitando mesmo (ifconfig eth0 down) pra tabela de roteamento passar a usar a eth2!

Para isso, só achei uma saída, usar o "Policy Routing" e o iproute2...

Com os comandos abaixo:

ip route add 192.168.1.0/24 dev eth2 src 192.168.1.250 table admin
ip route add default via 192.168.1.1 dev eth2 table admin
ip rule add from 192.168.1.250/32 table admin
ip rule add to 192.168.1.250/32 table admin
ip route flush cache

Criei a regra que eu precisava pra eth2!


[root@vendetta2 ~]# ip rule show
0: from all lookup local
32764: from all to 192.168.1.250 lookup admin
32765: from 192.168.1.250 lookup admin
32766: from all lookup main
32767: from all lookup default
[root@vendetta2 ~]#

Assim meu amigo, acho que resolvi a encrenca... posso puxar qualquer cabo agora, que cada IP, mesmo da mesma subrede, e ligados num switch "porco" como o meu, vão continuar funcionando independentemente!

Abrcs, mande notícias "primo"!!!
Saulo