How to encrypt all TCP traffic from my client app to my server app?

0 votes
asked Dec 19, 2019 by rbrown (120 points)

My windows client program and backend windows server program use various TCP communications between them... in some cases .NET Remoting (binary TCP) and in some cases a custom protocol using plain text bytes with Socket.Listen and Socket.Poll on several ports. (the plain text strings are usually device-specific protocols which get relayed to attached devices)

We have been asked to encrypt the traffic between the client/server. Primarily the text protocol using the sockets, but it would be preferred to encrypt the remoting channel if possible too (could be a single solution or two separate approaches).

We have accomplished this in some cases with VPN or other port forwarding/tunnelling approaches between the client and server using external tools. However, to simplify this for my customers' deployments, is there a straightforward way with Rebex Total Pack .NET to simply encrypt (via SSH or other means) all traffic between my two applications?

I believe I could do this by using the FileServer.Bind(FileServerProtocol.Tunneling) on the server, and have the calling application use the Ssh.StartOutgoingTunnel or StartSocksServer, and mapping the ports. (I assume I also need to change the client to refer to localhost:localport everywhere it makes the connections). Is this the best approach or is there a better/simpler option?

The client talks to multiple "servers". And it is for long running operations so it would need to be able to re-establish the connection in case of a drop out on either side.

Any advice is appreciated.
Thanks!

1 Answer

0 votes
answered Dec 19, 2019 by Lukas Pokorny (106,330 points)

The SSH tunneling approach is a straightforward solution, although it might be useful to consider the alternatives as well.

a) Use FileServer to implement a single-purpose tunneling SSH server. Run it at the remote site. Make sure to enable tunneling. At the client side, establish an outgoing tunnel to the server using Ssh object's StartOutgoingTunnel method. Then, instead of connecting your client directly to the remote server, connect to the local end of the tunnel you established.

b) Install any capable stand-alone SSH server at the remote site and enable tunneling. At the client side, use Rebex Ssh object as described in the scenario above.

c) Use TLS instead of SSH. In this approach, instead of communicating via .NET's System.Net.Sockets.Socket, you would use Rebex' Rebex.Net.TlsSocket that features a socket-like API but supports TLS. See this forum post for sample TLS server code. At the client side, create an instance of TlsSocket, call Connect following with Negotiate to negotiate a secure TLS session (before you can use Send and Read methods).

Unfortunately, SSH or TLS do not support re-establishment of connections in their original state in case of a drop out. To achieve this, you would have to add some custom layer on top of them that makes this possible.

commented Dec 19, 2019 by rbrown (120 points)
Thanks for the advice!  Some follow up questions regarding option (a).

1. Is there a way to have the SshClient/tunnel verify the connection and reconnect if needed?  E.g. will it re-connect on its own?  Or is there an event/handler which gets called upon connection dropped?   (Any other events or callbacks I could use to ensure it stays connected)

2. What is the difference between StartSocksServer and StartOutgoingTunnel?
commented Dec 20, 2019 by Lukas Pokorny (106,330 points)
1. No connection-resuming functionality is provided by the TCP protocol or the SSH protocol. Rebex libraries cannot provide it either, because they know nothing about the context of your connections or your communication protocol.

When the tunneled connection fails, you would get a SocketException from your Receive call, making it easily possible to detect this and re-establish the connection.

To ensure the underlying SSH connection is alive, the recommended approach is to call Ssh object's Session.KeepAlive() method periodically. If it fails, dispose the Ssh object and reconnect it.

2. StartOutgoingTunnel simply starts listening on a local IP/port. When a connection is made to it, all communication is forwarded to a specific remote IP/port. StartSocksServer starts a local SOCKS5 proxy server at the specified local IP/port. Client applications that support SOCKS5 protocol can then connect to the proxy server and instruct it to connect to the remote IP/port supplied via the SOCKS5 protocol. Unless your client application already supports SOCKS5, this is probably not what you need.
...