How to Create a Reverse SSH Tunnel: Difference between revisions

From RidgeRun Developer Wiki
No edit summary
Line 30: Line 30:
Now you will find instructions to create a '''reverse SSH tunnel'''.
Now you will find instructions to create a '''reverse SSH tunnel'''.


== Generate Key Pairs (REMOTE and LOCAL) ==
* On '''REMOTE'''
<source lang=bash>
ssh-keygen -f /home/$USER/.ssh/id_rsa_remote
</source>


== Create Key Pairs ==
* On '''LOCAL'''
On '''REMOTE'''
<source lang=bash>
ssh-keygen -f /home/$USER/.ssh/id_rsa_local
</source>


{{Ambox
|type=notice
|issue= '''Keys naming'''<br>You can use any names you want for your keys, we are just using ''remote'' and ''local'' for convinience.
}}<br>


[[Category:HowTo]][[Category:SSH]]
=== Share Generated Public Keys ===
We will share the public keys between both devices, so that no password is required when enabling the connections.
 
* Copy the '''LOCAL''''s public key into the '''REMOTE''''s <code>authorized_keys</code> file.
<source lang=bash>
cat id_rsa_local.pub >> ~/.ssh/authorized_keys
</source>
 
* Copy the '''REMOTE''''s public key into the '''LOCAL''''s <code>authorized_keys</code> file.
<source lang=bash>
cat id_rsa_remote.pub >> ~/.ssh/authorized_keys
</source>
 
{{Ambox
|type=notice
|issue= '''Key copying'''<br>The commands above work if you have a way of placing the key inside each other device. If it's not possible, you can also just copy the raw text from the <code>.pub</code> file and paste it into the required file as a new line.
}}<br>
 
== Systemd Service (REMOTE) ==
We want the '''REMOTE''' to enable the tunnel every time it starts. Also, it will try to enable the tunnel if there's an error.
 
For this we'll create a <code>systemd</code> service running on the '''REMOTE'''.
 
* Create the file <code>/etc/systemd/system/reverse_ssh.service</code> with the following contents:
<source lang=bash>
[Unit]
Description=Reverse SSH Tunnel Example
 
[Service]
# Please replace "user" with your username
User=user
Type=simple
ExecStart=/bin/bash /usr/local/bin/reverse-ssh.sh
Restart=always
RestartSec=10
 
[Install]
WantedBy=multi-user.target
</source>
 
{{Ambox
|type=notice
|issue= '''Set the User'''<br>Remember to set the User variable in the service file. Also notice the script called <code>reverse-ssh.sh</code>, we will create it right away.
}}<br>
 
* Create the script file <code>/usr/local/bin/reverse-ssh.sh</code> with the content:
<source lang=bash>
DATE=`date '+%Y-%m-%d %H:%M:%S'`
echo "Reverse SSH started at ${DATE}" | systemd-cat -p info
 
ssh -i /home/$USER/.ssh/id_rsa_remote -oStrictHostKeyChecking=no -N -R 2210:localhost:22 -p 2020 LOCAL_USER@LOCAL_IP
</source>
 
{{Ambox
|type=notice
|issue= '''Set the LOCAL info'''<br>Remember to set <code>LOCAL_USER</code> as the user from the '''LOCAL''' device, and <code>LOCAL_IP</code> as the IP of the '''LOCAL''' device too. Ideally, this IP should be static, so that you don't need to change this in case the IP changes. Also, you can just use a DNS instead of the IP (ex. mydomain.com).
}}<br>
 
And finally, start the service and enable it so that it starts on every boot.
 
<source lang=bash>
sudo systemctl daemon-reload
sudo systemctl start reverse_ssh.service
sudo systemctl enable reverse_ssh.service
</source>
 
== Enable Port (LOCAL)==
We will enable the <code>2020</code> port to receive the reverse tunnel request in the '''LOCAL''' device.
 
* Search the following line inside the file <code>/etc/ssh/sshd_config</code>:
<pre>
#Port 22
</pre>
 
* And replace it with
<pre>
Port 2020
</pre>
 
{{Ambox
|type=notice
|issue= '''Port 2020'''<br>You might have noticed that we have used ''2020'' as a port number multiple times . You can change it depending on your needs, but please take a look at the other sections of this wiki to change this port accordingly.
}}<br>
 
* Start the <code>ssh</code> service:
 
<source lang=bash>
sudo service ssh start
</source>
 
== SSH Access (LOCAL) ==
We are all set!
 
Access the '''REMOTE''' with:
 
<source lang=bash>
ssh -i ~/.ssh/id_rsa_local -p 2210 REMOTE_USER@localhost
</source>
 
{{Ambox
|type=notice
|issue= '''REMOTE User'''<br>Replace <code>REMOTE_USER</code> with the User's name that is running the tunnel on the '''REMOTE''' side.
}}<br>
 
 
[[Category:HowTo]]

Revision as of 00:28, 11 November 2021

Introduction

Oftentimes, a remote device needs to be accessed through SSH but it's not reachable due to network conditions, security requirements, etc.

SSH Connection Blocked

A reverse SSH tunnel is a solution to that problem. Basically, the hard-to-reach device will create a tunnel to a specific device we have access to. From now on, we will use the following notation:

  • LOCAL Device
The device to which we have easy access (your laptop, for example).
  • REMOTE Device
The device that is hard to access (usually it's far away from us, or it's someone else's device).

The following diagram represents the LOCAL device to the left, the REMOTE device to the right, and the tunnel enabling the connection.


SSH Reverse Tunnel Diagram

Actually the tunnel is created by the REMOTE device, and the LOCAL device uses that tunnel to access the REMOTE. Then, to create the tunnel, you need some level of access to the REMOTE device, but this process is done only once, whether you need to move to the REMOTE or you need the REMOTE owner's help.

Instructions

Now you will find instructions to create a reverse SSH tunnel.

Generate Key Pairs (REMOTE and LOCAL)

  • On REMOTE
ssh-keygen -f /home/$USER/.ssh/id_rsa_remote
  • On LOCAL
ssh-keygen -f /home/$USER/.ssh/id_rsa_local


Share Generated Public Keys

We will share the public keys between both devices, so that no password is required when enabling the connections.

  • Copy the LOCAL's public key into the REMOTE's authorized_keys file.
cat id_rsa_local.pub >> ~/.ssh/authorized_keys
  • Copy the REMOTE's public key into the LOCAL's authorized_keys file.
cat id_rsa_remote.pub >> ~/.ssh/authorized_keys


Systemd Service (REMOTE)

We want the REMOTE to enable the tunnel every time it starts. Also, it will try to enable the tunnel if there's an error.

For this we'll create a systemd service running on the REMOTE.

  • Create the file /etc/systemd/system/reverse_ssh.service with the following contents:
[Unit]
Description=Reverse SSH Tunnel Example

[Service]
# Please replace "user" with your username
User=user
Type=simple
ExecStart=/bin/bash /usr/local/bin/reverse-ssh.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target


  • Create the script file /usr/local/bin/reverse-ssh.sh with the content:
DATE=`date '+%Y-%m-%d %H:%M:%S'`
echo "Reverse SSH started at ${DATE}" | systemd-cat -p info

ssh -i /home/$USER/.ssh/id_rsa_remote -oStrictHostKeyChecking=no -N -R 2210:localhost:22 -p 2020 LOCAL_USER@LOCAL_IP


And finally, start the service and enable it so that it starts on every boot.

sudo systemctl daemon-reload
sudo systemctl start reverse_ssh.service
sudo systemctl enable reverse_ssh.service

Enable Port (LOCAL)

We will enable the 2020 port to receive the reverse tunnel request in the LOCAL device.

  • Search the following line inside the file /etc/ssh/sshd_config:
#Port 22
  • And replace it with
Port 2020


  • Start the ssh service:
sudo service ssh start

SSH Access (LOCAL)

We are all set!

Access the REMOTE with:

ssh -i ~/.ssh/id_rsa_local -p 2210 REMOTE_USER@localhost