Skip to content
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

Unexpected behavior (a.k.a. bug) on local tunnel #117

Open
fidergo-stephane-gourichon opened this issue Nov 16, 2016 · 4 comments
Open

Unexpected behavior (a.k.a. bug) on local tunnel #117

fidergo-stephane-gourichon opened this issue Nov 16, 2016 · 4 comments
Assignees

Comments

@fidergo-stephane-gourichon

Bug as seen on the net

People try to use local tunnels and that fails like on:

Usually the user has found a workaround but not clarified what happens.

This bug report clarifies and suggests an improvements.

How to reproduce

OS is Win7 here but probably happens with other configurations.

From c# - Creating a forwarded port within an SSH tunnel - Stack Overflow:

  PrivateKeyFile file = new PrivateKeyFile(@" .. path to private key .. ");
  using (var client = new SshClient(" .. remote server .. ", "ubuntu", file))
  {

      client.Connect();
      var port = new ForwardedPortLocal(3306, "localhost", 3306);
      client.AddForwardedPort(port);
      port.Start();

      Thread.Sleep(10000000);

      client.Disconnect();
  }

Expected behaviour

OS accepts connections to any local IP (127.0.0.1, ::1), port 3306.

Observed behaviour

OS does not accept connections to local IP (127.0.0.1) (not sure if tester ::1), port 3306.

It does accept connection to a particular IPV6 address, though.

Technical analysis: what's happening

Expected behavior

When opening a local tunnel without specifying IP to bind, OpenSSH implementation binds to all local IPs. Here's an example on Linux:

ssh somehost -L 1234:127.0.0.1:1234

On another terminal:

netstat -n  -at | grep -i listen | grep 1234

tcp        0      0 127.0.0.1:1234          0.0.0.0:*               LISTEN     
tcp6       0      0 ::1:1234                :::*                    LISTEN     

Observed behavior

Instead, SSH.NET does this (from SSH.NET/ForwardedPortLocal.NET.cs at 5f6c3b0bc7a5916d92467931ecacdfc0917f83d7 · sshnet/SSH.NET):

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

which on local machine provides IP addresses provided by DHCP server, not 127.0.0.1 or ::1.

Taking only the first result from array returned by DnsAbstraction.GetHostAddresses(BoundHost) is code smell.

Suggested change

(1) Make a foreach loop that binds to all adresses returned by DnsAbstraction.GetHostAddresses(BoundHost)
(2) if String.IsNullOrEmpty(BoundHost), use something like IPAddress.Loopback (or something ensuring IPv4 and IPv6 compatibility).

Though I'm not using that at the moment, can SSH.NET bind to "any IP" (pseudo-address '*') like OpenSSH does:

ssh somehost -L *:localport:remotehost:remoteport

That suggests : (3) if ("*".Equals(BoundHost)) { ... }

Conclusion

IMHO such a change would make SSH.NET more inline with expected behavior and avoid much frustration for people.

Thank you for your attention.

@drieseng drieseng self-assigned this Nov 16, 2016
@drieseng
Copy link
Member

Thanks for the great bug report.
I'll look into asap, but for now I want to use the little time that I have to prepare for the next release.

@corelgott
Copy link

+1

1 similar comment
@gokhansengun
Copy link

+1

@drieseng drieseng added this to the 2017.0.0 milestone Aug 17, 2017
@ingul-buz
Copy link

It seems to me that (the basic reason for) this issue can also have an influence on all connections, not just local ones. If the first IP address returned within the array from the DNS server doesn't work for some reason, SSH.NET is unable to connect to any other address possibly returned within the same array, just because only the first one has been taken hold of. E.g. in Session.cs:

var ipAddress = DnsAbstraction.GetHostAddresses(host)[0];

I ran across this when an SSH server I am using had port 22 accidentally blocked at its IPv6 firewall. I suspect that since the IPv6 address was the only one returned from the DnsAbstraction.GetHostAddresses call, the connection just failed. It was difficult to find out the reason, as common SSH clients (e.g. Putty) could connect succesfully at the same time. I got a hunch of what's happening only after realising Putty tried the IPv6 address first as well, and after that one failed it immediately connected to the parallel IPv4 address of the server.

AFAICS the change @fidergo-stephane-gourichon suggested looks good, but it should be expanded to apply to all connections, not just local ones.

@drieseng drieseng removed this from the 2017.0.0 milestone Mar 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants