-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TcpClient(hostName, port) constructor not handling IPv4-Mapped Addresses correctly #46724
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsThe System.Net.Sockets.TcpClient constructor fails to handle IPv4-Mapped Addresses correctly. I've tried this with Powershell 7.0.1 and .Net Core 3.1.4 Not working example:
Working example:
Version information:
Related RFC: https://tools.ietf.org/html/rfc4038#section-4.2 References: microsoft/dotnet#1214
|
Reproduced on both .NET Core 3.1 and .NET 5: TcpClient c1 = new TcpClient();
c1.Connect("::ffff:c163:9050", 443);
Console.WriteLine(c1.Connected); // True
TcpClient c2 = new TcpClient("::ffff:c163:9050", 443);
// System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10049): The requested address is not valid in its context. [::ffff:193.99.144.80]:443 |
Since dotnet/corefx#30036 the parameterless constructor is triggering
runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs Lines 432 to 440 in c2e098b
The runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs Lines 171 to 174 in c2e098b
I think this is a legacy logic inherited from the times before dual-stack sockets existed in .NET. Replacing it with a call to @agowa338 are you interested in a PR? |
@antonfirsov just to understand your last comment better , InitializeClientSocket() method call addition will fix out the issue correct ? |
Setting
We also need a new test case to validate the fix and establish functional coverage. However: |
I think we can look at it. I'm not sure what the behavior would be is OS does not support DualMode sockets. It seems like the current logic would still work but I'm not sure what the behavior would be with Socket.Connect(). It seems like we would always connect to only one address family. |
@wfurt: I'd expect behavior according to the RFC https://tools.ietf.org/html/rfc4038#section-4.2 I'm interested in this feature as I do not want to handle dual stack and just use the mapped addresses instead of the IPv4 ones, so that my applications can be fully IPv6 only while still being able to reach github and twitter... |
@agowa338 some context on @wfurt's concerns: Regardless, we need to pick a preference regarding the type of the sockets we use in AddressFamily-agnostic API-s, and stick to it for consistency. Currently our most visible Socket constructor is creating Dual Stack sockets in most environments, so we should prefer it everywhere IMO. If we are concerned about potential issues and side effects of using dual-stack, we should shift our preference globally, not just in one particular method. |
@antonfirsov Well, these workaround than provide issues to others. I'd suggest to follow the RFC. |
@agowa338 I am not sure which part of RFC you have in mind. Can you please be specific? Thanks! |
The RFC really talks what should happen on the wire. There is no doubt that it should go out as IPv4. The trickery in in TcpClient it self. I was wondering if we should do something similar to https://github.com/dotnet/corefx/pull/37194/files e.g. treat v4 mapped address as IPv4 instead of using dual-mode socket. Since that (and any other clean-up) is unrelated to the reported issue I put up PR to fix this issue. |
@wfurt: I thought the RFC is clear on that, look at the "stack" in section 4.2, the application (and the libraries should be IPv6). Therefore the application should think that it has a IPv6 only socket. But when the application is going to access a mapped address it will be translated transparently onto the wire while still looking like "normal" IPv6 traffic to the application. The beauty of IPv4 Mapped addresses is that it will (if implemented properly) free Layer 4 to 7 from checking if the Layer 3 connection is IPv4 or IPv6 allowing for a uniform IPv6 only code path while still being able to connect to IPv4 only endpoints (like github and twitter). Also just a quick reminder (even though windows doesn't support them itself), for historic reasons there are not just only IPv4 Mapped addresses, but also IPX and NSAP (https://tools.ietf.org/html/rfc1884#page-10 2.4.5-2.4.6), if you now consider an application attempting to make a connection to such addresses windows would pass it onto the wire according to the routing table. Than another device (a router) than could do the address conversion and connect the IPv6 network to an IPX or NSAP network. Therefore looking into the future if windows is going to drop the IPv4 stack, the same will happen here, therefore the IPv4Mapped addresses will no longer be considered special (as the stack got removed) and another device (router) will provide backwards compatibility and free developers and admins from dealing with legacy stuff and allowing to innovate. Tl;Dr: Applications should be able to be written in IPv6 only fashion utilizing the Mapped addresses to tell Layer 3 or a router (if the device doesn't have an IPv4 stack anymore and the special case gets removed) to perform the address translation and connect the two protocols with each other for compatibility reasons. |
The System.Net.Sockets.TcpClient constructor fails to handle IPv4-Mapped Addresses correctly.
However the Connect function does.
I've tried this with Powershell 7.0.1 and .Net Core 3.1.4
Not working example:
Working example:
Version information:
Related RFC: https://tools.ietf.org/html/rfc4038#section-4.2
References: microsoft/dotnet#1214
The text was updated successfully, but these errors were encountered: