Reputation: 45
Not a powershell expert but doing something to check for IPv6 connectivity as part of a small project for Windows 10. This (code below) is what I'm using, i'd like to stay with it if possible because its fast and does not involve a web site somewhere to return the public view IPv6 address. The remote IPv6 address used (2001:4860:4860::8888) is the Google public IPv6 DNS. I got the idea from some code in which the Google Ipv6 DNS server is used to check for global Ipv6 connectivity in Chrome from this > 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
The problem with it is that even with the IPv6 disabled on the interface adapter and Teredo disabled it still returns 'True' (that its connected) when it should not be connected. I want it to return 'False' when there is no IPv6 enabled on the interface adapter or IPv6 is blocked at firewall or via something else. What am I doing wrong with this?
Upvotes: 2
Views: 213
Reputation: 8456
With another look at the chromium code we can see what it's doing.
TL;DR, it checks whether the machine actually has a valid non-local, non-tunneled, ipv6 address assigned.
The critical function (or method, it's C++) is bool IsGloballyReachable()
It starts with some boiler plate with the function header, a tracing function, and the creation of a UDP socket pointer
// 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()
)
);
Then comes the first test: can we connect to the given address?
int rv = socket->Connect(IPEndPoint(dest, 53));
if (rv != OK)
return false;
If this fails, that's what we return.
This is where the powershell code stops
But we aren't done yet...
The next test: Can we get the local address for the socket?
IPEndPoint endpoint;
rv = socket->GetLocalAddress(&endpoint);
if (rv != OK)
return false;
If that works, we start checking the actual address,
DCHECK_EQ(ADDRESS_FAMILY_IPV6, endpoint.GetFamily());
const IPAddress& address = endpoint.address();
We first eliminate link_local addresses:
bool is_link_local =
(address.bytes()[0] == 0xFE) && ((address.bytes()[1] & 0xC0) == 0x80);
if (is_link_local)
return false;
And we eliminate addresses with a teredo prefix
const uint8_t kTeredoPrefix[] = {0x20, 0x01, 0, 0};
if (IPAddressStartsWith(address, kTeredoPrefix))
return false;
Anything else is assumed to be a valid local ipv6 address in the global address space:
return true;
}
Does this actually test global connectivity? No. As you aren't actually sending any packets around this will not see if there's any firewall that might block your traffic. But it validates that at least one network interface has a valid non-local ipv6 address.
To replicate this test you would need to check that the network interface you connect through is actually an ipv6 address.
Upvotes: 2
Reputation: 5369
UDP protocol is connectionless. So, "connected" state has no practical meaning for it, unlike TCP (and you receive just hardcoded stub value, I'm suspecting). Then, you can try to switch to TCP version of DNS request from very beginning (despite RFC recommends to use TCP DNS only if the UDP response contains "truncated" flag).
Upvotes: 3