Windows 10 がルーティング テーブルを無視する

Windows 10 がルーティング テーブルを無視する

私は 2 つのネットワーク インターフェイスを備えた Windows 10 PC を持っています。これらのインターフェイスの 1 つは、ファイル サーバー、DNS、およびインターネット用のルーターが配置されているメイン LAN に接続されます。2 つ目のインターフェイスは、PLC と HMI を備えた小さな LAN です。これらは両方とも物理的には同じ LAN にありますが、サブネットが異なります (申し訳ありませんが、これは変更できません。私の管理外です)。

つまり、物理インターフェースが 2 つと論理インターフェースが 1 つあります: eth0: DHCP、172.16.xy、MASK 255.255.255.0、デフォルト gw 1​​72.16.xz eth1: static 192.168.1.158、MASK 255.255.255.0 static 192.168.19.158、MASK 255.255.255.0

HMIは192.168.19.135でアクセス可能です

ここで、HMI を再起動すると、再びアクセス可能になるかどうかを確認するために ping を開始します。これは約 30 秒後に発生するはずです。しかし、80 ~ 90 秒後にのみ、肯定的な ping 応答が返されます。

Ping wird ausgeführt für 192.168.19.135 mit 32 Bytes Daten:
Antwort von 192.168.19.158: Zielhost nicht erreichbar.
Zeitüberschreitung der Anforderung.
Zeitüberschreitung der Anforderung.
Zeitüberschreitung der Anforderung.

(ドイツ語のテキストで申し訳ありませんが、ここで見ている内容は明確であると思います) 最初の ping と 2 番目の ping では応答が異なります。

XP以降のWindowsは「ルーティングマジック」を実行し、より具体的なルートでターゲットに到達できない場合は、デフォルトルートからデータを送信するようになったようです。他のWindowsでも同様のことが行われているようです。この問題

私にとって本当の解決策ではない「解決策」をいくつか見つけました(詳細は後述)

  1. ping には、送信元アドレスを定義するための便利な「-S」パラメータがあります。そして、はい、これで問題は「解決」されます。HMI が起動している場合は、即座に応答が返されます。しかし、私はそのコマンドを PowerShell スクリプトで使用しており、「test-connection」のソース パラメータはまったく異なる意味を持っています。また、これをスクリプトで使用するため、ローカル IP が変更されるとすぐに失敗します。
  2. 私は eth0 を DHCP ではなく静的に設定し、デフォルト ルートを定義しませんでした。これも問題を「解決」しました (これが実際には解決策ではない理由は想像できると思います)
  3. 私はこれを理論的に検討しただけですが、PC、LAN、PLC と HMI を備えた分離された LAN の間に 3 つのインターフェイスを備えた Linux ベースのルーターをインストールし、すべてのルーティングを実行させることができます (これで問題は確実に解決されます。しかし、正直なところ、壊れた Windows ルーティングを回避するためだけに追加のコンピューターが必要なのでしょうか?)
  4. ´arp -d *´も役立つようですが、権限の昇格が必要です

異なるパラメータとメトリックを使用して静的ルートを追加してみました。変化なし! HMI の MAC を静的に追加しても、この MAC は変更される可能性があるため役に立ちません。

私の質問は次のとおりです:

  1. Windows でのこの動作の変更に関するドキュメントはありますか?
  2. 定義されたインターフェースをWindowsに強制的に使用させる方法はありますか

答え1

そこで、簡単な解決策が見つからなかったため、Microsoft が Windows のルーティングをひどく台無しにすることで引き起こした問題を、自分なりの方法でプログラムして回避することにしました。

私はPowerShellのコマンドレットtest-connectionの代わりに、パラメータ-Sを指定した従来のpingを使用しています。

私のコードの ping 部分は次のようになります。

$localIPs = (Get-NetIPConfiguration -InterfaceAlias "PLC").IPv4Address.IPAddress

# because this command returns a string, when the interface has a single IP-address but an array of strings if the interface has more than one address, we need to check for this
if ($localIPs.GetType().Name -eq "string") { # only a single IP
  $localIP = $localIPs
}
else { # more than one IP
  $localIP = $localIPs[0] # since it seems that windows does use the ip address as a synonym for the interface, it's not important which of the addresses of that interface we use. So we're just picking the first one
}

$pingcount = 180

do {
  ping $HMI4IP -n 1 -w 1000 -S $localIP | Out-Null # redirect the output of ping to /dev/null
  $pingreply = $?
  $pingcount = $pingcount - 1
}
until ($pingcount -eq '0' -or $pingreply)
if ($pingreply) {
  # code here
}
else {
  exit 1337 # return with an error code, we've not reached our target
}

このためには、PLC と HMI が接続されているインターフェイスの名前が "PLC" であることを確認する必要があります。次に、処理する必要がある文字列またはアドレスの配列 (インターフェイスに 1 つ以上のアドレスがあるかどうかによって異なります) としてアドレスを取得します (動的型付けへようこそ...)。次に、このデータを ping に渡すだけです (Test-Connection は、それ自体の利益のために賢くなりすぎるため)。$? では、最後のコマンドが成功を返した場合は true、失敗した場合は false を取得します。そのため、そこからの処理は簡単です。

私が見る限り、この動作とその対処方法についての Microsoft によるドキュメントは存在せず、これは非常に残念なことだと思います。

関連情報