SSH Tunneling — Accessing Data from Private Servers

Prakhar Chaube
WhatfixEngineeringBlog
4 min readSep 11, 2022

Today, Data has become more valuable than gold. When processed and utilized judiciously, it can solve many cumbersome problems of life. However, the very first step of any data-driven consumer or enterprise firm is gathering it. In case the gates of the access are closed everything else becomes pretty much obsolete.

credits — Giphy

But what if you are faced with the following client request,

“Hello, yes we would love to integrate our application data with your product! However, just an FYI, the data is not accessible via the internet and appears within our internal network only! Hope we can see your integration in action soon!”

Surprisingly, such requests are very common for any B2B SaaS product as almost all enterprises protect their data access by either a VPN or maintaining their Intranet. So, what can be done? Of course, one option is to request the clients to expose their data over the internet, but the probability of that happening is lower than that of being chased by a Kangaroo in Antarctica.

There are a few ways in which one can solve this problem but in this blog, we will discuss how to achieve it via SSH tunneling.

What is SSH?

The Secure Shell Protocol is a cryptographic network protocol for operating network services securely over an unsecured network.

In simple terms, SSH is a mechanism that allows you to securely access data residing on a remote server. Now that we are betting on security, let us discuss how SSH ensures that data access/transfer is secure.

I will not jump into the details of SSH architecture, hope the sequence diagram below helps! Otherwise, you can always read more about it here.

SSH Connection Sequence Diagram — vividbreeze

Now let us see how SSH can be utilized to access data residing within a VPC (Virtual Private Cloud).

For simplicity, we would be considering that the data that we want to access resides within an HTTP Server. This is in line with the fact that in most cases users can access the internal portals on their browsers by entering an HTTP URL (eg. https://my_intranet.docs.com/resources/3423) after connecting to the VPN.

By this time you would have realized that a special feature of SSH would come in handy for this. Yes, I am talking about Port Forwarding.

What is Port Forwarding?

Once we establish an SSH Connection it creates a secure tunnel between the two participating servers, you can forward a port via this tunnel. In essence, this means all the requests on that particular port will travel through the SSH Tunnel.

Consider an example of two cities separated by a river and connected via a bridge. Now, just having information about the bridge’s existence is not going to help! There needs to be some specific route leading to it! Suppose from city A, Route 37 leads to the bridge, then it becomes evident for any traveller that taking route 37 shall reach city B. Similarly, once we forward a local port in SSH, that port (identifiable by the port number) becomes the route to the destination server connected across the SSH connection.

Thus, this process of forwarding local ports across an SSH connection is often called SSH Tunnelling and is readily used to forward requests to remote servers securely bypassing firewalls or VPNs.

Setting up SSH Tunnel (Using Java)

This would not be much of a tech blog without some information about how one can set up SSH Tunnelling via code.

For Java, I found Apache Mina to be a highly scalable, safe, and easy-to-learn framework for performing SSH Connections.

Step 1: Set up SSH Client

SshClient client = SshClient.setUpDefaultClient();
client.setForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
client.setSessionHeartbeat(SessionHeartbeatController.HeartbeatType.IGNORE,TimeUnit.MILLISECONDS, 15000);
client.addPublicKeyIdentity(new KeyPair(getPublicKey(), getPrivateKey()));
client.start();

Step 2: Set up SSH Client Session and local port forwarding

try (ClientSession session = client.connect(new HostConfigEntry("", server_ip, 22, ssh_username, proxy_jump)).verify().getSession()) {session.addPublicKeyIdentity(new KeyPair(getPublicKey(), getPrivateKey()));
session.auth().verify(10000);
session.addPortForwardingEventListener(
new PortForwardingEventListener() {
@Override
public void establishedDynamicTunnel(Session session, SshdSocketAddress local,SshdSocketAddress boundAddress,Throwable reason) throws IOException {
PortForwardingEventListener.super.establishedDynamicTunnel(
session, local, boundAddress, reason);
System.out.println("Dynamic Forword Tunnel is Ready");
}
});
SshdSocketAddress sshdSocketAddress = session.startDynamicPortForwarding(new SshdSocketAddress("localhost", 9098));// Do operations} catch (Exception e){
//handle exception
} finally {
client.stop();
}

Step 3: Use any HTTP Client with a proxy via the forwarded port and fetch request results through the tunnel

Proxy proxy = new Proxy(Proxy.Type.SOCKS,new InetSocketAddress(sshdSocketAddress.getHostName(),
sshdSocketAddress.getPort()));
HttpURLConnection connection = (HttpURLConnection) new URL( URL_TO_ACCESS).openConnection(proxy);BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));System.out.println("Data From URL:");
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();

Best Practices

Being vigilant and cautious is an absolute necessity when dealing with Security. As they say, “You can never be too sure!”.

Here are some best practices that would minimize the risk of getting compromised when dealing with SSH Tunnels:

  1. Always use Keys for Authenticating SSH Connections. Another option for authenticating SSH connections is username-password. Always avoid this method.
  2. Use Connection timeouts for stale connections. It is empirical that you do not leave stale open connections. Always configure auto-kill options to ensure session closure upon being left unused.
  3. Don’t connect to servers that have data, instead connect to a Jumphost server or Tunnel server which doesn’t contain data directly. Jumphost server or Tunnel server is a server machine within the VPC and is usually used for incoming SSH hops, these can easily be isolated and monitored. Most importantly they do not contain any precious data within.
  4. Keep rotating the authentication keys from time to time. Always keep rotating the private-public key periodically.

Hope you had fun reading the blog! Feedback is always appreciated in the comment section! Happy Coding!

--

--

Prakhar Chaube
WhatfixEngineeringBlog

So many things to learn, so many thoughts to pen. Software Engineer, Stock Market Enthusiast, Musician, Dreamer, Human.