簡體   English   中英

IP地址是否與本地計算機位於同一子網上(支持IPv6)

[英]Is IP address on the same subnet as the local machine (with IPv6 support)

有沒有人有一些代碼可以確定IP地址(IPv4或IPv6)是否與運行應用程序的計算機位於同一子網上? 我已經看過很多用IPv4做的代碼示例,但我找不到任何支持IPv6的代碼。

編輯:

我不確定我是否理解v4和v6之間的所有差異,所以這里有一點我的問題。 我有一個為Internet客戶端和Intranet客戶端提供服務的應用程序,也就是說有些客戶端與服務器位於同一物理網絡上。 所以有時客戶端之間有路由器,有時候沒有路由器。 使用IPv4,我可以通過檢查服務器IP地址和子網的客戶端IP地址來確定這一點,這樣如果我的服務器的IP和子網掩碼分別是:

192.168.123.15 255.255.255.0

並且服務器從192.168.123.100接收客戶端請求我知道客戶端和服務器之間沒有路由器。 但是,如果服務器收到來自192.168.1.100或67.7.23.4的客戶端請求,我知道這些客戶端和服務器之間存在路由器。 在.Net中,我可以收集客戶端和服務器IP地址(v4和v6)但我找不到IPv6子網掩碼。

有沒有辦法在.Net中收集這些信息,還是我誤解了IPv4和IPv6之間有什么區別?

編輯x2:

我在MS連接站點上發布了這個,看看它們是否正在處理,或者是否有原因他們沒有將IPv6Mask屬性添加到UnicastIPAddressInformation類。

https://connect.microsoft.com/VisualStudio/feedback/details/643031/unicastipaddressinformation-class-has-no-ipv6mask-property

我也在同一時間在MSDN論壇上發布了同樣的問題。 1800多個觀點,而不是一個回復。 猜猜我不是唯一一個對此感到好奇的人。

http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/dd30e161-9be5-4d70-97c0-22e2756ce953

它看起來不像框架有辦法做到這一點。 最准確的方法是進行路由查找,但我沒有看到在C#中做到這一點的好方法。 (在Linux下,我會執行/sbin/ip -6 route get <ipv6-addr>並查看返回的路由。)您必須在Windows中找到本機調用才能執行此操作。 我沒有看到命令行應用程序。

最好的方法可能是解析netsh interface ipv6 show route verbose的輸出。 您可以查找任何非/ 128前綴並對其進行最長前綴匹配。 (好吧,如果你點擊了/ 128,那就是分配給盒子的地址)

您還可以檢查鄰居表。 netsh interface ipv6 show neighbors ),但如果您最近沒有與該主機通信,則可能不包含您要查找的條目。

您需要考慮的其他潛在問題:

  • 鏈接本地地址(fe80 :: / 10) (以及多播,環回和未指定 - 表中的所有內容)
  • 事實上,在IPv6中,分配的地址並不意味着鏈接前綴。 前綴表是分開的。 目前還不清楚如何在Windows下測試,但netsh interface ipv6 show siteprefixes可能有所幫助。 看起來Windows可能實際上更像IPv4而不是標准期望。

編輯 :這聽起來像檢查鄰居表將是你做這個的阻力最小的路徑; 如果您正在接受來自Intranet的連接,然后轉身並檢查鄰居表,則可以合理地確保如果鄰居是本地的,則它將存在於表中。 如果檢查鄰居表,請小心 ,只查看LAN接口的鄰居表。 (ISATAP接口,默認安裝在許多Windows系統上,將整個IPv4 Internet公開為鏈接本地“子網”。)

同樣,IPv6地址沒有“網絡掩碼”的概念,因為鏈接前綴表與地址分配是分開的。 但是 ,如果你有一台服務器坐在某個地方你可能已經99%確定它在/ 64上 (雖然你必須要小心;如果它本身就是一個隧道端點,有時我看到為6in4隧道分配了更長的前綴)所以一個快速而骯臟的算法將是:

  • 忽略前64位為0的所有地址(本地環回)
  • 忽略匹配ff00 :: / 8(多播)的所有地址
  • 如果地址匹配fe80 :: / 10,則它是接口本地 小心這一點,因為如果你啟用了ISATAP接口,“link-local”意味着“自動隧道到整個IPv4互聯網”! (不好。)因此,除非您確定它們來自LAN接口,否則最好不要信任鏈接本地地址。 (他們不能被路由)
  • (現在是復雜的部分)確定地址是否是鄰居。 (鄰居查找)hack-and-slash解決方案是檢查系統上配置的所有IPv6地址(通過無狀態地址自動配置,DHCPv6或靜態自動配置,如果可以確定)並檢查前64位。 在服務器上 (假設沒有時髦的隧道配置有非/ 64前綴),在極少數情況下這將是一個錯誤,因為 - 再次 - 您無法確定該地址是否真的在鏈接上,除非您檢查 -鏈接前綴表。 (Windows沒有概念;它似乎存儲在路由表中。)大多數可以配置為在以太網接口上發送路由器通告的網絡設備將始終通告/ 64前綴。 如果您可以檢查數據包是否在LAN接口上進入,那么這將是一個錯誤的可能性更小。

編輯2

我編寫了一些代碼來解析IPv6路由表並在此處發布。 它並沒有解決這個問題中提出的難題,但它是朝着正確方向邁出的一步。

IPv6中IPv4網絡掩碼的道德等價物稱為前綴長度 (實際上,我們也喜歡在IPv4中討論前綴長度而不是網絡掩碼,但是有些人還沒有得到備忘錄。)

IPv6中沒有提出IPv4的另一個缺點是默認路由器通過回答來自主機的路由器請求查詢來宣傳它們在鏈路上的存在。 主機保留了他們以這種方式找到的所有默認路由器的列表以及它們的有效和首選生命周期。 路由器還可以通告它們作為默認路由器的零個,一個或多個前綴,並且主機保持這些前綴的列表以及它們的相關路由器以及它們各自的有效和優選生存期。

每個前綴在廣告A和L中有兩個輔助位,當它們被添加到前綴列表時由主機合並。 A = 1位表示是否允許主機自動配置具有該前綴的接口地址,而A = 0表示主機需要通過DHCPv6或手動獲取具有該前綴的地址。 L = 1比特表示前綴是“在鏈路上”,並且主機可以使用鄰居發現(ARP等效的ARP)直接通過網絡發送,而L = 0表示前綴是“關閉鏈路”,並且主機需要將該前綴的所有流量發送到默認路由器。

簡而言之:如果你想知道IPv6地址是“在鏈接上”那么你必須走IPv6前綴列​​表並將每個地址與地址進行比較,並查看L位以確保它是一個on-link字首。 唉,我只知道查看前綴列表的BSD系統方式,即sysctl(ICMPV6CTL_ND6_PRLIST, ...) 真的不確定MSFT為C#開發人員提供了什么。

是的,我意識到這不是一個完整的答案。 唉。

我一直在尋找wmi文檔試圖找到ipv6前綴,我也在努力找到它。 但是,我有IPv4的工作代碼。

我認為您可以放心地假設該網段的前綴為/ 64。 如果這樣做,您可以只比較每個地址的前8個字節。 通常,運行應用程序的單個本地網絡將是/ 64,即使只使用2個,即使點對點鏈接也經常被賦予完整的/ 64范圍。

在99%的情況下,這很簡單。 IPv6中的所有子網都是/ 64前綴,因此如果前綴的最左邊64位相同,則它們位於同一子網中。

現在確實有些人正在做一些奇怪的事情,並制作具有更長前綴的子網,但其中大部分是處​​理點對點電路,他們使用/ 126對兩個端點進行編號,然后保留包含/ 126。 由於不涉及任何服務器,因此應用程序永遠不會遇到這種情況。

沒有充分的理由支持/ 64以外的子網大小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM