不是PowerShell专家,而是做一些事情来检查IPv6连接,作为Windows 10小项目的一部分。这个(下面的代码)是我正在使用的,我想留下它,如果可能因为它速度快而且不涉及某个网站返回公共视图的IPv6地址。使用的远程IPv6地址(2001:4860:4860 :: 8888)是Google公共IPv6 DNS。我从一些代码中得到了这个想法,其中使用Google Ipv6 DNS服务器从这个>检查Chrome中的全局Ipv6连接。 https://codereview.chromium.org/141023002<
$Saddrf = [System.Net.Sockets.AddressFamily]::InterNetworkV6;
$Stypeg = [System.Net.Sockets.SocketType]::Dgram ;
$Ptypeg = [System.Net.Sockets.ProtocolType]::UDP ;
$Sockg = New-Object System.Net.Sockets.Socket($Saddrf, $Stypeg, $Ptypeg);
$Sockg.Connect('2001:4860:4860::8888', 53); $cnx = $Sockg.Connected;
write $cnx
问题在于,即使在接口适配器上禁用了IPv6并禁用了Teredo,它仍然会返回' True' (它已连接)何时不应连接。我希望它返回' False'当接口适配器上未启用IPv6或IPv6在防火墙或其他情况下被阻止时。我做错了什么?
答案 0 :(得分:3)
UDP协议是无连接的。所以,"连接"与TCP不同,状态对它没有实际意义(你只收到硬编码的存根值,我怀疑)。然后,您可以尝试从一开始就切换到TCP版本的DNS请求(尽管RFC建议仅在UDP响应包含"截断"标志时才使用TCP DNS。)
答案 1 :(得分:2)
再看看chromium code我们可以看到它正在做什么。
TL; DR,它检查机器是否实际上分配了有效的非本地,非隧道,ipv6地址。
关键功能(或方法,它是C ++)是bool IsGloballyReachable()
它以一些带有函数头,跟踪函数和创建UDP套接字指针的样板开始
// Attempts to connect a UDP socket to |dest|:53.
bool IsGloballyReachable(const IPAddress& dest,
const NetLogWithSource& net_log) {
// TODO(eroman): Remove ScopedTracker below once crbug.com/455942 is fixed.
tracked_objects::ScopedTracker tracking_profile_1(
FROM_HERE_WITH_EXPLICIT_FUNCTION("455942 IsGloballyReachable")
);
std::unique_ptr<DatagramClientSocket> socket(
ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
net_log.net_log(),
net_log.source()
)
);
然后是第一个测试:我们可以连接到给定的地址吗?
int rv = socket->Connect(IPEndPoint(dest, 53));
if (rv != OK)
return false;
如果失败,那就是我们的回报。
这是powershell代码停止的地方
但我们还没有完成......
下一个测试:我们可以获得套接字的本地地址吗?
IPEndPoint endpoint;
rv = socket->GetLocalAddress(&endpoint);
if (rv != OK)
return false;
如果可行,我们开始检查实际地址
DCHECK_EQ(ADDRESS_FAMILY_IPV6, endpoint.GetFamily());
const IPAddress& address = endpoint.address();
我们首先删除了link_local地址:
bool is_link_local =
(address.bytes()[0] == 0xFE) && ((address.bytes()[1] & 0xC0) == 0x80);
if (is_link_local)
return false;
我们用teredo前缀消除地址
const uint8_t kTeredoPrefix[] = {0x20, 0x01, 0, 0};
if (IPAddressStartsWith(address, kTeredoPrefix))
return false;
假设其他任何内容都是全局地址空间中有效的本地ipv6地址:
return true;
}
这是否真的测试全球连接?不会。由于您实际上并未发送任何数据包,因此无法查看是否存在可能会阻止您的流量的防火墙。但它验证至少有一个网络接口具有有效的非本地ipv6地址。
要复制此测试,您需要检查连接的网络接口实际上是否为ipv6地址。