SSH tunnel consists of an encrypted tunnel which is created through a SSH protocol. This tunnel can be used to transfer unencrypted traffic through an encrypted channel over the network. For example we can use a SSH tunnel to securely transfer files.
SSH tunnels are also used for bypassing firewalls that deny certain internet services.
SSH tunnels can be created in various ways depending on which type of port forwarding is used:
There are three types of port forwarding:
- Local port forwarding
- Remote port forwarding
- Dynamic port forwarding
Tunnelling with Local port forwarding
Lets say, yahoo.com is being blocked using a proxy filter at your college. An SSH tunnel can be used to bypass this restriction. Let’s give name to my machine at college as “college-pc” and my home machine as “home-pc” (SSH server should be running on “home-pc”)
To create the SSH tunnel that is executed from “college-pc” use the below command:
-L indicates that this is local port forwarding
Now SSH client at college-pc is connected to SSH server running at “home-pc”. This is also binding port 9090 of college-pc to listen to all local requests thus creating an SSH tunnel between “college-pc” and “home-pc”.
At the home-pc side, It will create a connection to yahoo.com at port 80. home-pc will think of how to connect to yahoo rather than college-pc.
Now we can browse yahoo.com at work using localhost:9090
The home-pc will act as a gateway.
Reverse Tunnelling with remote port forwarding
Let’s say you want to connect to an internal university website from the home-pc system.
The university firewall will block its incoming traffic. We have to use SSH reverse tunnelling here.
We will use the option -R for reverse tunneling.
Once done, The SSH client at college-pc will connect to the SSH server running at home-pc. Then the server will bind port 9090 on home-pc to listen to all incoming requests.
By visiting localhost:9090 at home-pc, the college-pc will create a connection to the internal site and give back the response to home-pc via the created SSH channel.
- Automation Test Framework
- BI Tools
- FireTV App
- Machine Learning
- Media Coverage
- Open Source
- Smart Appliances
- Smart Healthcare
- Work Culture
All content provided on this blog is for informational purposes only. Tudip Technologies provides no endorsement and makes no representations as to accuracy, reliability, completeness, suitability or validity of any information or content on, distributed through or linked, downloaded or accessed from this site. Tudip Technologies will not be liable for any errors, omissions, or delays in this information or any losses, injuries, or damages arising from its display or use of the information on this site. All information is provided on an as-is basis without any obligation to make improvements or to correct errors or omissions. This site may contain links to other websites. Tudip Technologies makes no guarantees or promises regarding these websites and does not necessarily endorse or approve of their content. You may not modify any part of the blog. The inclusion of any part of this blog in another work, whether in printed or electronic or other form, or inclusion of any part of the blog in another website by linking, framing or otherwise without the express permission of Tudip Technologies is prohibited. This site may not be used for any illegal or illicit purpose and Tudip Technologies reserves the right, at its sole discretion and without notice of any kind, to remove anything posted to this site. By using this site, you hereby acknowledge that any reliance upon any materials shall be at your sole risk.
- IoT & Wearables
- Product Engineering
- Cloud Enablement
- Google Cloud Platform
- Amazon Web Services
- Azure Cloud
- UI/UX & Web Development
- Mobile & Devices
- Quality Assurance & RPA
- Support and Maintenance
“Is to be a Global partner and the first choice for our customers by providing leadership in specific domains to help our customers accelerate the value creation process.”
“Is to create a niche’ by offering cutting-edge integrated services across technologies empowered by innovation, best in class process and best of breed technology.”
Plot No. 11/2, Phase 3,
Hinjewadi Rajiv Gandhi Infotech Park,
Hinjewadi, Pune, India – 411057
64 Caracas Road North York, Toronto
Ontario M2K 1B1, Canada
Cra. 9 # 113-53 Of. 1405 Bogotá D.C., Colombia
22 Kumasi Crescent, Wuse 2, Abuja,
Calle Amado Nervo #785 Interior B
Colonia Ladrón De Guevara
44600 Guadalajara, Jalisco, Mexico
2021 © Tudip Technologies Pvt. Ltd. All rights reserved.
If you’re lucky enough that your Internet Service Provider (ISP) gives you a dedicated IP address, you can set up a home server and make it available to the Internet by adding a few port forwarding rules to your router. But if your ISP makes you share that IP with your neighbors, then port forwarding won’t help. Other providers simply block incoming connections through firewall rules.
You can bypass all of these restrictions with the help of a virtual private server. Anything will work, even if it has less than 512MB of RAM, as all it has to do is redirect network traffic. This is very light on CPU and RAM. The server will receive incoming connections and redirect them to your computer through what is called a “reverse SSH tunnel.” This way you can set up any kind of home server, with very small monthly costs.
Imagine you create a NextCloud server to upload/synchronize your files. You get the privacy of having those files on your home server, and then you can buy a 6TB hard drive to get all the space you need. You only have to pay a monthly electricity bill and less than $5/month for a virtual private server. That’s way cheaper than the monthly bill for a server with 6TB of space.
Note: This only works for redirecting TCP network traffic. TCP is used by things such as web servers (port 80/tcp). UDP is used by some (not all) game servers, for example Counter Strike (port 27015/UDP). UDP tunneling is possible, but with some “hacks,” which may be the topic of a future tutorial.
Windows 10 Now Has a Built-in SSH Client
There’s no need to use PuTTY anymore to initiate SSH connections. In fact, for this tutorial you will actually use this built-in client to set up the tunnel. Read the tutorial about Windows 10’s OpenSSH client if you’re not already familiar with it.
Prepare Virtual Private Server to Tunnel Connections
Create a Virtual Private Server with your favorite provider, like DigitalOcean, Linode, Vultr, or whatever else you prefer. The most important thing is to choose a server location that is as close to you as possible to minimize network latency. Try to set up the server in such a way that you get to log in to the root account directly, preferably with an SSH key, as it’s more secure. This is required if you want to make the server listen to connections coming on ports below 1024, so-called privileged ports.
Open command prompt (or a terminal if you’re on Linux), and log in to the server through SSH.
Edit OpenSSH server settings:
If you didn’t log in as root but as a regular user, you will need to use this command, otherwise you won’t be able to save the file:
Scroll down until you find a variable called “GatewayPorts.” The line may look like this: #GatewayPorts no . Delete the preceding “#” (to uncomment) and change the line to GatewayPorts yes .
If you can’t find the line, just scroll down to the end and add the line yourself:
Press Ctrl + X , then press y , and finally Enter to save the file.
Reload the SSH daemon so it picks up on the new setting.
Exit from the SSH session.
How to Set Up a Reverse SSH Tunnel
The command parameters are the same on Linux, Windows, and even BSD operating systems. The general syntax is:
- remote_port tells the server to redirect connections that come to it on that port.
- host tells the server at what IP address the connection should be redirected to. 127.0.0.1 will be used here to redirect to your own computer.
- localport instructs what port data packets should be redirected to. Here, you should put the port number that your application, installed on your local computer, listens on.
For example, to forward all connections that come on port 80 (to the server) and send them to port 8080 on your local computer, the command would be:
This assumes that you have a web server, like Apache or Nginx, that listens on port 8080 on your local machine. But if Apache/Nginx is listening on the default port 80, then there is no problem using the same port twice in the previous command (since they are referring to port 80 in a different server).
At this point, if someone enters the IP address of your virtual private server in the address bar of a browser, their connection would be redirected and served by your local computer.
In the picture above, a simple web server for Chrome was used that listens on port 8887 by default. You can try this setup yourself by installing the app and then using the command, as in the picture.
It’s worth mentioning that to keep the tunnel active, your SSH session must remain active. To close the tunnel, type exit in the terminal/command prompt window.
As you can see, it’s not hard to create a reverse SSH tunnel, but securing a website is. So if you choose to implement an idea like a local NextCloud server, isolate it in a virtual machine at least. This way, if your website gets compromised, at least the rest of your operating system will be unharmed.
And, you know … always back up what you don’t want to risk losing!
Fell in love with computers when he was four years old. 27 years later, the passion is still burning, fueling constant learning. Spends most of his time in terminal windows and SSH sessions, managing Linux desktops and servers.
Reverse SSH Port Forwarding specifies that the given port on the remote server host is to be forwarded to the given host and port on the local side. To try to put this as simple as can be, Reverse SSH is a technique through which you can access systems that are behind a firewall from the outside world.
So instead of your machine doing a simple SSH, the server does an SSH and through the port forwarding makes sure that you can SSH back to the server machine.
Why should you use Reverse SSH Port Forwarding
SSH is a very useful and powerful tool when comes time to access a remote machine or server securely. But now the problem occurs when you try to connect to a remote server that is behind a firewall and that firewall rejects any incoming connection or data transfer request that has no prior outgoing request.
So let’s say that you’re working from home and need to access your office computer that is behind some very restrictive corporate firewall, well you wouldn’t be able to connect because of the firewall policies. Usually this would be more than welcome since no outsiders should be allowed to access internal parts of a secure network. A secure VPN access would certainly solve your problem but what if you don’t have access to that VPN? You know that the same firewall wouldn’t have any issues with the connection coming straight from the server machine! Well this is when Reverse SSH Port Forwarding comes to the rescue!
With reverse port forwarding you can forward a port on the remote machine to the local machine while still initiating the tunnel from the local machine. This works by assigning a socket to listen to the port on the remote side, and whenever a connection is made to this port, the connection is forwarded over the secure channel, and a connection is made to the host port from the local machine. Simply put, you want to connect your local machine to a server, so that you can use the tunnel to connect from the server to your local machine.
How to Reverse SSH Port Forwarding
In order to SSH into a machine behind a firewall you will need to use Reverse SSH Port Forwarding. The machine in question needs to open an SSH connection to the outside world and include a -R tunnel whose entry point is the remote side (from server in our example) to connect to your machine, allocate a port there and make certain that any connection request on that port is then forwarded to the SSH port of the remote side (server).
From the remote server side run the following command on the server: ssh –R 2210:localhost:22 [email protected]
This command will initiate an ssh connection with reverse port forwarding option which will then open listening port 2210: who is going to be forwarded back to localhost’s port :22 and all this will happen on the remote computer [email protected]
The -R option tells the tunnel to answer on the remote side, which is the SSH server and the -L option tells the tunnel to answer on the local side of the tunnel, which is the host running your client.
You could also add some options to your command: ssh –f –N –T –R 2210:localhost:22 [email protected]
- -f: tells the SSH to background itself after it authenticates, saving you time by not having to run something on the remote server for the tunnel to remain alive.
- -N: if all you need is to create a tunnel without running any remote commands then include this option to save resources.
- -T: useful to disable pseudo-tty allocation, which is fitting if you are not trying to create an interactive shell.
Now you need to do an SSH connection request from your machine to your own machine at port 2210:
ssh -p 2210 [email protected]
It may seem like you’re doing an SSH on localhost but instead your request would be forwarded to the remote host. This command will establish a connection to the firewall host through the tunnel.
Hopefully this will help you to clear the fog surrounding Reverse SSH Port Forwarding. Have fun!
Do you have publicly inaccessible database that you need to SSH into? Using SSH Reverse Tunneling, aka SSH Reverse Port Forwarding, you can securely connect to the database without directly opening it up to a vector of attack.
Resources in private subnets are notoriously hard to connect to (by design). With AWS you have VPNs and AWS Direct Connect as options, but the overhead isn’t worth it unless you have very specific requirements. That’s where SSH port forwarding/tunneling + Bastion Hosts come in.
This post goes hand in hand with another piece I will be uploading soon; the purpose of that post being a beginner’s DevOps/Cloud Architect’s guide to bringing up the foundational infrastructure featured below. I will post a link here when that goes up.
What is SSH Reverse Tunneling?
With a traditional SSH, your machine can connect to a remote instance.
SSH reverse tunneling on the other hand, sets up an omnidirectional connection between a port on your local machine and a port on the remote instance.
Your local machine initiates a connection by forwarding a port on the remote instance to your local machine. You can then use that established connection to set up a new connection from your local machine back to the remote instance. The end-state of this interaction being that you can connect your local machine to the remote instance, so that you can use the tunnel (in reverse) to connect from the server to your local machine. Fortunately for us, this process is way easier to do than it is to understand.
Our Infrastructure Topology
Zooming out, we can see the individual resources we’re dealing with. In your AWS cloud you have a VPC (Virtual Private Cloud) that has one public subnet and one private subnet.
The public subnet has a lightweight EC2 instance (t2.nano in our case) whose only function is to act as a jump server. It doesn’t even have PSQL installed. This bastion host’s security group allows inbound connections on port 22 (SSH) and already has my public key and user profile on it.
Our bastion host’s security group (sg-096afe51bf07b5e3c) allows inbound connections on port 22 (SSH) from all IP addresses.
The private subnet has a PostgresSQL database with an attached security group (sg-00d981dc294ce24f0) that allows inbound connections from our bastion host’s security group (sg-096afe51bf07b5e3c)
Our PostgresSQL database’s security group (sg-00d981dc294ce24f0) allows inbound connections from our bastion host’s security group
Using SSH Reverse Tunneling
First, we want to establish a reverse tunnel through our bastion host (184.108.40.206) to our PostgresSQL DB (postgrestest.cewfon7xqsuk.us-east-1.rds.amazonaws.com). To do so, we want to open up a terminal window on our local machine and write the following command:
- “ssh -i” is what we use to tell SSH what private key to use
- [private key] is your private ssh key
- -N sets up the tunnel without running any remote commands
- -L tells the tunnel to answer on the local side of the runnel
- [local port] should match the port number of your database. For PSQL this is 5432
- [database host] is your database’s endpoint listed in the Connectivity and Security tab of of your database
- [remote port] should match the port number of your database.
- [remote username] is the username
- [remote host] is your ec2 IP address
This is what it looks like for me
That’s it, our reverse tunnel is now sitting open for as long as we keep this terminal window open. Now all we have to do is to open up a new terminal window on our local machine and connect to our PostgresSQL database using:
- psql is the command we use to talk to postgres
- -U says what user to use
- [db username] is the existing user on the psql db we want to connect as
- -p says what port we want to use
- [local port] is the local port we used to connect from before
- -h says which host to connect to
- localhost is the same as 127.0.0.1, since were connecting to a locally forwarded port that leads to the tunnel
And we’re in. A super complicated concept that only takes two short alphanumerical lines to put into practice.
Aside from the theory behind SSH Reverse Tunneling, the hardest part is setting up the infrastructure to support it. I will be covering just that in my next post.
What Is SSH Port Forwarding, aka SSH Tunneling?
SSH port forwarding is a mechanism in SSH for tunneling application ports from the client machine to the server machine, or vice versa. It can be used for adding encryption to legacy applications, going through firewalls, and some system administrators and IT professionals use it for opening backdoors into the internal network from their home machines. It can also be abused by hackers and malware to open access from the Internet to the internal network. See the SSH tunneling page for a broader overview.
Local forwarding is used to forward a port from the client machine to the server machine. Basically, the SSH client listens for connections on a configured port, and when it receives a connection, it tunnels the connection to an SSH server . The server connects to a configurated destination port, possibly on a different machine than the SSH server.
Typical uses for local port forwarding include:
Tunneling sessions and file transfers through jump servers
Connecting to a service on an internal network from the outside
Connecting to a remote file share over the Internet
Quite a few organizations for all incoming SSH access through a single jump server . The server may be a standard Linux/Unix box, usually with some extra hardening, intrusion detection, and/or logging, or it may be a commercial jump server solution.
Many jump servers allow incoming port forwarding, once the connection has been authenticated. Such port forwarding is convenient, because it allows tech-savvy users to use internal resources quite transparently. For example, they may forward a port on their local machine to the corporate intranet web server, to an internal mail server’s IMAP port, to a local file server’s 445 and 139 ports, to a printer, to a version control repository, or to almost any other system on the internal network. Frequently, the port is tunneled to an SSH port on an internal machine.
In OpenSSH , local port forwarding is configured using the -L option:
This example opens a connection to the gw.example.com jump server, and forwards any connection to port 80 on the local machine to port 80 on intra.example.com .
By default, anyone (even on different machines) can connect to the specified port on the SSH client machine. However, this can be restricted to programs on the same host by supplying a bind address:
The LocalForward option in the OpenSSH client configuration file can be used to configure forwarding without having to specify it on command line.
In OpenSSH, remote SSH port forwardings are specified using the -R option. For example:
This allows anyone on the remote server to connect to TCP port 8080 on the remote server. The connection will then be tunneled back to the client host, and the client then makes a TCP connection to port 80 on localhost . Any other host name or IP address could be used instead of localhost to specify the host to connect to.
This particular example would be useful for giving someone on the outside access to an internal web server. Or exposing an internal web application to the public Internet. This could be done by an employee working from home, or by an attacker.
By default, OpenSSH only allows connecting to remote forwarded ports from the server host. However, the GatewayPorts option in the server configuration file sshd_config can be used to control this. The following alternatives are possible:
This prevents connecting to forwarded ports from outside the server computer.
This allows anyone to connect to the forwarded ports. If the server is on the public Internet, anyone on the Internet can connect to the port.
This means that the client can specify an IP address from which connections to the port are allowed. The syntax for this is:
In this example, only connections from the IP address 220.127.116.11 to port 8080 are allowed.
OpenSSH also allows the forwarded remote port to specified as 0. In this case, the server will dynamically allocate a port and report it to the client. When used with the -O forward option, the client will print the allocated port number to standard output.
Opening Backdoors into the Enterprise
Remote SSH port forwarding is commonly used by employees to open backdoors into the enterprise. For example, the employee may set get a free-tier server from Amazon AWS , and log in from the office to that server, specifying remote forwarding from a port on the server to some server or application on the internal enterprise network. Multiple remote forwards may be specified to open access to more than one application.
The employee would also set GatewayPorts yes on the server (most employees do not have fixed IP addresses at home, so they cannot restrict the IP address).
For example, the following command opens access to an internal Postgres database at port 5432 and an internal SSH port at port 2222.
The AllowTcpForwarding option in the OpenSSH server configuration file must be enabled on the server to allow port forwarding. By default, forwarding is allowed. Possible values for this option are yes or all to allow all TCP forwarding, no to prevent all TCP forwarding, local to allow local forwardings, and remote to allow remote forwardings.
Another option of interest is AllowStreamLocalForwarding , which can be used to forward Unix domain sockets. It allows the same values as AllowTcpForwarding . The default is yes .
The GatewayPorts configuration option as described above also affects remote port forwardings. Possible values were no (only local connections from server host allowed; default), yes (anyone on the Internet can connect to remote forwarded ports), and clientspecified (client can specify an IP address that can connect, anyone can if not specified).
How to Prevent SSH Port Forwarding from Circumventing Firewalls
We recommend that port forwarding be expressly disabled when not needed. Leaving port forwarding enabled can expose the organization to security risks and backdoors. For example, if a server intended to only provide SFTP file transfers allows port forwardings, those forwardings might be used to gain unintended access into the internal network from the Intranet.
The problem is that port forwarding can in practice only be prevented by a server or firewall. An enterprise cannot control all servers on the Internet. Firewall-based control can also be tricky, as most organizations have servers in Amazon AWS and other cloud services, and those servers are usually accessed using SSH.
Before starting the steps of this tutorial, the following steps will be required to complete.
A. Enable the SSH service on Ubuntu if it is not enabled before.
B. Generate the SSH Key pairs to execute the commands in the remote server. Run the following command to create the public key and the private key. The private key will be stored in the remote server, and the public keys will be stored in the client securely.
C. Run the following command to open the sshd_config file using nano editor to add some necessary configurations.
Add the following lines in the file to enable the root login and password-based authentication.
D. Run the following command to restart the SSH service.
Local Port Forwarding
It is used to forward a port from the client machine to a port of the server machine, and next, that will be forwarded to the destination machine. The client machine listens on a given port and tunnels the connection from that port to the particular port of the server machine in this type of forwarding. Here, the destination machine can be any remote server or another machine. This forwarding is mainly used on the internal network such as VNC (Virtual Network Computing) server.
Remote Port Forwarding
The opposite of the local port forwarding is remote port forwarding. It is used to forward a port from the server machine to a port of the client machine, and next, that will be forwarded to the destination machine. The server machine listens on a given port and tunnels the connection from that port to the particular port of the client machine in this type of forwarding. Here, the destination machine can be any local machine or another machine.
Dynamic Port Forwarding
It is used to create a socket on the client machine that will work as a SOCKS proxy server, and when a client connects to the port, the connection will be forwarded to the server machine. Next, it will forward to the dynamic port of the destination machine. The applications using SOCKS proxy will connect to the server machine that will forward the traffics to the destination machine.
Examples of SSH tunneling or port forwarding
The SSH tunneling and port forwarding examples have been shown here using two local server accounts. You can follow the same process for the remote server. Here, the username of the server machine is ‘fahmida,’ and the username of the client machine is ‘Yasmin. Three types of SSH port forwarding have been shown here by three examples.
A. Access remote resources from the client machine
The resources of the remote machine can be accessed from the client machine by using local port forwarding. It will normally connect to the SSH server, but in this case, you have to use the -L option with ssh command by defining the local port, remote address, and remote port. The syntax of the local port forwarding is given below.
Suppose the local port number is 8080, the IP address of the remote server is 10.0.2.15, and the remote port number is 80. Run the following command to connect with the server machine by local port forwarding. Here, the hostname of the remote machine is ‘fahmida.com.bd.’
After connecting with the remote machine, the user of the client machine will be able to access any content from the remote machine that has been shown here. A text file named log.txt exists in the remote machine. Now, run the following command from the client machine to read the file’s content after login into the remote machine.
Run the following commands to log out from the remote machine.
The following similar output will appear after executing the above commands. The output shows the content of the text file from the remote machine and the next log out from the remote machine.
B. Access local resources from the server machine
The resources of the local machine can be accessed from the server machine by using remote port forwarding. It will normally connect to the SSH server, but in this case, you have to use the -R option with ssh command by defining the remote port, local address, and local port. The syntax of the remote port forwarding is given below.
Suppose the remote port number is 22, the hostname of the local server is localhost, and the local port number is 2345. Run the following command to connect with the server machine by remote port forwarding. Here, the hostname of the remote machine is ‘fahmida.com.bd.’
After connecting with the remote machine, the remote machine user will access any content from the remote machine shown here. A text file named products.txt exists in the home directory of the client machine. Now, run the following command after connecting with the remote machine to read the content of the local file.
Run the following commands to log out from the remote machine.
[cc lang=”text” width=”100%” height=”100%” escaped=”true” theme=”blackboard” nowrap=”0″]
The following similar output will appear after executing the above commands. The output shows the content of the text file from the client machine and the next log out from the remote machine.
C. Using SSH server as a proxy server
Dynamic port forwarding is mainly used to access the particular application of the internal network by using a SOCKS proxy. The -D option is used with ssh command for dynamic port forwarding. The syntax of the dynamic port forwarding is given below.
Suppose the local port number is 5050. Run the following command to open a SOCKS proxy at the 5050 port. Now, the user can configure any browser or application to use the local IP address and the 5050 port for redirecting all traffic through the tunnel.
Three different ways of SSH port forwarding have been described in this tutorial for helping the readers to understand the concept of SSH tunneling or port forwarding.
About the author
I am a trainer of web programming courses. I like to write article or tutorial on various IT topics. I have a YouTube channel where many types of tutorials based on Ubuntu, Windows, Word, Excel, WordPress, Magento, Laravel etc. are published: Tutorials4u Help.
Using a VPN connection is the most secure way to access a network if you are working remotely, but as this configuration could require hardware, time, and knowledge, you should probably want to know alternatives to do it. Using SSH is also a secure way to access a remote network without extra hardware, less time consuming, and less effort than configuring a VPN server. In this blog, we’ll see how to configure SSH Tunneling to access your databases in a secure way.
What is SSH?
SSH (Secure SHell), is a program/protocol that allows you to access a remote host/network, run commands, or share information. You can configure different encrypted authentication methods and it uses the 22/TCP port by default, but it’s recommended changing it for security reasons.
How to Use SSH?
The most secure way to use it is by creating an SSH Key Pair. With this, you don’t only need to have the password but also the private key to be able to access the remote host.
Also, you should have a host with only the SSH server role, and keep it as isolated as possible, so in case of an external attack, it won’t affect your local servers. Something like this:
Let’s see first, how to configure the SSH server.
Most of the Linux Installation has SSH Server installed by default, but there are some cases where it could be missing (minimal ISO), so to install it, you just need to install the following packages:
Now you have the SSH Server installed, you can configure it to only accept connections using a key.
Make sure you change it after having the public key in place, otherwise you won’t be able to log in.
You can also change the port and deny root access to make it more secure:
You must check if the selected port is open in the firewall configuration to be able to access it.
This is a basic configuration. There are different parameters to change here to improve the SSH security, so you can follow the documentation for this task.
Now, let’s generate the key pair for the local user “remote” to access the SSH Server. There are different types of keys, in this case, we’ll generate an RSA key.
This will generate the following files in a directory called “.ssh” inside the user’s home directory:
The “ id_rsa ” file is the private key (keep it as secure as possible), and the “ id_rsa.pub ” is the public one that must be copied to the remote host to access it. For this, run the following command as the corresponding user:
In this example, I’m using the port 20022 for SSH, and my remote host is 18.104.22.168. I have also the same user (remote) created in both local and remote hosts. You can use another user in the remote host, so in that case, you should change the user to the correct one in the ssh-copy-id command:
This command will copy the public key to the authorized_keys file in the remote .ssh directory. So, in the SSH Server you should have this now:
Now, you should be able to access the remote host:
But this is not enough to access your database node, as you are in the SSH Server yet.
SSH Database Access
To access your database node you have two options. The classic way is, if you are in the SSH Server, you can access it from there as you are in the same network, but for this, you should open two or three connections.
First, the SSH connection established to the SSH Server:
Then, the SSH connection to the Database Node:
And finally, the database connection, that in case of MySQL, is:
And for PostgreSQL:
If you have the database client installed in the SSH Server, you can avoid the second SSH connection and just run the database connection directly from the SSH Server:
But, this could be annoying as you used to use the database connection directly from your computer connected in the office, so let’s see how to use the SSH Tunneling for this.
Following the same example, we have:
- SSH Server Public IP Address: 22.214.171.124
- SSH Server Port: 20022
- Database Node Private IP Address: 192.168.100.120
- Database Port: 3306/5432
- SSH user (local and remote): remote
- Database user: dbuser
So, if you run the following command in your local machine:
This will open the port 8888 in your local machine, which will access the remote database node, port 3306, via the SSH Server, port 20022, using the “remote” user.
So, to make it more clear, after running this command, you can access the remote database node, running this in your local machine:
If you are using a graphic tool to manage databases, most probably it has the option to use SSH Tunneling to access the database node.
Let’s see an example using MySQL Workbench:
And the same for PgAdmin:
As you can see, the information asked here is pretty similar to the used for the command line SSH Tunneling connection.
Security is important for all companies, so if you are working from home, you must keep data as secure as you are while working in the office. As we mentioned, for this, probably the best solution is having a VPN connection to access the databases, but if for some reason it is not possible, you need to have an alternative to avoid handling data over the internet in an insecure way. As you could see, configuring SSH Tunneling for accessing your databases is not rocket science, and is probably the best alternative in this case.
As I understand this, firewalls (assuming default settings) deny all incoming traffic that has no prior corresponding outgoing traffic.
Based on Reversing an ssh connection and SSH Tunneling Made Easy, reverse SSH tunneling can be used to get around pesky firewall restrictions.
I would like to execute shell commands on a remote machine. The remote machine has its own firewall and is behind an additional firewall (router). It has an IP address like 192.168.1.126 (or something similar). I am not behind a firewall and I know the remote machine’s IP address as seen from the Internet (not the 192.168.1.126 address). Additionally, I can ask someone to execute ssh (something) as root on the remote machine first.
Could anyone explain me, step by step, how reverse SSH tunneling works to get around the firewalls (local and remote machines’ firewalls and the additional firewall between them)?
What is the role of the switches ( -R , -f , -L , -N )?
5 Answers 5
I love explaining this kind of thing through visualization. 🙂
Think of your SSH connections as tubes. Big tubes. Normally, you’ll reach through these tubes to run a shell on a remote computer. The shell runs in a virtual terminal (tty). But you know this part already.
Think of your tunnel as a tube within a tube. You still have the big SSH connection, but the -L or -R option lets you set up a smaller tube inside it.
Every tube has a beginning and an end. The big tube, your SSH connection, started with your SSH client and ends up at the SSH server you connected to. All the smaller tubes have the same endpoints, except that the role of “start” or “end” is determined by whether you used -L or -R (respectively) to create them.
(You haven’t said, but I’m going to assume that the “remote” machine you’ve mentioned, the one behind the firewall, can access the Internet using Network Address Translation (NAT). This is kind of important, so please correct this assumption if it is false.)
When you create a tunnel, you specify an address and port on which it will answer, and an address and port to which it will be delivered. The -L option tells the tunnel to answer on the local side of the tunnel (the host running your client). The -R option tells the tunnel to answer on the remote side (the SSH server).
So. To be able to SSH from the Internet into a machine behind a firewall, you need the machine in question to open an SSH connection to the outside world and include a -R tunnel whose “entry” point is the “remote” side of his connection.
Of the two models shown above, you want the one on the right.
From the firewalled host:
This tells your client to establish a tunnel with a -R emote entry point. Anything that attaches to port 22222 on the far end of the tunnel will actually reach “localhost port 22”, where “localhost” is from the perspective of the exit point of the tunnel (i.e. your ssh client).
The other options are:
- -f tells ssh to background itself after it authenticates, so you don’t have to sit around running something on the remote server for the tunnel to remain alive.
- -N says that you want an SSH connection, but you don’t actually want to run any remote commands. If all you’re creating is a tunnel, then including this option saves resources.
- -T disables pseudo-tty allocation, which is appropriate because you’re not trying to create an interactive shell.
There will be a password challenge unless you have set up DSA or RSA keys for a passwordless login.
Note that it is STRONGLY recommended that you use a throw-away account (not your own login) that you set up for just this tunnel/customer/server.
Now, from your shell on yourpublichost, establish a connection to the firewalled host through the tunnel:
You’ll get a host key challenge, as you’ve probably never hit this host before. Then you’ll get a password challenge for the username account (unless you’ve set up keys for passwordless login).
If you’re going to be accessing this host on a regular basis, you can also simplify access by adding a few lines to your
Adjust remotehostname and remoteusername to suit. The remoteusername field must match your username on the remote server, but remotehostname can be any hostname that suits you, it doesn’t have to match anything resolvable.
Last updated on November 21, 2020 by Dan Nanni
You are running a Linux server at home, which is behind a NAT router or restrictive firewall. Now you want to SSH to the home server while you are away from home. How would you set that up? SSH port forwarding will certainly be an option. However, port forwarding can become tricky if you are dealing with multiple nested NAT environment. Besides, it can be interfered with under various ISP-specific conditions, such as restrictive ISP firewalls which block forwarded ports, or carrier-grade NAT which shares IPv4 addresses among users.
What is Reverse SSH Tunneling?
One alternative to SSH port forwarding is reverse SSH tunneling. The concept of reverse SSH tunneling is simple. For this, you will need another host (so-called relay host) outside your restrictive home network, which you can connect to via SSH from where you are. You could set up a relay host using a VPS instance with a public IP address. What you do then is to set up a persistent SSH tunnel from the server in your home network to the public relay host. With that, you can connect “back” to the home server from the relay host (which is why it’s called a reverse tunnel). As long as the relay host is reachable to you, you can connect to your home server wherever you are, or however restrictive your NAT or firewall is in your home network.
Set up a Reverse SSH Tunnel on Linux
Let’s see how we can create and use a reverse SSH tunnel. We assume the following. We will be setting up a reverse SSH tunnel from homeserver to relayserver , so that we can SSH to homeserver via relayserver from another computer called clientcomputer . The public IP address of relayserver is 126.96.36.199.
On homeserver , open an SSH connection to relayserver as follows.
Here the port 10022 is any arbitrary port number you can choose. Just make sure that this port is not used by other programs on relayserver .
The -R 10022:localhost:22 option defines a reverse tunnel. It forwards traffic on port 10022 of relayserver to port 22 of homeserver .
With -fN option, SSH will go right into the background once you successfully authenticate with an SSH server. This option is useful when you do not want to execute any command on a remote SSH server, and just want to forward ports, like in our case.
After running the above command, you will be right back to the command prompt of homeserver .
Log in to relayserver , and verify that 127.0.0.1:10022 is bound to sshd . If so, that means a reverse tunnel is set up correctly.
Now from any other computer (e.g., clientcomputer ), log in to relayserver . Then access homeserver as follows.
One thing to take note is that the SSH login/password you type for localhost should be for homeserver , not for relayserver , since you are logging in to homeserver via the tunnel’s local endpoint. So do not type login/password for relayserver . After successful login, you will be on homeserver .
Connect Directly to a NATed Server via a Reverse SSH Tunnel
While the above method allows you to reach homeserver behind NAT, you need to log in twice: first to relayserver , and then to homeserver . This is because the end point of an SSH tunnel on relayserver is binding to loopback address (127.0.0.1).
But in fact, there is a way to reach NATed homeserver directly with a single login to relayserver . For this, you will need to let sshd on relayserver forward a port not only from loopback address, but also from an external host. This is achieved by specifying GatewayPorts option in sshd running on relayserver .
Open /etc/ssh/sshd_conf at relayserver and add the following line.
Debian-based system without systemd :
Debian-based system with systemd :
Red Hat-based system:
Now let’s initiate a reverse SSH tunnel from homeserver as follows.
Log in to relayserver and confirm with netstat command that a reverse SSH tunnel is established successfully.
Unlike a previous case, the end point of a tunnel is now at 188.8.131.52:10022 ( relayserver ‘s public IP address), not 127.0.0.1:10022. This means that the end point of the tunnel is reachable from an external host.
Now from any other computer (e.g., clientcomputer ), type the following command to gain access to NATed homeserver .
In the above command, while 184.108.40.206 is the public IP address of relayserver , homeserver_user must be the user account associated with homeserver . This is because the real host you are logging in to is homeserver , not relayserver . The latter simply relays your SSH traffic to homeserver .
Set up a Persistent Reverse SSH Tunnel on Linux
Now that you understand how to create a reverse SSH tunnel, let’s make the tunnel persistent, so that the tunnel is up and running all the time (regardless of temporary network congestion, SSH timeout, relay host rebooting, etc.). After all, if the tunnel is not always up, you won’t be able to connect to your home server reliably.
For a persistent tunnel, I am going to use a tool called autossh . As the name implies, this program allows you to automatically restart an SSH session should it breaks for any reason. So it is useful to keep a reverse SSH tunnel active.
As the first step, let’s set up passwordless SSH login from homeserver to relayserver . That way, autossh can restart a broken reverse SSH tunnel without user’s involvement.
Next, install autossh on homeserver where a tunnel is initiated.
From homeserver , run autossh with the following arguments to create a persistent SSH tunnel destined to relayserver .
The -M 10900 option specifies a monitoring port on relayserver which will be used to exchange test data to monitor an SSH session. This port should not be used by any program on relayserver .
The -fN option is passed to ssh command, which will let the SSH tunnel run in the background.
The “-o XXXX” options tell ssh to:
- Use key authentication, not password authentication.
- Automatically accept (unknown) SSH host keys.
- Exchange keep-alive messages every 60 seconds.
- Send up to 3 keep-alive messages without receiving any response back.
The rest of reverse SSH tunneling related options remain the same as before.
If you want an SSH tunnel to be automatically up upon boot, you can add the above autossh command in /etc/rc.local .
In this post, I talked about how you can use a reverse SSH tunnel to access a Linux server behind a restrictive firewall or NAT gateway from outside world. While I demonstrated its use case for a home network via a public VPS, you must be careful when applying it for corporate networks. Such a tunnel can be considered as a breach of a corporate policy, as it circumvents corporate firewalls and can expose corporate networks to outside attacks. There is a great chance it can be misused or abused. So always remember its implication before setting it up.
This website is made possible by minimal ads and your gracious donation via PayPal (Credit Card) or Bitcoin ( 1M161JGAkz3oaHNvTiPFjNYkeABox8rb4g ).