Duas NICs na mesma sub-rede, mas com redes diferentes?

5

Descrição

Isso é semelhante a esta questão , mas diferente:

O computador Linux possui duas NICs. eth0 é estatisticamente atribuído com um IP. O eth1 é assiend pelo pessoal no campo que poderia ser mesmo IP ou IP diferente. O plano é que eth0 e eth1 estejam em redes diferentes e nunca troquem ou conectem pacotes. E meu aplicativo Linux apenas escuta e aceita conexão em eth0 e eth1 e começa a enviar pacotes ao receber, mas nunca tenta iniciar nenhuma atividade.

Pergunta

Duas NICs podem ter IP na mesma sub-rede: 192.168.1.4 e 192.168.1.5? Como você pode ver, eth0 e eth1 estão atribuídos a estar na mesma sub-rede ( 255.255.255.0 ), mas eles não estão conectados e não devem estar conectados.

Nesse caso, quando o aplicativo atende em eth0 port 55555 , aceita conexão e retorna o pacote, a camada subjacente sabe que deve retornar a eth0? Ou será que vai tentar eth1 , já que o sistema operacional acha que está na mesma sub-rede? Há alguma coisa que eu precise fazer na tabela de roteamento para ter certeza de que essas duas NICs não estão na mesma sub-rede?

Devo evitar não apenas IPs semelhantes, mas também a mesma sub-rede neste caso?

Atualizar

E se PC0 e PC1 tiverem o mesmo IP?

PC0 (1.100) <-------> [eth0 (1.4)  My System eth1 (1.5)]<-------PC1(1.100)

Meu aplicativo precisa escutar na porta 55555 na eth0 e na eth1, e uma solicitação entra pela eth1, o SO sabe responder a eth1? Essa configuração causará um problema?

O caso de negócio é que estou construindo este sistema embarcado, e eu pré-defino o IP para eth0 e PC0 (PC0 também poderia ser DHCP). Mas meu cliente já tem uma rede no lado direito. E se eles tiverem um dispositivo que entre em conflito com o PC0 ou o eht0? Mesmo com o servidor DHCP no eth0, não há como excluir os IPs do lado direito ao atribuir o IP ao PC0. Se isso criar problemas, tenho muitas soluções. Mas eu gostaria de ouvir as opiniões dos colegas se isso é um problema.

Dois dos meus colegas acham que não é um problema. Minha opinião é que a camada IP não sabe qual interface usar para responder um pacote, mesmo usando um soquete (assuma a ligação do lado direito). Ele apenas selecionará um, independentemente de como configurarmos a tabela de roteamento.

    
por Splash 24.10.2015 / 18:10

1 resposta

5

Sim, você pode. Seu computador enviará pacotes de retorno para fora da interface que estiver associada à rota para a rede de destino.

Na probabilidade, a rede de destino está contida na rota padrão - 0.0.0.0/0, através do gateway padrão.

Não acredite em mim?
Vamos examinar:

[root@localhost ~]# ip address show label eth* | grep -v 'link\|val'
  2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
      inet 192.168.1.4/24 brd 192.168.1.255 scope global eth0
  3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
      inet 192.168.1.5/24 brd 192.168.1.255 scope global eth1

Duas interfaces, eth0 e eth1, com endereços IP & mascarar como em sua pergunta.

Configuração completa de inicialização:

[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
  DEVICE="eth0"
  NM_CONTROLLED="no"
  ONBOOT="yes"
  TYPE=Ethernet
  DEFROUTE=yes
  IPV4_FAILURE_FATAL=yes
  IPV6INIT=no
  Name="eth0"
  BOOTPROTO=none
  IPADDR=192.168.1.4
  NETMASK=255.255.255.0
  GATEWAY=192.168.1.1

[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1
  DEVICE="eth1"
  NM_CONTROLLED="no"
  ONBOOT="yes"
  TYPE=Ethernet
  DEFROUTE=yes
  IPV4_FAILURE_FATAL=yes
  IPV6INIT=no
  Name="eth1"
  BOOTPROTO=none
  IPADDR=192.168.1.5
  NETMASK=255.255.255.0
  GATEWAY=192.168.1.2

Observe que diferentes endereços de gateway são definidos para cada um - .1 e .2. Agora vamos ver a tabela de roteamento:

[root@localhost ~]# ip route list
  default via 192.168.1.2 dev eth0 
  192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.4 
  192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.5 

Parece que apenas uma rota padrão foi escolhida - a eth0 por qualquer motivo (não sei, mas eu suponho porque é a NIC com numeração mais baixa), mas usando o gateway .2. Talvez porque foi a última declaração de gateway? Inferno se eu sei.

Vamos ver o que o kernel considera a rota apropriada para um determinado destino de endereço público, originado de um endereço IP local:

[root@localhost ~]# ip route get to 8.8.8.8 from 192.168.1.4
  8.8.8.8 from 192.168.1.4 via 192.168.1.2 dev eth0 
      cache 

[root@localhost ~]# ip route get to 8.8.8.8 from 192.168.1.5
  8.8.8.8 from 192.168.1.5 via 192.168.1.2 dev eth0 
      cache 

Como seria de esperar de "default ... dev eth0", os pacotes destinados ao endereço IP público sairão da eth0.
Note que não importa qual é o endereço IP de origem.

Vamos conferir para ter certeza!
Vamos farejar eth0 e eth1 enquanto fazemos o ping de qualquer interface e endereço de origem.
Primeiro, execute ping usando o endereço IP da eth0 como a origem (.4):

[root@localhost ~]# tcpdump -ni eth0 'icmp' & tcpdump -ni eth1 'icmp' & ping -nc 3 -I 192.168.1.4 8.8.8.8 2>&1 > /dev/null ; sleep 4 ; pkill tcpdump
  [1] 2603
  [2] 2604
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
  23:30:30.347429 IP 8.8.8.8 > 192.168.1.4: ICMP echo reply, id 2605, seq 1, length 64
  23:30:31.331631 IP 192.168.1.4 > 8.8.8.8: ICMP echo request, id 2605, seq 2, length 64
  23:30:31.350134 IP 8.8.8.8 > 192.168.1.4: ICMP echo reply, id 2605, seq 2, length 64
  23:30:32.333378 IP 192.168.1.4 > 8.8.8.8: ICMP echo request, id 2605, seq 3, length 64
  23:30:32.350145 IP 8.8.8.8 > 192.168.1.4: ICMP echo reply, id 2605, seq 3, length 64

  5 packets captured
  5 packets received by filter
  0 packets dropped by kernel

  0 packets captured
  0 packets received by filter
  0 packets dropped by kernel
  [1]-  Done                    tcpdump -ni eth0 'icmp'
  [2]+  Done                    tcpdump -ni eth1 'icmp'

Parece bom - consistente com nossa tabela de roteamento!
Nada é visto na eth1 (o segundo resumo) como seria de esperar.
Agora vamos pingar da fonte .5 (pertencente a eth1):

[root@localhost ~]# tcpdump -ni eth0 'icmp' & tcpdump -ni eth1 'icmp' & ping -nc 3 -I 192.168.1.5 8.8.8.8 2>&1 > /dev/null ; sleep 4 ; pkill tcpdump
  [1] 2609
  [2] 2610
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
  23:32:31.284113 IP 8.8.8.8 > 192.168.1.5: ICMP echo reply, id 2611, seq 1, length 64
  23:32:32.269281 IP 192.168.1.5 > 8.8.8.8: ICMP echo request, id 2611, seq 2, length 64
  23:32:32.284493 IP 8.8.8.8 > 192.168.1.5: ICMP echo reply, id 2611, seq 2, length 64
  23:32:33.270735 IP 192.168.1.5 > 8.8.8.8: ICMP echo request, id 2611, seq 3, length 64
  23:32:33.286849 IP 8.8.8.8 > 192.168.1.5: ICMP echo reply, id 2611, seq 3, length 64

  5 packets captured
  5 packets received by filter
  0 packets dropped by kernel

  0 packets captured
  0 packets received by filter
  0 packets dropped by kernel
  [1]-  Done                    tcpdump -ni eth0 'icmp'
  [2]+  Done                    tcpdump -ni eth1 'icmp'

Veja como, embora o endereço de origem dos pings tenha sido definido como o endereço IP da eth1, os pacotes saíram da eth0?
Mas !, podemos especificar para ping de uma interface de origem em vez de um endereço de origem.
Especificar eth0 funciona como você esperaria (sucesso), mas algo interessante acontece se definirmos eth1 como a fonte:

[root@localhost ~]# tcpdump -ni eth0 'icmp' & tcpdump -ni eth1 'icmp' & ping -nc 3 -I eth1 8.8.8.8 2>&1 > /dev/null ; sleep 4 ; pkill tcpdump
  [1] 2751
  [2] 2752
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

... O que dá?
BEM, estamos apenas cheirando o tráfego ICMP. Como nenhuma rota padrão (ou rota mais específica para 8.8.8.8) existe na eth1, presume-se que o destino exista no mesmo domínio de broadcast.
Isso significa que ele tenta obter o endereço MAC do destino antes mesmo de construir o pacote a ser enviado. Se não conseguir um endereço MAC, ele não enviará o pacote:

[root@localhost ~]# tcpdump -eni eth1 'icmp or arp' & ping -nc 3 -I eth1 8.8.8.8 2>&1 > /dev/null ; sleep 10 ; pkill tcpdump 
  [5] 2759
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
  00:00:26.075685 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28
  00:00:26.075685 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28
  00:00:27.075945 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28
  00:00:27.075945 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28
  00:00:27.075945 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28
  00:00:28.077935 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28
  00:00:28.077935 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28
  00:00:28.077935 08:00:27:48:e7:5d > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 8.8.8.8 tell 192.168.1.5, length 28

(o servidor DNS do Google provavelmente não está na sua LAN, assim como não está no meu.)

Ok, ok, ok.
Agora, e se substituirmos a rota padrão de out eth0 para out eth1?
Devemos esperar que nossa situação de conectividade seja espelhada, certo? :

[root@localhost ~]# ip ro
  default via 192.168.1.2 dev eth0 
  192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.4 
  192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.5 

[root@localhost ~]# ping -nc 3 -I eth0 8.8.8.8
  PING 8.8.8.8 (8.8.8.8) from 192.168.1.4 eth0: 56(84) bytes of data.
  64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=17.5 ms
  64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=15.9 ms
  64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=15.5 ms
  --- 8.8.8.8 ping statistics ---
  3 packets transmitted, 3 received, 0% packet loss, time 2002ms
  rtt min/avg/max/mdev = 15.547/16.331/17.526/0.864 ms

[root@localhost ~]# ping -nc 3 -I eth1 8.8.8.8
  PING 8.8.8.8 (8.8.8.8) from 192.168.1.5 eth1: 56(84) bytes of data.
  From 192.168.1.5 icmp_seq=1 Destination Host Unreachable
  From 192.168.1.5 icmp_seq=2 Destination Host Unreachable
  From 192.168.1.5 icmp_seq=3 Destination Host Unreachable
  --- 8.8.8.8 ping statistics ---
  3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 1999ms
  pipe 3

[root@localhost ~]# ip route replace default via 192.168.1.1 dev eth1 

[root@localhost ~]# ip ro
  default via 192.168.1.1 dev eth1 
  192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.4 
  192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.5 

[root@localhost ~]# ping -nc 3 -I eth0 8.8.8.8
  PING 8.8.8.8 (8.8.8.8) from 192.168.1.4 eth0: 56(84) bytes of data.
  From 192.168.1.4 icmp_seq=1 Destination Host Unreachable
  From 192.168.1.4 icmp_seq=2 Destination Host Unreachable
  From 192.168.1.4 icmp_seq=3 Destination Host Unreachable
  --- 8.8.8.8 ping statistics ---
  3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 1999ms
  pipe 3

[root@localhost ~]# ping -nc 3 -I eth1 8.8.8.8
  PING 8.8.8.8 (8.8.8.8) from 192.168.1.5 eth1: 56(84) bytes of data.
  64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=14.7 ms
  64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=18.8 ms
  64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=21.0 ms
  --- 8.8.8.8 ping statistics ---
  3 packets transmitted, 3 received, 0% packet loss, time 2003ms
  rtt min/avg/max/mdev = 14.760/18.216/21.010/2.596 ms

E assim acontece! Agora eth0 não pode alcançar nada além de eth1.

Supondo que você quer que as duas interfaces "apenas funcionem", vamos seguir o caminho da loucura que equilibra a carga ...:

[root@localhost ~]# ip route delete default

[root@localhost ~]# ip route add default scope global nexthop via 192.168.1.2 dev eth0 weight 1 nexthop via 192.168.1.1 dev eth1 weight 1

[root@localhost ~]# ip ro
  default 
          nexthop via 192.168.1.2  dev eth0 weight 1
          nexthop via 192.168.1.1  dev eth1 weight 1
  192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.4 
  192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.5 

Mas isso funciona?

[root@localhost ~]# ping -nc 3 -I eth0 8.8.8.8
  PING 8.8.8.8 (8.8.8.8) from 192.168.1.4 eth0: 56(84) bytes of data.
  64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=17.9 ms
  64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=16.2 ms
  64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=17.4 ms
  --- 8.8.8.8 ping statistics ---
  3 packets transmitted, 3 received, 0% packet loss, time 2003ms
  rtt min/avg/max/mdev = 16.281/17.238/17.986/0.727 ms

[root@localhost ~]# ping -nc 3 -I eth1 8.8.8.8
  PING 8.8.8.8 (8.8.8.8) from 192.168.1.5 eth1: 56(84) bytes of data.
  64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=16.6 ms
  64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=17.3 ms
  64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=26.0 ms
  --- 8.8.8.8 ping statistics ---
  3 packets transmitted, 3 received, 0% packet loss, time 2003ms
  rtt min/avg/max/mdev = 16.612/20.025/26.091/4.300 ms

Huzzah!

... No entanto, até estou um pouco surpreso.
Sua própria milhagem pode variar. Eu aconselharia contra essa loucura.

Nos meus testes, as coisas ficam complicadas quando se tenta alcançar destinos na sub-rede local.
Isso ocorre porque no uso normal do sistema (ou seja, não especificando uma interface de saída explicitamente), uma interface é escolhida.
Por exemplo, se eu pingar um host inexistente (.17) na sub-rede, as solicitações ARP serão enviadas somente eth0.
Então, em teoria, se o host existisse na eth1, o ARP funcionaria?
Provavelmente não:

[root@localhost ~]# ping 192.168.1.17
  PING 192.168.1.17 (192.168.1.17) 56(84) bytes of data.
  From 192.168.1.4 icmp_seq=1 Destination Host Unreachable
  From 192.168.1.4 icmp_seq=2 Destination Host Unreachable
  From 192.168.1.4 icmp_seq=3 Destination Host Unreachable
  ...

[root@localhost ~]# tcpdump -eni eth0 'arp'
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
  00:25:29.167575 08:00:27:f6:8f:c2 > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.17 tell 192.168.1.4, length 28
  00:25:30.168001 08:00:27:f6:8f:c2 > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.17 tell 192.168.1.4, length 28
  00:25:31.169967 08:00:27:f6:8f:c2 > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.17 tell 192.168.1.4, length 28
  ...

[root@localhost ~]# tcpdump -eni eth1 'arp'
  tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes



  ^C
  0 packets captured
  0 packets received by filter
  0 packets dropped by kernel

Felicidades.

    
por 26.10.2015 / 05:35