Another option is to use an SSH option called ProxyCommand
.
I'm going to define certain things. Your personal computer is C1, the intermediate computer is JH (from Jump Host ) and C2 is the final computer.
For this you do not need to be a root user, what you need is:
Have a pair of keys in C1 to connect C1 with JH
Have a pair of keys in JH to connect JH with C2
Have a pair of keys in C2 to connect C2 with JH
(optional) Create special users in JH and in C2 with the permissions you want to give them. This is just to make the matter a little less tangled.
Inside C2
In user C2 you do a port forwarding in both directions.
$ ssh -f -N -L <puerto C2>:<ip de JH>:22 -R <puerto JH>:127.0.0.1:22 usuarioJH@<ip de JH>
Where
- port C2: it is a port for C2 where traffic will be received from JH.
- JH ip: is the ip of the intermediate server.
- port JH: is the port from which JH can connect to C2.
Remember that in general, if you do not have root permissions to the system, you can not choose ports smaller than 1024.
The flags of -f
and -N
allow the command in C2 to run in background and not to execute remote commands.
The -L
option allows traffic from port 22 of JH to be redirected to puerto C2
of C2. The -R
option allows traffic from port 22 of C2 to be redirected to puerto JH
.
Inside JH
After what has been done in C2, you can enter JH first and run something like ssh -p <puerto JH> [email protected]
and enter C2 from JH.
But that's just to verify that the connection is well made, one step is still missing.
Inside C1
With your ~/.ssh/config
configured with the specifications.
Host C2
User usuarioC2
ProxyCommand ssh -W 127.0.0.1:<puerto JH> usuarioJH@<ip de JH>
You could already enter your C2 server from C1 with:
$ ssh C2
This way you could even do port forwarding , scp
or sftp
from those servers.
$ ssh -N -f -L 3306:127.0.0.1:3306 C2
$ scp C2:~/archivo_en_c2 archivo_de_c2
$ sftp -P <puerto JH> [email protected]
Recommendation
As the command in C2 can sometimes conflict or someone could turn off C2, it is useful to have a script that saves running the process inside C2.
#!/bin/bash
check_and_create_tunnel() {
ssh "[email protected]" -p $C2_PORT "netstat -tpln 2> /dev/null | grep $JH_PORT" &> /dev/null
if [[ "$?" != 0 ]]
then
ssh_process="$(ps -fea | egrep "ssh.*$C2_PORT" | head -n -1 | awk '{print $2}' )"
[[ -n "$ssh_process" ]] && echo "$ssh_process" | xargs kill &> /dev/null
#El famoso tunel.
ssh -f -N -R "$JH_PORT:127.0.0.1:22" -L "$C2_PORT:$JH_IP:22" "$JH_USER@$JH_IP" &> /dev/null
fi
}
check_and_create_tunnel
That basically checks if you can do a netstat
(can be another command) in JH and if you can not, then look for the processes that involve the port and send them a sigterm, then make the tunnel.
Like triviality, check if JH has installed netstat
.
Run this script as a cronjob or when starting C2.
Something that I do not remember well that can happen is that you have problems when ssh asks you if you want to connect to the verified Host, that can interfere with the connection the first time. In case that happens (which I do not remember well) there are several options that I do. One is to connect from C1 to JH by accepting all the options and then connect from JH to C2 accepting all the options. Another is putting the following in the configuration file of userJH and userC2
Host *
StrictHostKeyChecking no
Final Note
All this I wrote presupposing that.
The public key of userC1 is in the file ~/.ssh/authorized_keys
of userJH
The public user keyJH is in the file ~/.ssh/authorized_keys
of userC2
The public key of userC2 is in the file ~/.ssh/authorized_keys
of userJH
Where none of the users is necessarily root.