More .NET components

SSH tunelling (port forwarding)

SSH tunneling (port forwarding) is a useful feature that makes it possible to establish TCP tunnels through the SSH server. This makes it possible to forward traffic for all connections accepted on a local IP/port (at the client) to a remote IP/port through the server (turning the client to a proxy), or the other way around.

This makes it possible to use SSH as a transport layer for various TCP communication protocols such as FTP, HTTP, SCP, SMTP, IMAP, POP3 or Telnet.

Outgoing tunnels #

Outgoing tunnels forward connections to a local port through the SSH server to the specified endpoint, which may be located within the SSH server's internal network.

Use StartOutgoingTunnel method to start accepting connections and tunnel them to the desired endpoint:

CSharp

// connect and log in to an SSH server
var ssh = new Rebex.Net.Ssh();
ssh.Connect(hostname);
ssh.Login(username, password);

// create port forwarding rule
// to accept connections at localhost:44000
// and tunnel then over SSH session through the SSH server
// to the specified IMAP server
SshTunnel tunnel = ssh.StartOutgoingTunnel(
    "localhost", 44000,      // client-side source address
    imapHostname, imapPort); // server-side target address

// establish a connection to the remote IMAP server
// by connecting to localhost:44000
// (we are using Rebex IMAP here, but third-party
// application should work as well)
var imap = new Rebex.Net.Imap();
imap.Connect("localhost", 44000);
imap.Login(imapUsername, imapPassword);

// use Imap object to download some messages, etc.
// ...

// finish work with IMAP
imap.Disconnect();

// stop port forwarding
tunnel.Close();

// close SSH connection
ssh.Disconnect();

VisualBasic

' connect and log in to an SSH server
Dim ssh = New Rebex.Net.Ssh()
ssh.Connect(hostname)
ssh.Login(username, password)

' create port forwarding rule
' to accept connections at localhost:44000
' and tunnel then through the SSH server
' to the specified IMAP server
Dim tunnel As SshTunnel = ssh.StartOutgoingTunnel(
    "localhost", 44000,
    imapHostname, imapPort)
' client-side source address | server-side target address

' establish a connection to the remote IMAP server
' by connecting to localhost:44000
' (we are using Rebex IMAP here, but third-party
' application should work as well)
Dim imap = New Rebex.Net.Imap()
imap.Connect("localhost", 44000)
imap.Login(imapUsername, imapPassword)

' use Imap object to download some messages, etc.
' ...

' finish work with IMAP
imap.Disconnect()

' stop port forwarding
tunnel.Close()

' close SSH connection
ssh.Disconnect()

Incoming tunnels #

Incoming tunnels forward connections to a remote port at the SSH server through the SSH client to the specified endpoint, which may be located within SSH client's internal network.

Use StartIncomingTunnel method to start accepting connections and tunnel them to the desired endpoint:

CSharp

// connect and log in to an SSH server
var ssh = new Rebex.Net.Ssh();
ssh.Connect(hostname);
ssh.Login(username, password);

// create port forwarding rule
// to accept connections on port 55000 at the server
// and tunnel them over SSH session through the SSH client
// to port 44000 at the client
var tunnel = ssh.StartIncomingTunnel(
    "localhost", 55000,  // server-side source address/port
    "localhost", 44000); // client-side target address/port

// listen for incoming connections at local port 44000
var listener = new TcpListener(IPAddress.Any, 44000);
listener.Start();

// accept connections tunneled from the server
while (acceptConnections)
{
    TcpClient client = listener.AcceptTcpClient();

    // do something
    // ...
}

VisualBasic

' connect and login to an SSH server
Dim ssh = New Rebex.Net.Ssh()
ssh.Connect(hostname)
ssh.Login(username, password)

' create port forwarding rule
' to accept connections on port 55000 at the server
' and tunnel them over SSH session through the SSH client
' to port 44000 at the client
Dim tunnel = ssh.StartIncomingTunnel(
    "localhost", 55000,
    "localhost", 44000)
' "localhost", 55000 ... server-side source address/port
' "localhost", 44000 ... client-side target address/port

' listen for incoming connections at local port 44000
Dim listener = New TcpListener(IPAddress.Any, 44000)
listener.Start()

' accept connections tunneled from the server
While acceptConnections
    Dim client As TcpClient = listener.AcceptTcpClient()

    ' do something
    ' ...
End While

Tip: To test the incoming tunnel, connect to the SSH server and run "telnet localhost 55000" command. Either using an SSH terminal client or programmatically with Rebex Terminal Emulation:

CSharp

// use telnet command to connect through the incoming tunnel
// (listening at localhost:55000) to the target endpoint
var scripting = ssh.StartScripting("telnet localhost 55000");

// wait to initialize telnet
scripting.WaitFor("Escape character is");
scripting.WaitFor(ScriptEvent.Line);

// send something
scripting.SendCommand("Hello there");

// read response
string response = scripting.ReadLine();

VisualBasic

' use telnet command to connect through the incoming tunnel
' (listening at localhost:55000) to the target endpoint
Dim scripting = ssh.StartScripting("telnet localhost 55000")

' wait to initialize telnet
scripting.WaitFor("Escape character is")
scripting.WaitFor(ScriptEvent.Line)

' send something
scripting.SendCommand("Hello there")

' read response
Dim response As String = scripting.ReadLine()

Note: By default, many SSH servers either don't support incoming tunnels or only make it possible to forwards connections from their local endpoints.

In addition to actual remote IP addresses, StartIncomingTunnel method accepts the following special values:

Value IPAddress Meaning
""n/aListen on all protocol families supported by the SSH implementation on all addresses.
"localhost"n/aListen on all protocol families supported by the SSH implementation on loopback addresses only.
"0.0.0.0"IPAddress.AnyListen on all IPv4 addresses.
"127.0.0.1"IPAddress.LoopbackListen on the loopback interfaces for IPv4.
"::"IPAddress.IPv6AnyListen on all IPv6 addresses.
"::1"IPAddress.IPv6LoopbackListen on the loopback interfaces for IPv6.

Tip: Rebex File Server supports outgoing port forwarding.

Using SSH as a proxy for Rebex components #

Tunneling Rebex components that implement HTTP, FTP, SFTP, SCP, SMTP, IMAP, POP3 or Telnet is even easier. These components have built in support for SSH transport layer, which makes it possible to use an SSH server as a proxy server:

CSharp

// establish the shared SSH connection
var session = new SshSession();
session.Connect(hostname);
session.Authenticate(username, password);

// use SSH session as proxy to establish another SSH connection
var ssh = new Rebex.Net.Ssh();
ssh.SetSocketFactory(session.ToSocketFactory());
ssh.Connect(sftpHostname);
ssh.Login(sftpUsername, sftpPassword);
// use Ssh object to execute commands, etc.

// use SSH session as proxy to establish IMAP connection
var imap = new Rebex.Net.Imap();
imap.SetSocketFactory(session.ToSocketFactory());
imap.Connect(imapHostname);
imap.Login(imapUsername, imapPassword);
// use Imap object to download mail messages, etc.

// use any Rebex component the same way
// (Ssh, Sftp, Ftp, Scp, Smtp, Imap, Pop3, Telnet, WebClient objects)

VisualBasic

' establish the shared SSH connection
Dim session = New SshSession()
session.Connect(hostname)
session.Authenticate(username, password)

' use SSH session as proxy to establish another SSH connection
Dim ssh = New Rebex.Net.Ssh()
ssh.SetSocketFactory(session.ToSocketFactory())
ssh.Connect(sftpHostname)
ssh.Login(sftpUsername, sftpPassword)
' use Ssh object to execute commands, etc.

' use SSH session as proxy to establish IMAP connection
Dim imap = New Rebex.Net.Imap()
imap.SetSocketFactory(session.ToSocketFactory())
imap.Connect(imapHostname)
imap.Login(imapUsername, imapPassword)
' use Imap object to download mail messages, etc.

' use any Rebex component the same way
' (Ssh, Sftp, Ftp, Scp, Smtp, Imap, Pop3, Telnet objects)