web-dev-qa-db-ja.com

同じサブネット上にあるがネットワークが異なる2つのNIC?

説明

これは この質問 に似ていますが、異なります:

Linuxコンピュータには2つのNICがあります。 eth0には静的にIPが割り当てられます。 eth1は、同じIPまたは異なるIPである可能性のあるフィールドの担当者によって支援されます。計画では、eth0eth1を異なるネットワーク上に配置し、パケットを交換したりブリッジしたりしないでください。そして、私のLinuxアプリケーションは、eth0eth1でのみ接続をリッスンして受け入れ、受信時にパケットの送信を開始しますが、アクティビティを開始しようとはしません。

質問

2つのNICは同じサブネットにIPを持つことができます:192.168.1.4と192.168.1.5?ご覧のとおり、eth0eth1は同じサブネットに割り当てられています(255.255.255.0)しかし、それらは接続されておらず、接続されているはずではありません。

この場合、アプリケーションがeth0ポート55555でリッスンし、接続を受け入れてパケットを返すと、基盤となるレイヤーはeth0に戻る必要があることを認識していますか?または、OSが同じサブネット上にあると見なすため、eth1を試す可能性がありますか?これらの2つのNICが実際に同じサブネット上にあると見なされないようにするために、ルーティングテーブルに対して行う必要があることはありますか?

この場合、類似したIPだけでなく、同じサブネットも避ける必要がありますか?

更新

PC0とPC1のIPが同じ場合はどうなりますか?

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

私のアプリケーションはeth0とeth1のポート55555でリッスンする必要があり、リクエストはeth1を介して受信され、OSはeth1を介して応答することを認識できますか?この構成は問題を引き起こしますか?

ビジネスケースは、私がこの組み込みシステムを構築していて、eth0とPC0のIPを事前に定義していることです(PC0はDHCPでもかまいません)。しかし、私の顧客はすでに右側にネットワークを持っています。 PC0またはeht0のいずれかと競合するデバイスがある場合はどうなりますか? eth0にDHCPサーバーがある場合でも、PC0にIPを割り当てるときに右側のIPを除外する方法はありません。これが問題を引き起こす場合、私には多くの解決策があります。でも、それが問題なのか、仲間の意見を聞きたいです。

私の同僚の2人は、それは問題ではないと考えています。私の意見では、IP層は、ソケットを使用してもパケットに応答するために使用するインターフェイスを認識していません(右側にバインドすると仮定します)。ルーティングテーブルをどのように設定しても、1つだけが選択されます。

5
Splash

はい、できます。コンピュータは、宛先ネットワークへのルートに関連付けられているインターフェイスからリターンパケットを送信します。

おそらく、宛先ネットワークは、デフォルトゲートウェイを介して、デフォルトルート(0.0.0.0/0)内に含まれています。

私を信じないでください?
調べてみましょう:

[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

質問のようにIPアドレスとマスクを備えた2つのインターフェースeth0とeth1。

完全なスタートアップ構成:

[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

.1と.2ごとに異なるゲートウェイアドレスが設定されていることに注意してください。
次に、ルーティングテーブルを見てみましょう。

[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 

なんらかの理由でデフォルトルートが1つだけ選択されているようです(わかりませんが、NICの番号が小さいためだと思います)が、ゲートウェイを使用しています。おそらく後者のゲートウェイステートメントだったからですか?私が知っているなら地獄。

カーネルが、いずれかのローカルIPアドレスから供給された特定のパブリックアドレス宛先の適切なルートをどのように考慮するかを見てみましょう。

[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 

「default ... dev eth0」から予想されるように、パブリックIPアドレス宛てのパケットはeth0を終了します。
送信元IPアドレスが何であるかは問題ではないことに注意してください。

でも確認してみましょう!
いずれかのインターフェイスといずれかの送信元アドレスからpingを実行している間、eth0とeth1の両方をスニッフィングします。
まず、eth0のIPアドレスを送信元として使用してpingを実行します(.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'

見栄えが良い-ルーティングテーブルと一致しています!
予想どおり、eth1(2番目の要約)には何も表示されません。
ソース.5(eth1に属する)からpingを実行しましょう:

[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'

Pingの送信元アドレスがeth1のIPアドレスに設定されていても、パケットがeth0を離れた方法を確認してください。
ただし、送信元アドレスではなく送信元インターフェイスからpingを実行するように指定できます。
eth0の指定は期待どおりに機能しますが(成功)、eth1をソースとして設定すると何か面白いことが起こります。

[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

...何が得られますか?
まあ、私たちはICMPトラフィックをスニッフィングしているだけです。 eth1以外にはデフォルトルート(または8.8.8.8へのより具体的なルート)が存在しないため、宛先は同じブロードキャストドメインに存在すると見なされます。
つまり、送信するパケットを作成する前に、宛先のMACアドレスを取得しようとします。 MACアドレスを取得できない場合、パケットは送信されません。

[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

(GoogleのDNSサーバーは、私のLAN上にないのと同じように、おそらくLAN上にありません。)

大丈夫、大丈夫、大丈夫。
デフォルトルートをouteth0からouteth1に置き換えるとどうなりますか?
接続状況がミラーリングされることを期待する必要がありますよね? :

[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

そしてそうです!これで、eth0はeth1以外には到達できません。

両方のインターフェースを「正しく機能」させたいと仮定して、負荷分散である狂気の道を進みましょう...:

[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 

しかし、それは機能しますか?

[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

万歳!

...でも、私でも少し驚いています。
あなた自身のマイレージは異なる場合があります。私はこの狂気に反対することをお勧めします。

私のテストでは、ローカルサブネット上の宛先に到達しようとすると、状況が不安定になります。
これは、通常のシステム使用(つまり、出口インターフェースを明示的に指定しない)では、1つのインターフェースが選択されるためです。
たとえば、サブネット上に存在しないホスト(.17)にpingを実行すると、ARP要求はeth0からのみ送信されます。
理論的には、ホストdidがeth1の外に存在する場合、ARPは機能しますか?
そうではないようです:

[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

乾杯。

5
robut