com.sshtools.net
Class ForwardingClient

java.lang.Object
  extended bycom.sshtools.net.ForwardingClient

public class ForwardingClient
extends java.lang.Object

Provides management of port forwarding connections and active tunnels.

Three types of forwarding are provided by both SSH protocol versions; local forwarding allows you to transfer data (or socket connections if you prefer) from the local computer to a destination on the remote computer/network. For example you could setup a local forwarding to listen for connection's on port 110 (the POP3 protocol) and forwarding those connections to the port 110 at the remote side of the connection. This secures the data by encrypting it within the SSH connection making the insecure POP3 protocol secure. It is normally the practice to deliver the connection to a socket on the localhost of the remote computer to ensure that the data is not transmitted over any other insecure network. Remote forwarding is simply the reverse of this operation; a request is made to the server to listen on a particular port and any connections made are forwarded to the local computer where they are delivered to the required destination.The third type of forwarding is X forwarding and this is available for you to forward X11 data from the remote machine to a local X server.

The use of this client is a simple procedure. First create an instance once you have an authenticated SshClient. You can then use the methods to start local forwarding or request remote forwarding. This implementation manages all the connections and manages threads to transfer the data from sockets to the forwarding channels. All you are required to do is to select the forwarding configuration you require.

  // Create an SshClient instance into the variable ssh
  ...

  // Create a forwarding client
        ForwardingClient fwd = new ForwardingClient(ssh);

  // Configure X forwarding to deliver to a local X server
         fwd.allowX11Forwarding("localhost:0");

  // Request that HTTP requests on the port 8080 be forwarding from the
  // remote computer to the local computers HTTP server.
        if(!fwd.requestRemoteForwarding("127.0.0.1", 8080, "127.0.0.1", 80)) {
                System.out.println("Forwarding request failed!");
        }

  // Create a session to start the user's shell (see notes below)
        SshSession session = ssh.openSessionChannel();
        session.requestPseudoTerminal("vt100",80,24,0,0);
        session.startShell();

  // Forwarding POP3 connections made to the local computer to the remote server's POP3 port
        fwd.startLocalForwarding("127.0.0.1", 110, "127.0.0.1", 110);

  // Read the output of the users shell until EOF.
        InputStream in = session.getInputStream();
        try {
                int read;
                while((read = in.read()) > -1) {
                        if(read > 0)
                                System.out.print((char)read);
                }
                } catch(Throwable t) {
                        t.printStackTrace();
                } finally {
                        System.exit(0);
                }

  

The are several restrictions you must follow if you require protocol independece so that your code will work with both SSH1 and SSH2 servers. SSH1 remote forwarding requests MUST be made before you start the users shell and local forwarding's MUST only be started once you have started the users shell. With SSH1 you must always start the user's shell in order to perform port forwarding as this places the protocol into interactive mode. SSH2 does not place any restrictions as to when a remote forwarding is requesting or local forwarding started.

Additionally the single threaded nature of the API means there is no background thread available to service remote forwarding connection requests. In order that these requests are dealt with in a timely fashion your implementation will be required to start the users shell and read from its InputStream until it reaches EOF. This provides a thread to service the incoming requests and conforms to the requirements of using SSH1 forwarding so we recommend you follow this procedure even if you only require SSH2 connections.

The X forwarding managed by this class should be requested before starting any sessions. When X forwarding is requested a fake MIT-MAGIC-COOKIE is supplied to the remote machine which protects your real authentication cookies from being detected. When an X11 request comes in the fake cookie is replaced with your real cookie by looking at your .Xauthority file. If in the event that a real cookie cannot be found there are additional methods to either specify an alternative path to your .Xauthority file or to specify the cookie itself. Please note that X forwarding provided by this class does not operate over Unix Domain sockets so you should ensure that your X server is listening on a TCP port.

Author:
Lee David Painter

Nested Class Summary
 class ForwardingClient.ActiveTunnel
          This class represents an active tunnel.
 
Field Summary
 int HIGHEST_RANDOM_PORT
          The highest possible random port to select *
 int LOWEST_RANDOM_PORT
          The lowest possible random port to select *
static java.lang.String X11_KEY
          The key used to identify X11 forwarding
 
Constructor Summary
ForwardingClient(SshClient ssh)
          Create an forwarding client.
 
Method Summary
 void addListener(ForwardingClientListener listener)
          Add a ForwardingClientListener to receive forwarding events.
 void allowX11Forwarding(java.lang.String display)
          Configure the fowarding client to manage X11 connections.
 void allowX11Forwarding(java.lang.String display, java.io.File f)
          Configure the fowarding client to manage X11 connections.
 void allowX11Forwarding(java.lang.String display, java.lang.String magicCookie)
          Configure the fowarding client to manage X11 connections.
 void cancelAllRemoteForwarding()
          Stop all remote forwarding
 void cancelAllRemoteForwarding(boolean killActiveTunnels)
          Stop all remote forwarding.
 void cancelRemoteForwarding(java.lang.String bindAddress, int bindPort)
          Requests that the remote side stop listening for socket connections.
 void cancelRemoteForwarding(java.lang.String bindAddress, int bindPort, boolean killActiveTunnels)
          Requests that the remote side stop listening for socket connections.
 java.lang.String[] getLocalForwardings()
          Return the currently active local forwarding listeners.
 ForwardingClient.ActiveTunnel[] getLocalForwardingTunnels(java.lang.String key)
          Get the active tunnels for a local forwarding listener.
 ForwardingClient.ActiveTunnel[] getLocalForwardingTunnels(java.lang.String addressToBind, int portToBind)
          Get the active tunnels for a local forwarding listener.
 java.lang.String[] getRemoteForwardings()
          Returns the currently active remote forwarding listeners.
 ForwardingClient.ActiveTunnel[] getRemoteForwardingTunnels(java.lang.String key)
          Get the active tunnels for a remote forwarding listener.
 ForwardingClient.ActiveTunnel[] getRemoteForwardingTunnels(java.lang.String addressToBind, int portToBind)
          Get the active tunnels for a remote forwarding listener.
 ForwardingClient.ActiveTunnel[] getX11ForwardingTunnels()
          Get the active X11 forwarding channels.
 boolean hasLocalForwarding(java.lang.String addressBound, int portBound)
           
 boolean hasRemoteForwarding(java.lang.String addressBound, int portBound)
           
 boolean isXForwarding()
          Is X forwarding currently active?
 void removeListener(ForwardingClientListener listener)
          Remove a ForwardingClientListener from the list receiving forwarding events.
 boolean requestRemoteForwarding(java.lang.String addressToBind, int portToBind, java.lang.String hostToConnect, int portToConnect)
          Requests that the remote side start listening for socket connections so that they may be forwarded to to the local destination.
protected  int selectRandomPort()
          Select a random port.
 void startLocalForwarding(java.lang.String addressToBind, int portToBind, java.lang.String hostToConnect, int portToConnect)
          Start's a local listening socket and forwards any connections made to the to the remote side.
 int startLocalForwardingOnRandomPort(java.lang.String addressToBind, int maxFailedPorts, java.lang.String hostToConnect, int portToConnect)
          Start's a local listening socket and forwards any connections made to the to the remote side.
 void stopAllLocalForwarding()
          Stop all local forwarding
 void stopAllLocalForwarding(boolean killActiveTunnels)
          Stop all local forwarding
 void stopLocalForwarding(java.lang.String key, boolean killActiveTunnels)
          Stop a local listening socket from accepting connections.
 void stopLocalForwarding(java.lang.String bindAddress, int bindPort)
          Stops a local listening socket from accepting connections.
 void stopLocalForwarding(java.lang.String bindAddress, int bindPort, boolean killActiveTunnels)
          Stops a local listening socket from accepting connections.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

X11_KEY

public static final java.lang.String X11_KEY
The key used to identify X11 forwarding

See Also:
Constant Field Values

LOWEST_RANDOM_PORT

public final int LOWEST_RANDOM_PORT
The lowest possible random port to select *

See Also:
Constant Field Values

HIGHEST_RANDOM_PORT

public final int HIGHEST_RANDOM_PORT
The highest possible random port to select *

See Also:
Constant Field Values
Constructor Detail

ForwardingClient

public ForwardingClient(SshClient ssh)
Create an forwarding client.

Method Detail

addListener

public void addListener(ForwardingClientListener listener)
Add a ForwardingClientListener to receive forwarding events.

Parameters:
listener - listener

hasRemoteForwarding

public boolean hasRemoteForwarding(java.lang.String addressBound,
                                   int portBound)

hasLocalForwarding

public boolean hasLocalForwarding(java.lang.String addressBound,
                                  int portBound)

removeListener

public void removeListener(ForwardingClientListener listener)
Remove a ForwardingClientListener from the list receiving forwarding events.

Parameters:
listener - listener

startLocalForwarding

public void startLocalForwarding(java.lang.String addressToBind,
                                 int portToBind,
                                 java.lang.String hostToConnect,
                                 int portToConnect)
                          throws SshException
Start's a local listening socket and forwards any connections made to the to the remote side.

Parameters:
addressToBind - the listening address
portToBind - the listening port
hostToConnect - the host to connect on the remote side
portToConnect - the port to connect on the remote side
Throws:
java.io.IOException
SshException

startLocalForwardingOnRandomPort

public int startLocalForwardingOnRandomPort(java.lang.String addressToBind,
                                            int maxFailedPorts,
                                            java.lang.String hostToConnect,
                                            int portToConnect)
                                     throws SshException
Start's a local listening socket and forwards any connections made to the to the remote side.

Parameters:
addressToBind - the listening address
maxFailedPorts - the number of times to retry if the randomly selected port is in use.
hostToConnect - the host to connect on the remote side
portToConnect - the port to connect on the remote side
Returns:
the random port on which the tunnel is now listening
Throws:
java.io.IOException
SshException

getRemoteForwardings

public java.lang.String[] getRemoteForwardings()
Returns the currently active remote forwarding listeners.

Returns:

getLocalForwardings

public java.lang.String[] getLocalForwardings()
Return the currently active local forwarding listeners.

Returns:

getLocalForwardingTunnels

public ForwardingClient.ActiveTunnel[] getLocalForwardingTunnels(java.lang.String key)
                                                          throws java.io.IOException
Get the active tunnels for a local forwarding listener.

Parameters:
key -
Returns:
Throws:
java.io.IOException

getLocalForwardingTunnels

public ForwardingClient.ActiveTunnel[] getLocalForwardingTunnels(java.lang.String addressToBind,
                                                                 int portToBind)
                                                          throws java.io.IOException
Get the active tunnels for a local forwarding listener.

Parameters:
addressToBind -
portToBind -
Returns:
Throws:
java.io.IOException

getRemoteForwardingTunnels

public ForwardingClient.ActiveTunnel[] getRemoteForwardingTunnels(java.lang.String key)
                                                           throws java.io.IOException
Get the active tunnels for a remote forwarding listener.

Parameters:
key -
Returns:
Throws:
java.io.IOException

isXForwarding

public boolean isXForwarding()
Is X forwarding currently active?

Returns:

getRemoteForwardingTunnels

public ForwardingClient.ActiveTunnel[] getRemoteForwardingTunnels(java.lang.String addressToBind,
                                                                  int portToBind)
                                                           throws java.io.IOException
Get the active tunnels for a remote forwarding listener.

Parameters:
addressToBind -
portToBind -
Returns:
Throws:
java.io.IOException

getX11ForwardingTunnels

public ForwardingClient.ActiveTunnel[] getX11ForwardingTunnels()
                                                        throws java.io.IOException
Get the active X11 forwarding channels.

Returns:
Throws:
java.io.IOException

requestRemoteForwarding

public boolean requestRemoteForwarding(java.lang.String addressToBind,
                                       int portToBind,
                                       java.lang.String hostToConnect,
                                       int portToConnect)
                                throws SshException
Requests that the remote side start listening for socket connections so that they may be forwarded to to the local destination.

Parameters:
addressToBind - the listening address on the remote server
portToBind - the listening port on the remote server
hostToConnect - the host to connect on the local side
portToConnect - the port to connect on the local side
Returns:
Throws:
java.io.IOException
SshException

allowX11Forwarding

public void allowX11Forwarding(java.lang.String display,
                               java.lang.String magicCookie)
                        throws SshException
Configure the fowarding client to manage X11 connections. This method will configure the SshClient for X11 forwarding and will generate a fake cookie which will be used to spoof incoming X11 requests. When a request is received the fake cookie will be replaced in the authentication packet by a real cookie provided and passed onto the X server.

Parameters:
display - String
magicCookie - String
Throws:
java.io.IOException
SshException

allowX11Forwarding

public void allowX11Forwarding(java.lang.String display)
                        throws SshException
Configure the fowarding client to manage X11 connections. This method will configure the SshClient for X11 forwarding and will generate a fake cookie which will be used to spoof incoming X11 requests. When a request is received the fake cookie will be replaced in the authentication packet by a real cookie which is extracted from the users .Xauthority file.

Parameters:
display - String
Throws:
java.io.IOException
SshException

allowX11Forwarding

public void allowX11Forwarding(java.lang.String display,
                               java.io.File f)
                        throws SshException
Configure the fowarding client to manage X11 connections. This method will configure the SshClient for X11 forwarding and will generate a fake cookie which will be used to spoof incoming X11 requests. When a request is received the fake cookie will be replaced in the authentication packet by a real cookie which is extracted from the .Xauthority file provided in the File parameter.

Parameters:
display - String
Throws:
java.io.IOException
SshException

cancelRemoteForwarding

public void cancelRemoteForwarding(java.lang.String bindAddress,
                                   int bindPort)
                            throws SshException
Requests that the remote side stop listening for socket connections. Please note that this feature is not available on SSH1 connections. The only way to stop the server from listening is to disconnect the connection.

Parameters:
bindAddress - the listening address on the remote side
bindPort - the listening port on the remote side
Throws:
java.io.IOException
SshException

cancelRemoteForwarding

public void cancelRemoteForwarding(java.lang.String bindAddress,
                                   int bindPort,
                                   boolean killActiveTunnels)
                            throws SshException
Requests that the remote side stop listening for socket connections. Please note that this feature is not available on SSH1 connections. The only way to stop the server from listening is to disconnect the connection.

Parameters:
bindAddress - the listening address on the remote side
bindPort - the listening port on the remote side
killActiveTunnels - should any active tunnels be closed
Throws:
java.io.IOException
SshException

cancelAllRemoteForwarding

public void cancelAllRemoteForwarding()
                               throws SshException
Stop all remote forwarding

Throws:
SshException

cancelAllRemoteForwarding

public void cancelAllRemoteForwarding(boolean killActiveTunnels)
                               throws SshException
Stop all remote forwarding.

Parameters:
killActiveTunnels - Should any active tunnels be closed.
Throws:
SshException

selectRandomPort

protected int selectRandomPort()
Select a random port. NOTE: this method does not gaurentee that the port is available.

Returns:

stopAllLocalForwarding

public void stopAllLocalForwarding()
                            throws SshException
Stop all local forwarding

Throws:
SshException

stopAllLocalForwarding

public void stopAllLocalForwarding(boolean killActiveTunnels)
                            throws SshException
Stop all local forwarding

Parameters:
killActiveTunnels - should any active tunnels be closed
Throws:
SshException

stopLocalForwarding

public void stopLocalForwarding(java.lang.String bindAddress,
                                int bindPort)
                         throws SshException
Stops a local listening socket from accepting connections.

Parameters:
bindAddress - the listening address
bindPort - the listening port
Throws:
SshException

stopLocalForwarding

public void stopLocalForwarding(java.lang.String bindAddress,
                                int bindPort,
                                boolean killActiveTunnels)
                         throws SshException
Stops a local listening socket from accepting connections.

Parameters:
bindAddress - the listening address
bindPort - the listening port
killActiveTunnels - should any active tunnels be closed.
Throws:
SshException

stopLocalForwarding

public void stopLocalForwarding(java.lang.String key,
                                boolean killActiveTunnels)
                         throws SshException
Stop a local listening socket from accepting connections.

Parameters:
key - the bound address and port in the format "127.0.0.1:8080"
killActiveTunnels - should any active tunnels be closed.
Throws:
SshException


Copyright © 2003 3SP LTD. All Rights Reserved.