检测Windows网络连接是否被劫持

在现代网络环境中,Captive Portal(劫持门户)是一种常见的技术,用于在用户连接到网络之前强制他们访问特定的登录页面。这在公共Wi-Fi热点、学校和企业网络中尤为常见。然而,有时可能需要检测网络连接是否被劫持,以便采取相应的措施。本文将介绍如何使用Windows Network List Manager API来实现这一功能。

微软开发者网络(MSDN)提供了一个方便的API,用于查询网络连接属性。通过NLM_INTERNET_CONNECTIVITY标志,可以获取IPV4和IPV6网络协议的额外属性,例如NLM_INTERNET_CONNECTIVITY_WEBHIJACK,这是想要找到的属性,以识别网络连接是否位于Captive Portal后面。

使用代码

总体策略是使用Network List Manager来枚举已连接的连接。然后,通过INetwork接口查询IPropertyBag,寻找所需的NLM_INTERNET_CONNECTIVITY标志。正如MSDN文档所建议的:“这些连接标志可以通过查询INetwork或INetworkConnection接口的IPropertyBag接口的NA_InternetConnectivityV4或NA_InternetConnectivityV6属性来检索。”首先尝试了INetworkConnection接口来查询IPropertyBag,但在检索标志时失败了。所以转而使用INetwork接口(其余代码保持不变),它就工作了。没有介意调查为什么INetworkConnection失败了。然而,如果遇到了类似的问题,认为应该指出这一点。

最后,检查网络连接标志,查看NLM_INTERNET_CONNECTIVITY_WEBHIJACK标志是否已设置。如果这个标志对于NLM_CONNECTIVITY_IPV6_INTERNET或NLM_CONNECTIVITY_IPV4_INTERNET已设置,那么就在IPV6或IPV4的Captive Portal连接下。

代码示例

以下是执行上述逻辑并设置布尔变量以检测Captive Portal是否被检测到的代码片段:

bool fCaptivePortalDetected = false; // 初始化COM。 if (SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) { // 声明INetworkListManager指针 INetworkListManager* pNetworkListManager; // 创建CLSID_NetworkListManger COM对象的实例 if (SUCCEEDED(CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_INetworkListManager, (LPVOID*)&pNetworkListManager))) { // 声明IEnumNetworkConnections指针 IEnumNetworks* pEnum; // 调用INetworkListManager接口的GetNetworks if (SUCCEEDED(pNetworkListManager->GetNetworks( NLM_ENUM_NETWORK_CONNECTED, &pEnum)) && pEnum != NULL) { INetwork *pINetwork; HRESULT hr = pEnum->Next(1, &pINetwork, nullptr); while (hr == S_OK) { if (pINetwork != NULL) { IPropertyBag *pNetworkPropertyBag; HRESULT hrQueryInterface = pINetwork->QueryInterface( IID_IPropertyBag, (LPVOID*)&pNetworkPropertyBag); if (SUCCEEDED(hrQueryInterface) && pNetworkPropertyBag != nullptr) { NLM_CONNECTIVITY networkConnectivity; VARIANT variantConnectivity; if (SUCCEEDED(pINetwork->GetConnectivity(&networkConnectivity))) { if ((networkConnectivity & NLM_CONNECTIVITY_IPV4_INTERNET) == NLM_CONNECTIVITY_IPV4_INTERNET) { VariantInit(&variantConnectivity); if (SUCCEEDED(pNetworkPropertyBag->Read(NA_InternetConnectivityV4, &variantConnectivity, nullptr)) && (V_UINT(&variantConnectivity) & NLM_INTERNET_CONNECTIVITY_WEBHIJACK) == NLM_INTERNET_CONNECTIVITY_WEBHIJACK) { fCaptivePortalDetected = true; } auto t = V_UINT(&variantConnectivity); VariantClear(&variantConnectivity); } if (!fCaptivePortalDetected && (networkConnectivity & NLM_CONNECTIVITY_IPV6_INTERNET) == NLM_CONNECTIVITY_IPV6_INTERNET) { VariantInit(&variantConnectivity); if (SUCCEEDED(pNetworkPropertyBag->Read(NA_InternetConnectivityV6, &variantConnectivity, nullptr)) && (V_UINT(&variantConnectivity) & NLM_INTERNET_CONNECTIVITY_WEBHIJACK) == NLM_INTERNET_CONNECTIVITY_WEBHIJACK) { fCaptivePortalDetected = true; } VariantClear(&variantConnectivity); } } } pINetwork->Release(); } if (fCaptivePortalDetected) break; hr = pEnum->Next(1, &pINetwork, nullptr); } } } } // 反初始化COM。 // (这应该在应用程序关闭时调用。) CoUninitialize();
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485