Disclaimer: This post has been translated to English using a machine translation model. Please, let me know if you find any mistakes.
Historical Introduction
In the early days of the internet, the telnet
protocol was created to enable communication between multiple computers, but it had the problem of not being encrypted, which meant that anyone who intercepted the communication could read it without any issues. That's why SSH
(Secure Shell) was created.
SSH Encryption
The SSH
encryption system works through the public key and private key system, so that if communication is encrypted with one of the keys, it can only be decrypted by the other key.
Why is there a public key and a private key? The public key is the one you give to everyone, and the private key is the one that only you should possess.
So, if you want to communicate with another team via SSH
, you first give them your public key, then you encrypt the message with your private key, and the message can only be decrypted with the public key that you have given to the other team.
The same happens in reverse, if the other team wants to send you a message, they encrypt it with your public key and it can only be decrypted with the private key that only you possess.
Requirements SSH
Service SSH
To be able to use SSH
you need to have an SSH
service. In Linux
it usually comes pre-installed, but if it's not the case, you can install it via
!apt install openssh-server
During the installation process, it will ask for your location to adjust the time zone.
We then start the service
!systemctl enable ssh
SSH Client
Once you have the service, you need a client. Although in Linux
it usually comes installed, if not, you can install it using
!apt install openssh-client
Connection via SSH
To connect via SSH
you need to enter the command ssh <user>@<ip>
!ssh root@172.17.0.1
The authenticity of host '172.17.0.1 (172.17.0.1)' can't be established.ECDSA key fingerprint is SHA256:M+qsqSC4HiYztm1ij8iDkh9KHJz+pxrTm9GTZIf2N9k.Are you sure you want to continue connecting (yes/no/[fingerprint])?
As you can see, the first time it asks you if you want to save the fingerprint
, this is so that if the next time you connect to the same machine (the same public key) the fingerprint
has changed, you should be careful because there might be something dangerous, like someone impersonating that machine.
If we trust, we enter yes
!ssh root@172.17.0.1
The authenticity of host '172.17.0.1 (172.17.0.1)' can't be established.ECDSA key fingerprint is SHA256:M+qsqSC4HiYztm1ij8iDkh9KHJz+pxrTm9GTZIf2N9k.Are you sure you want to continue connecting (yes/no/[fingerprint])? yesWarning: Permanently added '172.17.0.1' (ECDSA) to the list of known hosts.root@172.17.0.1's password:
Next, the machine we are connecting to asks for the password. We enter it, and we will be inside the machine.
!ssh root@172.17.0.1
The authenticity of host '172.17.0.1 (172.17.0.1)' can't be established.ECDSA key fingerprint is SHA256:M+qsqSC4HiYztm1ij8iDkh9KHJz+pxrTm9GTZIf2N9k.Are you sure you want to continue connecting (yes/no/[fingerprint])? yesWarning: Permanently added '172.17.0.1' (ECDSA) to the list of known hosts.root@172.17.0.1's password:Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.15.0-58-generic x86_64)* Documentation: https://help.ubuntu.com* Management: https://landscape.canonical.com* Support: https://ubuntu.com/advantage1 device has a firmware upgrade available.Run `fwupdmgr get-upgrades` for more information.* Introducing Expanded Security Maintenance for Applications.Receive updates to over 25,000 software packages with yourUbuntu Pro subscription. Free for personal use.https://ubuntu.com/proSe pueden aplicar 0 actualizaciones de forma inmediata.Your Hardware Enablement Stack (HWE) is supported until April 2025.Last login: Thu Dec 1 16:32:23 2022 from 127.0.0.1root@172.17.0.1:~$
Connection without password requirement
As we have seen, when we connect, it asks for the password of the target machine, but if it is a machine that we are going to connect to frequently, we can set it up so that it does not ask for the password every time we want to connect.
To do this, first we generate an ssh
key using ssh-keygen
!ssh-keygen
Generating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa):Enter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /root/.ssh/id_rsaYour public key has been saved in /root/.ssh/id_rsa.pubThe key fingerprint is:SHA256:4HxRXkVkcK5kNXNyzakfQ6t8a24wRGCUYz4s5KL5ZEc root@e108f6f395b3The key's randomart image is:+---[RSA 3072]----+| o+==@.=|| +.= * Oo|| . + = = + .|| o o E * + + || = S . = o o|| o + . = o || + . + .|| . + || +. |+----[SHA256]-----+
As we can see, it first asks us where we want to save the key; if we don't enter anything, it saves it in the default path. And then it prompts for a phrase to generate the key, **if you write a phrase, you must always remember it**. Additionally, if you write a phrase, it will ask you for it every time you try to access the key, so each time we want to access the machine via SSH
, it won't ask for the machine's password, but it will ask for this phrase. Therefore, you choose whether to not enter a phrase so that it never asks you, or to enter one and always input it.
Next, we ask the remote machine to save our key using ssh-copy-id <user>@<id>:
!ssh-copy-id root@172.17.0.1:
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keysroot@172.17.0.1's password:Number of key(s) added: 1Now try logging into the machine, with: "ssh 'root@172.17.0.1'"and check to make sure that only the key(s) you wanted were added.root@103b6040196a:/# ssh root@172.17.0.1Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.15.0-58-generic x86_64)* Documentation: https://help.ubuntu.com* Management: https://landscape.canonical.com* Support: https://ubuntu.com/advantage4 devices have a firmware upgrade available.Run `fwupdmgr get-upgrades` for more information.58 updates can be applied immediately.41 of these updates are standard security updates.To see these additional updates run: apt list --upgradableNew release '22.04.1 LTS' available.Run 'do-release-upgrade' to upgrade to it.Your Hardware Enablement Stack (HWE) is supported until April 2025.Last login: Thu Feb 2 08:05:48 2023 from 172.17.0.2(base) root@172.17.0.1:~$
Using the remote terminal via SSH
Maybe we don't need to log into the remote machine because we only need to run a single command, so we can use its terminal remotely by adding the -t
flag to the SSH
command, that is, through ssh -t <user>@<id> <command>
!ssh -t root@172.17.0.1 ping -c 4 google.com
PING google.com (172.217.168.174) 56(84) bytes of data.64 bytes from mad07s10-in-f14.1e100.net (172.217.168.174): icmp_seq=1 ttl=111 time=2.94 ms64 bytes from mad07s10-in-f14.1e100.net (172.217.168.174): icmp_seq=2 ttl=111 time=2.55 ms64 bytes from mad07s10-in-f14.1e100.net (172.217.168.174): icmp_seq=3 ttl=111 time=2.78 ms64 bytes from mad07s10-in-f14.1e100.net (172.217.168.174): icmp_seq=4 ttl=111 time=2.69 ms--- google.com ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3005msrtt min/avg/max/mdev = 2.550/2.739/2.940/0.142 msConnection to 172.17.0.1 closed.
As can be seen, the command is executed on the remote machine and when it finishes, the last line tells us that the connection is closed.
Proxy SSH
If you are browsing from an insecure location, or a place that has a proxy that doesn't allow access to certain ports, you can browse through the proxy of another machine using SSH
. This can be done by adding the -D
flag and the port through which you want to make the connection to the remote proxy. Since the port for tcp/ip
is 9999
, the command could look like ssh -D 9999 <user>@<id>
To make this look better, before running it I get my public IP
!curl ifconfig.me
188.127.184.59
Now I'm using the proxy of a web server that I have set up
!ssh -D 9999 root@194.62.99.222
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)* Documentation: https://help.ubuntu.com* Management: https://landscape.canonical.com* Support: https://ubuntu.com/advantageSystem information as of Wed Feb 22 06:08:51 AM UTC 2023System load: 0.02978515625Usage of /: 11.7% of 24.53GBMemory usage: 33%Swap usage: 0%Processes: 89Users logged in: 0IPv4 address for eth0: 194.62.99.222IPv4 address for eth1: 10.7.0.168IPv6 address for eth2: 2a04:3542:8000:1000:d48a:cbff:fefb:5b10 updates can be applied immediately.The list of available updates is more than a week old.To check for new updates run: sudo apt updateLast login: Wed Feb 22 06:02:35 2023 from 188.127.184.59root@server1:~#
Change the proxy configuration of my computer

Now I'm going to check my public IP again, but using the recently configured proxy
!curl -x socks5h://localhost:9999 ifconfig.me
194.62.99.222
We see that we obtain the public IP of the server
Remote graphical interface via SSH
In Linux, the graphical interface is a server, so we can take advantage of this and run programs with graphical interfaces that are on a remote machine via SSH
. To do this, you need to use the -X
flag. The command would be ssh -X <user>@<id>
First I log into my server and install xeyes
using sudo apt install x11-apps
and then I run it remotely from my computer.
!ssh -X root@194.62.99.222
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)Last login: Wed Feb 22 06:39:52 2023 from 188.127.184.59/usr/bin/xauth: file /root/.Xauthority does not existroot@server1:~sudo apt install x11-appsroot@server1:~#xeyes
Now on my computer the xeyes
window is opening but it's not running on my computer.

SSH Tunnel
As I mentioned, I have set up a server to which I have SSH access.
!ssh root@194.62.99.222
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)Last login: Wed Feb 22 06:40:58 2023 from 188.127.184.59root@server1:~#
And I also set up a second server from which I have access from server1
, but I don't have access from my computer.
Next, I try to access the server2
from my computer and we see that I cannot.
!ssh root@194.62.99.235
ssh: connect to host 194.62.99.235 port 22: Connection timed out
And then I try to access server2
from server1
and we see that I can.
!root@server1:~# ssh root@10.7.2.228
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)Last login: Wed Feb 22 06:59:01 2023 from 10.7.0.168root@server2:~#
So what we create is a tunnel from my computer to the server2
through the server1
, for this we use the -L
flag. To create the tunnel, you need to specify the port on your computer where you will create the tunnel, followed by the destination IP
of the tunnel, the port through which the tunnel will go, and finally the device that will create the tunnel. It would look like this
ssh -L <HOST PORT>:<DEST IP>:<TUNNEL PORT> <TUNNEL CREATOR USER>@<TUNNEL CREATOR IP>
Let's look at my example, I have server1
with a public IP
that we can call ip_pub1
and to which I have access via SSH
and a private IP
that we can call ip_priv1
which is within the same network as server2
. And I have server2
with a public IP
that we can call ip_pub2
to which I do not have SSH
access and a private IP
that we can call ip_priv2
within the same network as server1
.
First I create the tunnel
ssh -L host_port:ip_priv2:22 root@ip_pub1
I have created a tunnel to the private IP
of server2
through the public IP
of server1
Lastly, to connect to server2
, I do it through the localhost
and the host port that I have declared in the tunnel.
ssh -p 2020 root@localhost
Let's see it in reality, the IP
s of my servers are
server1
:Public IP
:194.62.99.222
IP
private:10.7.0.168
server2
:*Public IP
:194.62.99.235
Private IP
:10.7.2.228
First I create the tunnel
!ssh -L 2020:10.7.2.228:22 root@194.62.99.222
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)* Documentation: https://help.ubuntu.com* Management: https://landscape.canonical.com* Support: https://ubuntu.com/advantageSystem information as of Wed Feb 22 11:13:39 AM UTC 2023System load: 0.0Usage of /: 13.3% of 24.53GBMemory usage: 36%Swap usage: 0%Processes: 91Users logged in: 1IPv4 address for eth0: 194.62.99.222IPv4 address for eth1: 10.7.0.168IPv6 address for eth2: 2a04:3542:8000:1000:d48a:cbff:fefb:5b1101 updates can be applied immediately.60 of these updates are standard security updates.To see these additional updates run: apt list --upgradableLast login: Wed Feb 22 09:29:52 2023 from 188.127.184.59]0;root@server1: ~root@server1:~# ^C]0;root@server1: ~root@server1:~#
With the tunnel created, I can now connect to server2
from my computer.
!ssh -p 2020 root@localhost
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)* Documentation: https://help.ubuntu.com* Management: https://landscape.canonical.com* Support: https://ubuntu.com/advantageSystem information as of Wed Feb 22 11:14:15 AM UTC 2023System load: 0.0Usage of /: 13.3% of 24.53GBMemory usage: 33%Swap usage: 0%Processes: 90Users logged in: 0IPv4 address for eth0: 194.62.99.235IPv4 address for eth1: 10.7.2.228IPv6 address for eth2: 2a04:3542:8000:1000:d48a:cbff:fefb:7f47* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8sjust raised the bar for easy, resilient and secure K8s cluster deployment.https://ubuntu.com/engage/secure-kubernetes-at-the-edge101 updates can be applied immediately.60 of these updates are standard security updates.To see these additional updates run: apt list --upgradableLast login: Wed Feb 22 11:14:16 2023 from 10.7.0.168]0;root@server2: ~root@server2:~# ^C]0;root@server2: ~root@server2:~#
Reverse connection
Let's assume I want to connect to server2
, but now I can't establish a tunnel from server1
for whatever reason. What we can do is create a reverse connection from another server.
Suppose I have a third server, called server3
, which can be accessed via SSH
from anywhere, meaning both I from my computer and the server2
have access. Therefore, if we can physically access the server2
, we can establish a reverse connection from the server2
to the server3
.
ssh -R <server3port>:localhost:22 root@<IPserver3>
With this, what I have done is enable a connection from server3
to server2
(which was not possible before), through the localhost
and port server3port
of server3
Now from my computer I can connect to the server3
and from the server3
I can connect to the server2
through
ssh -p <server3port> root@localhost
Let's see it with the data from my servers
server2
:Public IP
:194.62.99.235
*server3
:Public IP
:194.62.96.236
First I make the reverse connection from server2
to server3
!root@server2:~# ssh -R 2020:localhost:22 root@194.62.96.236
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)Last login: Wed Feb 22 15:25:58 2023 from 188.127.184.59root@server3:~#
Now I connect to the server3
!ssh root@194.62.96.236
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)Last login: Wed Feb 22 15:12:19 2023 from 188.127.184.59root@server3:~#
And now that I'm on the server3
, I connect to the server2
.
!root@server3:~# ssh -p 2020 root@localhost
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)Last login: Wed Feb 22 15:12:07 2023 from 188.127.184.59root@server2:~#
Achieved! Through my computer I cannot connect directly to the server2
, but by connecting to the server3
I was able to access the server2
thanks to the reverse connection I had made from the server2
to the server3
.
Jump
Finally, another way to access server2
is by first entering server1
and then, from server1
, accessing server2
. However, this can be a bit cumbersome because you first need to make an SSH
connection to server1
and then another one to server2
. So, to do it all in one step, we can use the -J
(jump
) flag, which would look like ssh -J server1 server2
.
Summary, first we would do ssh root@194.62.99.222
and then ssh root@10.7.2.228
(since inside server1
we connect to server2
via the private IP
).
So we could do it all in one go with ssh -J root@194.62.99.222 root@10.7.2.228
Let's give it a try
!ssh -J root@194.62.99.222 root@10.7.2.228
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 06:46:11 2023 from 10.7.0.168root@server2:~#
We have been able to make the jumps!
User's SSH
configuration file
Devices with Aliases
In every computer there is a configuration file for SSH
which usually resides in the user's folder.
!cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost 192.168.1.138HostName 192.168.1.138User maximo.fernandez
In this file, I have stored the user credentials and IP of some devices that I usually connect to so I don’t have to fill everything out myself. Let’s take a look at it with the servers I have.
My server server1
has the user root
and the IP 194.62.99.222
, so I add it to the list.
!echo "Host server1 HostName 194.62.99.222 User root" >> ~/.ssh/config
Let's take another look at the configuration file.
!cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost 192.168.1.138HostName 192.168.1.138User maximo.fernandezHost server1HostName 194.62.99.222User root
Now that we have added it to connect to server1
, we only need to do ssh server1
!ssh server1
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 05:18:59 2023 from 188.127.184.59root@server1:~#
Proxy
As we have seen, by adding the flag -D <port>
we could change the proxy. To save this in the configuration file, we just need to add the line DynamicForward <port>
to the host we are saving.
Repeating the previous example where we used server1
as a TCP/IP
port (9999
) proxy, the configuration file would look like this
Host proxyServer1
HostName 194.62.99.222
User root
DynamicForward 9999
We add it
!echo "Host proxyServer1 HostName 194.62.99.222 User root DynamicForward 9999" >> ~/.ssh/config
Let's see how the configuration file looks like
!cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost 192.168.1.138HostName 192.168.1.138User maximo.fernandezHost server1HostName 194.62.99.222User rootHost proxyServer1HostName 194.62.99.222User rootDynamicForward 9999
I get my IP
address
!curl ifconfig.me
188.127.184.59
I connect to the proxy server
!ssh proxyServer1
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 05:42:32 2023 from 188.127.184.59root@server1:~#
Change the proxy configuration of my computer

I check my public IP
again, but using the recently configured proxy
!curl -x socks5h://localhost:9999 ifconfig.me
194.62.99.222
We see that we obtain the public IP of the server
SSH Tunnel
If I want to create a tunnel to server2
through server1
as before, we used to do ssh <HOST PORT>:<DEST IP>:<TUNNEL PORT> <TUNNEL CREATOR USER>@<TUNNEL CREATOR IP>
, now we have to add the line
``` bash
LocalForward <localhost>:<HOST PORT> <DEST IP>:<TUNNEL PORT>```
That is, the configuration file would be
Host tunnelToServer2
HostName 194.62.99.222
User root
LocalForward 127.0.0.1:2020 10.7.2.228:22
But that doesn't quite make sense, let's look at it with something concrete.
server1
:Public IP
:194.62.99.222
IP
private:10.7.0.168
server2
:Public IP
:194.62.99.235
IP
private:10.7.2.228
Before, the command was
ssh -L 2020:10.7.2.228:22 root@194.62.99.222
So the configuration file should look like this:
Host tunnelToServer2
HostName 194.62.99.222
User root
LocalForward 127.0.0.1:2020 10.7.2.228:22
Let's see if it works
We add the new configuration
!echo "Host tunelToServer2 HostName 194.62.99.222 User root LocalForward 127.0.0.1:2020 10.7.2.228:22" >> ~/.ssh/config
Let's see how the configuration file looks like
!cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost 192.168.1.138HostName 192.168.1.138User maximo.fernandezHost server1HostName 194.62.99.222User rootHost proxyServer1HostName 194.62.99.222User rootDynamicForward 9999Host tunelToServer2HostName 194.62.99.222User rootLocalForward 127.0.0.1:2020 10.7.2.228:22
We create the tunnel
!ssh tunelToServer2
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 06:02:20 2023 from 188.127.184.59root@server1:~#
Now we try to connect to the server2
from my computer.
!ssh -p 2020 root@localhost
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 06:02:36 2023 from 10.7.0.168root@server2:~#
Got it! But we can make everything a bit cleaner, we can add this last connection to the configuration file.
!echo "Host server2ByTunel HostName localhost User root Port 2020" >> ~/.ssh/config
Let's see how the configuration file looks like
!cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost 192.168.1.138HostName 192.168.1.138User maximo.fernandezHost server1HostName 194.62.99.222User rootHost proxyServer1HostName 194.62.99.222User rootDynamicForward 9999Host tunelToServer2HostName 194.62.99.222User rootLocalForward 127.0.0.1:2020 10.7.2.228:22Host server2ByTunelHostName localhostUser rootPort 2020
Now we connect back to server2
from my computer, through the tunnel, but with the last configuration we just saved.
!ssh server2ByTunel
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 06:13:33 2023 from 10.7.0.168root@server2:~#
In summary, with everything we have done, we can create the tunnel to server2
with the command ssh tunelToServer2
and then connect to server2
with the command ssh server2ByTunel
Amazing!
Reverse Connection
We remember that our problem now was that we couldn't connect to server2
through the tunnel of server1
. So, by creating a reverse connection from server2
(we have someone on server2
who can make that reverse connection, or we set it up ourselves before leaving) to a server3
, I can connect from my computer to server3
and then connect to server2
.
First, we need to make the reverse connection from server2
to server3
. We could do this with a command.
ssh -R <server3port>:localhost:22 root@<IPserver3>
Or save the connection in the configuration file by adding
Host reverseToServer3
HostName <IPserver3>
User root
RemoteForward <server3port> localhost:22
And make the inverse connection through
ssh reverseToServer3
Let's look at it with concrete data.
server2
:Public IP
:194.62.99.235
server3
:Public IP
:194.62.96.236
To make the reverse connection, you would have to use the command
ssh -R 2020:localhost:22 root@194.62.96.236
or save the following configuration
Host reverseToServer3
HostName 194.62.96.236User root
RemoteForward 2020 localhost:22
And connect through
ssh reverseToServer3
So I save the configuration on server 2 and make the connection
!root@server2:~# echo "Host reverseToServer3 HostName 194.62.96.236 User root RemoteForward 2020 localhost:22" >> ~/.ssh/config
Let's check if it has been saved properly
!root@server2:~# cat .ssh/config
Host reverseToServer3HostName 194.62.96.236User rootRemoteForward 2020 localhost:22
I make the reverse connection
!root@server2:~# ssh reverseToServer3
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)Last login: Wed Feb 22 15:26:18 2023 from 194.62.99.235root@server3:~#
Jump
As we said, we made jumps using the -J
flag, so with the command ssh -J root@194.62.99.222 root@10.7.2.228
we could connect to server2
.
To configure the configuration file, there are two options
The first is that since we already have server1
saved in the configuration file, we only need to add server2
.
Host server2
HostName 10.7.2.228
User root
And then we could connect via
ssh -J server1 server2
Let's test it out
!echo "Host server2 HostName 10.7.2.228 User root " >> ~/.ssh/config
We see the configuration file
!cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost 192.168.1.138HostName 192.168.1.138User maximo.fernandezHost server1HostName 194.62.99.222User rootHost proxyServer1HostName 194.62.99.222User rootDynamicForward 9999Host tunelToServer2HostName 194.62.99.222User rootLocalForward 127.0.0.1:2020 10.7.2.228:22Host server2ByTunelHostName localhostUser rootPort 2020Host server2HostName 10.7.2.228User root
Now we connect through the jumps
!ssh -J server1 server2
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 12:05:16 2023 from 10.7.0.168root@server2:~#
This has been the first option: to save each server and set the jumps; but a second option is to save all the jumps in a single configuration, which would look like this
Host server2jumping
HostName 10.7.2.228
User root
ProxyJump root@194.62.99.222
And it would only be left to connect via
ssh server2jumping
Let's give it a try
!echo "Host server2jumping HostName 10.7.2.228 User root ProxyJump root@194.62.99.222" >> ~/.ssh/config
Let's take a look at the configuration file
!cat ~/.ssh/config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_configHost 192.168.1.138HostName 192.168.1.138User maximo.fernandezHost server1HostName 194.62.99.222User rootHost proxyServer1HostName 194.62.99.222User rootDynamicForward 9999Host tunelToServer2HostName 194.62.99.222User rootLocalForward 127.0.0.1:2020 10.7.2.228:22Host server2ByTunelHostName localhostUser rootPort 2020Host server2HostName 10.7.2.228User rootHost server2jumpingHostName 10.7.2.228User rootProxyJump root@194.62.99.222
Now we try to connect
!ssh server2jumping
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)Last login: Fri Feb 24 12:06:22 2023 from 10.7.0.168root@server2:~#
System SSH
configuration file
We previously looked at the user's SSH
configuration file, where we store settings for machines we want to connect to via SSH
. However, there is another SSH
configuration file, but in this case it is for the system, located at /etc/ssh/ssh_config
. Let's take a look at it.
!cat /etc/ssh/sshd_config
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $# This is the sshd server system-wide configuration file. See# sshd_config(5) for more information.# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin# The strategy used for options in the default sshd_config shipped with# OpenSSH is to specify options with their default value where# possible, but leave them commented. Uncommented options override the# default value.Include /etc/ssh/sshd_config.d/*.conf#Port 22#AddressFamily any#ListenAddress 0.0.0.0#ListenAddress ::#HostKey /etc/ssh/ssh_host_rsa_key#HostKey /etc/ssh/ssh_host_ecdsa_key#HostKey /etc/ssh/ssh_host_ed25519_key# Ciphers and keying#RekeyLimit default none# Logging#SyslogFacility AUTH#LogLevel INFO# Authentication:#LoginGraceTime 2m#PermitRootLogin prohibit-password#StrictModes yes#MaxAuthTries 6#MaxSessions 10#PubkeyAuthentication yes# Expect .ssh/authorized_keys2 to be disregarded by default in future.#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2#AuthorizedPrincipalsFile none#AuthorizedKeysCommand none#AuthorizedKeysCommandUser nobody# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts#HostbasedAuthentication no# Change to yes if you don't trust ~/.ssh/known_hosts for# HostbasedAuthentication#IgnoreUserKnownHosts no# Don't read the user's ~/.rhosts and ~/.shosts files#IgnoreRhosts yes# To disable tunneled clear text passwords, change to no here!#PasswordAuthentication yes#PermitEmptyPasswords no# Change to yes to enable challenge-response passwords (beware issues with# some PAM modules and threads)ChallengeResponseAuthentication no# Kerberos options#KerberosAuthentication no#KerberosOrLocalPasswd yes#KerberosTicketCleanup yes#KerberosGetAFSToken no# GSSAPI options#GSSAPIAuthentication no#GSSAPICleanupCredentials yes#GSSAPIStrictAcceptorCheck yes#GSSAPIKeyExchange no# Set this to 'yes' to enable PAM authentication, account processing,# and session processing. If this is enabled, PAM authentication will# be allowed through the ChallengeResponseAuthentication and# PasswordAuthentication. Depending on your PAM configuration,# PAM authentication via ChallengeResponseAuthentication may bypass# the setting of "PermitRootLogin without-password".# If you just want the PAM account and session checks to run without# PAM authentication, then enable this but set PasswordAuthentication# and ChallengeResponseAuthentication to 'no'.UsePAM yes#AllowAgentForwarding yes#AllowTcpForwarding yes#GatewayPorts noX11Forwarding yes#X11DisplayOffset 10#X11UseLocalhost yes#PermitTTY yesPrintMotd no#PrintLastLog yes#TCPKeepAlive yes#PermitUserEnvironment no#Compression delayed#ClientAliveInterval 0#ClientAliveCountMax 3#UseDNS no#PidFile /var/run/sshd.pid#MaxStartups 10:30:100#PermitTunnel no#ChrootDirectory none#VersionAddendum none# no default banner path#Banner none# Allow client to pass locale environment variablesAcceptEnv LANG LC_*# override default of no subsystemsSubsystem sftp /usr/lib/openssh/sftp-server# Example of overriding settings on a per-user basis#Match User anoncvs# X11Forwarding no# AllowTcpForwarding no# PermitTTY no# ForceCommand cvs server
With this file, we can change the configuration of how SSH
works on our computer. For example, we can see a commented line that says
#Port 22
If we uncomment it and change the SSH
port number, SSH will no longer use port 22, which is its default port, and will instead use the port number specified there.
Copying files over SSH
We can copy files via SSH
using the scp
(secure copy) command. For this, the syntax is
scp <path local file> <user>@<IP>:<path to save>
o
``` bash
scp <user>@<ip>:<path to remote file> <path to save>```
The first way copies a file from our computer to another, and the second way copies a file from another to ours.
For example, let's do a ls
of server1
!ssh -t server1 "ls"
snapConnection to 194.62.99.222 closed.
Let's see now what we have locally that we can pass on
!ls
2021-02-11-Introduccion-a-Python.ipynb html_files2021-04-23-Calculo-matricial-con-Numpy.ipynb html.ipynb2021-06-15-Manejo-de-datos-con-Pandas.ipynb introduccion_python2022-09-12-Introduccion-a-la-terminal.ipynb mi_paquete_de_python2023-01-22-Docker.ipynb movies.csv2023-02-01-Bash-scripting.ipynb movies.dat2023-02-04-Blip-2.ipynb notebooks_translated2023-XX-XX-SSH.ipynb __pycache__california_housing_train.csv scripts_bashcommand-line-cheat-sheet.pdf ssh.ipynbCSS.ipynb test.ipynb'Expresiones regulares.ipynb'
Let's send the html.ipynb
file to the server since it takes up little space.
!scp html.ipynb server1:/root/
html.ipynb 100% 14KB 229.0KB/s 00:00
Let's check what's inside server1
again.
!ssh -t server1 "ls"
html.ipynb snapConnection to 194.62.99.222 closed.
It has been copied
File Synchronization via SSH
The downside of the scp
command is that if something happens during the copy process and the file doesn't finish copying, when you try again, you have to start from scratch. This is especially a problem with very large files.
To solve this, you can use rsync
, the syntax is
rsync --partial --progress --rsh=ssh <local file path> <user>@<IP>:<path to save>
o
``` bash
rsync --partial --progress --rsh=ssh
Just like before, the first method copies a file from our computer to another and the second from another to ours. The --partial
flag is to indicate that partially copied files should be saved, meaning that if the copy stops before it finishes, what has been copied will remain. The --progress
flag is to indicate that it should show the progress of the copy. The --rsh=ssh
flag is to indicate that file transfer should be done via SSH
.
We pass a file
!rsync --partial --progress -rsh=ssh 2021-06-15-Manejo-de-datos-con-Pandas.ipynb server1:/root/
sending incremental file list2021-06-15-Manejo-de-datos-con-Pandas.ipynb608.34K 100% 197.78MB/s 0:00:00 (xfr#1, to-chk=0/1)
And we see if it has been copied
!ssh -t server1 "ls"
2021-06-15-Manejo-de-datos-con-Pandas.ipynb html.ipynb snapConnection to 194.62.99.222 closed.
Mounting Remote Folders Locally
In the case that we want to have a folder from another machine as if it were on our computer, we need to use sshfs
First, it is necessary to install it via
sudo apt install sshfs
And once it's installed, it's used with the syntax
sshfs <user>@<ip>:<remote path> <local path to mount>
We are going to mount the /root
folder of server1
, but first we need to create a folder where we will mount it.
!mkdir server1folder
We see that, within the folder we have mounted, there is nothing
!ls server1folder
Now we mount the server folder
!!sshfs server1:/root/ server1folder
Let's check what's inside again
!ls server1folder
2021-06-15-Manejo-de-datos-con-Pandas.ipynb html.ipynb snap
When we no longer want to have the folder mounted, we can unmount it using fusermount -u server1folder
!!fusermount -u server1folder
We look inside again to see if there is nothing.
!ls server1folder
Debugging the SSH
Connection
We can debug the SSH
connection by adding from -v
to -vvvv
to the connection; the more v
s we add, the higher the level of information.
!ssh -v server1
OpenSSH_8.2p1 Ubuntu-4ubuntu0.5, OpenSSL 1.1.1f 31 Mar 2020debug1: Reading configuration data /home/wallabot/.ssh/configdebug1: /home/wallabot/.ssh/config line 6: Applying options for server1debug1: Reading configuration data /etc/ssh/ssh_configdebug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no filesdebug1: /etc/ssh/ssh_config line 21: Applying options for *debug1: Connecting to 194.62.99.222 [194.62.99.222] port 22.debug1: Connection established.debug1: identity file /home/wallabot/.ssh/id_rsa type 0debug1: identity file /home/wallabot/.ssh/id_rsa-cert type -1debug1: identity file /home/wallabot/.ssh/id_dsa type -1debug1: identity file /home/wallabot/.ssh/id_dsa-cert type -1debug1: identity file /home/wallabot/.ssh/id_ecdsa type -1debug1: identity file /home/wallabot/.ssh/id_ecdsa-cert type -1debug1: identity file /home/wallabot/.ssh/id_ecdsa_sk type -1debug1: identity file /home/wallabot/.ssh/id_ecdsa_sk-cert type -1debug1: identity file /home/wallabot/.ssh/id_ed25519 type -1debug1: identity file /home/wallabot/.ssh/id_ed25519-cert type -1debug1: identity file /home/wallabot/.ssh/id_ed25519_sk type -1debug1: identity file /home/wallabot/.ssh/id_ed25519_sk-cert type -1debug1: identity file /home/wallabot/.ssh/id_xmss type -1debug1: identity file /home/wallabot/.ssh/id_xmss-cert type -1debug1: Local version string SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5debug1: Remote protocol version 2.0, remote software version OpenSSH_8.9p1 Ubuntu-3debug1: match: OpenSSH_8.9p1 Ubuntu-3 pat OpenSSH* compat 0x04000000debug1: Authenticating to 194.62.99.222:22 as 'root'debug1: SSH2_MSG_KEXINIT sentdebug1: SSH2_MSG_KEXINIT receiveddebug1: kex: algorithm: curve25519-sha256debug1: kex: host key algorithm: ecdsa-sha2-nistp256debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: nonedebug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: nonedebug1: expecting SSH2_MSG_KEX_ECDH_REPLYdebug1: Server host key: ecdsa-sha2-nistp256 SHA256:jwpQt2a69LQcuvvYPPKL32bBwTi1Je/ZmUdr4zEiD1Ydebug1: Host '194.62.99.222' is known and matches the ECDSA host key.debug1: Found key in /home/wallabot/.ssh/known_hosts:14debug1: rekey out after 134217728 blocksdebug1: SSH2_MSG_NEWKEYS sentdebug1: expecting SSH2_MSG_NEWKEYSdebug1: SSH2_MSG_NEWKEYS receiveddebug1: rekey in after 134217728 blocksdebug1: Will attempt key: /home/wallabot/.ssh/id_rsa RSA SHA256:ID3HcrbyPBGjFx/qeiJK50eqihLGrpDVu02oRSyKGh4 agentdebug1: Will attempt key: wallabot@wallabot RSA SHA256:Qlq6hXbToInW+efEK666BFT26EeUSpBhzcqxTLrDBpQ agentdebug1: Will attempt key: /home/wallabot/.ssh/id_dsadebug1: Will attempt key: /home/wallabot/.ssh/id_ecdsadebug1: Will attempt key: /home/wallabot/.ssh/id_ecdsa_skdebug1: Will attempt key: /home/wallabot/.ssh/id_ed25519debug1: Will attempt key: /home/wallabot/.ssh/id_ed25519_skdebug1: Will attempt key: /home/wallabot/.ssh/id_xmssdebug1: SSH2_MSG_EXT_INFO receiveddebug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,sk-ssh-ed25519@openssh.com,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ecdsa-sha2-nistp256@openssh.com,webauthn-sk-ecdsa-sha2-nistp256@openssh.com>debug1: kex_input_ext_info: publickey-hostbound@openssh.com (unrecognised)debug1: SSH2_MSG_SERVICE_ACCEPT receiveddebug1: Authentications that can continue: publickeydebug1: Next authentication method: publickeydebug1: Offering public key: /home/wallabot/.ssh/id_rsa RSA SHA256:ID3HcrbyPBGjFx/qeiJK50eqihLGrpDVu02oRSyKGh4 agentdebug1: Authentications that can continue: publickeydebug1: Offering public key: wallabot@wallabot RSA SHA256:Qlq6hXbToInW+efEK666BFT26EeUSpBhzcqxTLrDBpQ agentdebug1: Server accepts key: wallabot@wallabot RSA SHA256:Qlq6hXbToInW+efEK666BFT26EeUSpBhzcqxTLrDBpQ agentdebug1: Authentication succeeded (publickey).Authenticated to 194.62.99.222 ([194.62.99.222]:22).debug1: channel 0: new [client-session]debug1: Requesting no-more-sessions@openssh.comdebug1: Entering interactive session.debug1: pledge: networkdebug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0debug1: Remote: /root/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwardingdebug1: Remote: /root/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwardingdebug1: Sending environment.debug1: Sending env LANG = es_ES.UTF-8Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)* Documentation: https://help.ubuntu.com* Management: https://landscape.canonical.com* Support: https://ubuntu.com/advantageSystem information as of Fri Feb 24 01:25:10 PM UTC 2023System load: 0.0Usage of /: 15.2% of 24.53GBMemory usage: 34%Swap usage: 0%Processes: 89Users logged in: 0IPv4 address for eth0: 194.62.99.222IPv4 address for eth1: 10.7.0.168IPv6 address for eth2: 2a04:3542:8000:1000:d48a:cbff:fefb:5b1* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8sjust raised the bar for easy, resilient and secure K8s cluster deployment.https://ubuntu.com/engage/secure-kubernetes-at-the-edge43 updates can be applied immediately.To see these additional updates run: apt list --upgradableLast login: Fri Feb 24 13:10:05 2023 from 188.127.184.59]0;root@server1: ~root@server1:~# ^C]0;root@server1: ~root@server1:~#