SSH connection unable to try IPv4 if IPv6 fails

I ran across a puzzling problem when using an SSH storage connection. It appears that if the destination server has both IPv6 and IPv4 addresses, and the IPv6 connection (which was tried first) doesn’t work for some reason, Duplicati is not able to go on and try the IPv4 address. Instead, it just fails miserably:

System.Net.Sockets.SocketException (0x80004005): A connection attempt
failed because the connected party did not properly respond after a period
of time, or established connection failed because connected host has
failed to respond

or later:

System.Net.Sockets.SocketException (0x80004005): No connection could be
made because the target machine actively refused it

At first I couldn’t understand this at all, as the connection had worked for years already, and when I tried it with an ordinary SSH client (Putty in this case), it worked flawlessly. Only after a while and after scrutinizing the connection details, I noticed that Putty tried the IPv6 connection first as well, and after that failed, it immediately connected to the server’s IPv4 address. But Duplicati couldn’t switch to IPv4 and failed after only trying the IPv6 address. When testing the connection with the pure numerical IPv4 address, thus forcing an IPv4 connection, Duplicati could connect as well. This is not ideal though, since an IP address may change at some point.

I got this settled with the service provider, who accidentally had port 22 blocked at their IPv6 firewall :roll_eyes:. But I’m wondering if Duplicati should be able to try the other IP addresses that the domain name resolves to if any of them fails, just like common SSH clients do. Or perhaps this is a problem with the SSH library and should be dealed with SSH.NET?

Very good catch on the IP 4 vs 6 fallback fix.

I don’t know much about normal SSH protocol processes but hopefully @kenkendk will see this and have some input.

I noticed this issue at the Renci SshNet github. Looks like it’s related or even exactly the same problem, even though it specifically discusses about local tunneling:

If this is purely a shortcoming of SshNet and can’t be dealt with Duplicati, I may add a comment there that this problem affects all connections, not just local ones. The issue seems to be added to their milestone, so it will probably be corrected at some point, I hope.

Yep - that looks like what you’re describing. It’s pretty sad how poorly IPv6 is still handled - on my Windows boxes I almost always turn it off because of all the issues like this that keep popping up.

Whether or not it’s an actual SSH.Net bug, I don’t see why we couldn’t catch the SocketException error and if it was for an IPv6 address and an IPv4 one is available, try again with just IPv4.

But then I don’t know anything about that chuck of code so could certainly be wrong about that. And of course handling other people’s errors, while good for end users, often ends up a nightmare for developers…

Not sure about it, but doesn’t the decision for using IPv4 or IPv6 takes place in another layer than the Application Layer?

Also, DNS resolving is something that takes place outside your local system, the application just connects to what the DNS server answers to the DNS request. If your (IPv4) DNS server responds to a DNS lookup with an IPv6 address, the application will connect to that IPv6 address. If the connection fails, there is no option for the application to try IPv4, the DNS server will still respond with the IPv6 address to the same query.

Could be that I’m missing something, but I guess it’s not easy to implement this at the application level.

1 Like

If I correctly understand the issue I referred to above, SshNet only catches the first IP address from the array returned by the DNS server:

var addr = DnsAbstraction.GetHostAddresses(BoundHost)[0];

I’m not (much of) a programmer myself, but I guess that’s basically wherein the bug lies. So, you’re probably right in that Duplicati cannot possibly even know about any other IP addresses the DNS server may have returned, as the library doesn’t return any of them in its turn. And if that’s the case, it probably can only be fixed by SshNet.

1 Like