sshnet / sshnet/SSH.NET

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

Aperta
#117 4 commenti 2 reazioni 1 assegnatario Vedi su GitHub

@drieseng ci sta già lavorando.

Dal 16/11/2016.

enhancement
Lingua principale
C#
Stelle
4.4k
Fork
993
Merge medio
9g 21h
PR unite (30g)
1

Descrizione

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.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.