Skip to main content

Secure Access to Secure Sites: SSH Tunneling & Reverse tunnels, VNC, X11

By 24 October 2023No Comments

As our other blog post might have suggested, we like SSH at Alteeve. It is secure, widely supported, requires minimal security concessions to make available, and it is publicly audited for vulnerabilities, backdoors, and exploits. There is a lot to love about Secure Shell! While we touched upon SSH tunnels and SOCKS5 proxies last time, there are a lot of other use cases for SSH in supporting remote deployments.

A specific case we have run into regarding remote access is interacting with client sites that have very strict inbound access rules. Any access to these sites are often highly controlled and changes must be thoroughly vetted by upstream security teams – which can take quite a while! In the meantime, a client may have services impacted or be in a degraded state. In these situations, we always caution adherence to security policies, especially for organizations outside of your own. However, there are usually secure and workable alternatives to permanent security changes to access these sites. This article will be on one avenue to access, reverse tunneling, as well as an open-source and freely-available way of achieving remote desktop connections using VNC or RDP.

A note on these solutions

While this method of access is secure, and when implemented with knowledge and consent of a client, is a great way to make sure you have approved access to a system in a pinch, these tools are also available by default on most UNIX-based systems and are equally usable by malicious users or attackers. Being aware of the bilateral nature of many networking tools is a key way to prepare for and plan against external attacks and internal misuse. To this end, it is worthwhile to try these methods on your own networks and observe the traffic. Is this the kind of access you want to make available? If not, what tools do you have in your firewall and security suites that could mitigate this access? These questions are outside of the scope of this article, but we heartily recommend that our community members ask them. Curiosity is a virtue!

Digging into tunneling

In our last discussion about SSH, I wrote about SSH tunnels: secure, encrypted connections through which other network traffic could be sent. I breezed through the topic, but it is worth getting into more detail as SSH tunneling is an extremely powerful tool to have in your sysadmin kit. We make extensive use of SSH in Anvil’s inter-node and subnode communication, including tunneling.

Network connections between systems can be conceptualized as having multiple ‘layers’, as best demonstrated by the OSI model, with each layer generally depending on the layers below. For instance, a network connection between two physical computers requires a physical link (be it copper, fiber optics, or an electromagnetic signal such as wifi), which transmits the data link. The data link includes the protocols and data packaging which comprises the ‘network’ and ‘transport’ layers. Atop of those, a session which is a series of cogent communications between systems is created, through which data is presented and applications operate.

SSH tunneling operates at the fifth, or ‘Session’ layer. It relies on all of the network infrastructure and protocols, but is itself not quite an application per se. It connects two ‘ports’, or conceptual start and end points for a network connection. These ports can be thought of as ends of a physical cable, but in software. In creating an SSH tunnel, we are plugging in that ‘cable’ from port A on our system to port B on a different one, and keeping it plugged in for the duration of the SSH session. What data goes over that cable is up to us!

This ‘wrapping’ of data in an SSH session is what makes tunneling so powerful. We can make insecure connections secure by virtue of the encrypted SSH tunnel, and pipe software and services which would otherwise be denied by security systems through legitimate ports and access. Best of all, creating a tunnel session is very straightforward:

# ssh -L $localport:localhost:$destinationport

Or, in more memorable terms, we will use ssh to Link a port on our local host to our destination port, which can be found as the user at the destination IP or URL.

But what ports should we use? We won’t get into the details of how ports work, especially as this differs by operating system, but generally speaking, ports above 10000 are less likely to be used by other services[. If we are just creating a tunnel through which another connection will be made, any unused port will do. More often, however, we will want to tunnel a specific application through SSH, and that generally will have ports already selected for you. Let’s use VNC, an open source remote desktop protocol, as an example.

VNC uses ports starting at 5900 by convention, with the terminal or display number added on. While we won’t be getting into VNC configuration today, let’s assume that you have a VNC server offering up a session on display 2, or :2 in UNIX terminology. That would mean we should be able to access VNC on port 5902. Let’s also assume that the remote location does not allow external connections over port 5902, however, we do know that we have the ability to connect over SSH (default port 22). This is a relatively common situation in our experience at Alteeve.

If we were to connect to, port 5902 using our VNC client, the firewall rules will disallow that. We’d get a denied or bounced message. However, if we first run:

ssh -L 5902:localhost:5902

and then connect to localhost at port 5902, we should be greeted with a lovely login prompt!

Naturally, we can also use non-standard SSH ports, and non-standard local ports:

ssh -L 15999:localhost:5902 -p 11111

This should connect our local port 15999 to the remote port 5902 over port 11111. Fun!

And, per our last article, these connections can also be daisy chained:

# ssh -L 9999:localhost:10001 user@midpoint1
(on midpoint1) # ssh -L 10001:localhost:12999 user@midpoint2
(on midpoint2) # ssh -L 12999:localhost:5902 user@endpoint

This should allow us to connect to localhost:9999 and connect to endpoint:5902 bouncing through our two midpoints. As a bonus, you get to feel like a cool hacker doing so!

As a bonus, tangential tip: The endpoint port doesn’t need to be open via the destination’s firewall either! TigerVNC (and, I believe, most VNC implimentations on linux) default to localhost only connections, making them inherently secure against remote connection attempts. Forwarding ports via tunnels like this is an excellent way to maintain that security as it will look like you are logging in locally!

Reverse Tunneling: Dig up

Up until now, we have been logging in from a source external to the client system. In most cases, this is the usual method to take, however some security or policy regimes may disallow this. Another option is for the client to open an SSH tunnel to a predefined endpoint through which you can connect. This is referred to as reverse tunneling.

There are a few advantages to this method of tunneling, the chief of which is that it initiates the connection from within a network. This can avoid strict external connection rules, and it places the control over when the connection is available in the hands of the client. Of course, the latter can also be a downside: in the case of an emergency, you will be caught waiting for the client to open the tunnel.

# From the endpoint:
# ssh -R 10000:localhost:5902 user@midpoint

This command will reach out to the midpoint and create a connection that can be accessed on port 10000 at that location. To take advantage of this tunnel, you can then connect from your own system like so:

#ssh -L 11111:localhost:5902 user@midpoint -p 10000

And this should allow you to then connect at your localhost at port 11111, and have a multi-hop tunnel to the endpoint on port 5902. The -p means that SSH will do so over the previously reverse forwarded port 10000; or in other words, to use the existing connection. This means we can go without having to create any new inbound firewall rules, and with full client control of the tunnel.

To end any of these SSH sessions, typing ‘exit’ in the command prompt will shut down the connection, provided nothing is actively using it (like a VNC session).

Wrapping up

This should offer a more complete look at some ways that SSH can be used to extend your ability to support clients in a variety of security contexts without having to have unique applications for every opportunity. While we can’t always choose the tools we’d prefer, finding ways to unify access while maintaining security speeds interventions in critical situations.

Happy computing!