Discuss this help topic in SecureBlackbox Forum

Intercept the data being tunneled

Certain tasks may require you to intercept and/or modify application layer data tunneled over a simple forwarding object. For example, you might need that if you are building a proxy with NAT features, or if you are an NSA branch secretly building a secure worldwide surveillance solution.

Intercepting functionality is offered with TElSSHForwardingIntercept component. The Intercept object is attached to the host simple forwarding component (e.g. TElSSHLocalPortForwarding) via its Intercept property; once attached, the forwarding component will direct all its data flows through it.

The TElSSHForwardingIntercept object is abstract and is supposed to be overridden by the component user as per their interception requirements. Essentially, you need to override the following protected methods:

  • Accept() method is called when a new connection is accepted and lets you reject it if needed.
  • ChannelOpen(), ChannelClose(), SocketOpen(), SocketClose() are called when a virtual forwarding channel or a socket are opened or closed. These mainly serve for notification purposes.
  • ChannelRead() is called when some data arrives in the virtual channel from the remote party. In case of local port forwarding this is the data the remote server sends over the SSH channel to an application connected to your local listening port. With transparent interception you simply pass the data over via a built-in WriteToSocket() method after logging. If building an active interception solution, you can modify the data as needed before passing it to WriteToSocket().
  • SocketRead() is called when some data arrives in the local socket. In case of local port forwarding this is the data that a connected local application wants to be sent to the remote server over the SSH channel. Just as above, you can pass the data over in its original or altered form to WriteToChannel() method.
Example 1. Implementing logging:
void ChannelRead(TElSSHForwardedConnection conn, byte[] buffer)
{
    Logger.Log(conn, "RemoteToLocal", buffer); // logging data to some file
    WriteToSocket(buffer, 0, buffer.Length) // writing data unchanged to socket
}

void SocketRead(TElSSHForwardedConnection conn, byte[] buffer)
{
    Logger.Log(conn, "LocalToRemote", buffer); // logging data to some file
    WriteToChannel(buffer, 0, buffer.Length);
}
Example 2. Implementing (very nasty) active interception
void ChannelRead(TElSSHForwardedConnection conn, byte[] buffer)
{
    For (int I = 0; I < buffer.Length; i++)
    {
        If (buffer[i] == 0x41)  buffer[i] = 0x42; // replacing all 'A's with 'B's.
    }
    WriteToSocket(buffer, 0, buffer.Length)
}

void SocketRead(TElSSHForwardedConnection conn, byte[] buffer)
{
    Byte[] buf = SBUtils.Unit.CloneArray(buffer, 0, buffer.Length  - 1); // truncating the last byte of the original buffer
    WriteToChannel(buf, 0, buf.Length);
}
Not overriding a particular method preserves its default behavior. For example, Accept() will let accept all incoming connections, and ChannelRead() and SocketRead() will opaquely direct all provided data to the destination point with WriteToSocket() and WriteToChannel() calls.

How To articles about SSH client-side port forwarding

Discuss this help topic in SecureBlackbox Forum