Creation of SSH tunnels through jump host and obtaining of an access to target host's SSH daemon which have no public IP.

There how it looks like

Description of tunnels

  1. Reverse tunnel – created from Target host (TH) to Jump host (JH). Creating socket on JH which forwards all traffic to some port on TH.
  2. Straight tunnel – created from Client host (CH) to JH. Creating socket on CH which forwards all traffic to some port on JH.

Hence, having such tunnels allows us to get an access to some port on TH. We can proxy one single port – SSH server port from TH and then establish SSH connection or create SOCKS5 proxy directly with TH.

Creation of tunnel user at JH

In order to make tunnels it is very handy to have special nologin user. Lets name it tunnel. Code creates user without home directory and entry shell. Also we need to restrict authentication method to password only.

sudo adduser -s /bin/false -M -N tunnel
sudo usermod -d / tunnel
echo 'tunnel:tunnel' | sudo chpasswd
cat <<EOF | sudo tee -a /etc/ssh/sshd_config

Match User tunnel
    PasswordAuthentication yes
    AuthenticationMethods "password"
EOF
sudo systemctl restart sshd

Reverse tunnel

Lets create reverse tunnel from TH to JH. Code below use utility sshpass which enters SSH password automatically. Can be installed on Ubuntu by default or from EPEL repository on CentOS.

if command -v apt; then
    sudo apt update
    sudo apt install -y sshpass
elif command -v yum; then
    sudo yum install -y epel-release
    sudo yum makecache fast
    sudo yum install sshpass
fi

Lets finally create the tunnel. Execute the following on TH.

sshpass -p 'tunnel' ssh -o StrictHostKeyChecking=no -fNR 2222:localhost:22 [email protected]

sshpass -p 'tunnel' – using of sshpass in order to automate entering of SSH password. This section can be omitted.

ssh -o StrictHostKeyChecking=no -fNR – calling ssh ignoring host key checking – do not do this :) You should create first tunnel manually and print yes confirming host key check at first SSH session. After that moment, you can prepend sshpass utility and all will work. In case if you as lazy, as I, and was not been hacked because of laziness – you're welcome.

2222:localhost:22 – tunnel configuration has format <address on start of tunnel>:<port on start of tunnel>:<adress on the end of tunnel>:<port on the end of tunnel>. Hence, command above does the following: proxy all requests from 127.0.0.1:2222 (default value of address is localhost) of JH to 127.0.0.1:22 on TH. Now we have an access to have SSH server on TH from JH. You can check that executing ssh -p 2222 localhost from JH.
Notice: the start of the reverse tunnel is on remote server (JH in our case) while the end is on localhost (TH in our case). In case of using of straight tunnel – swapped.

Straight tunnel

Lets create straight tunnel from CH to JH. Execute the following on CH.

sshpass -p 'tunnel' ssh -o StrictHostKeyChecking=no -fNL 2222:localhost:2222 [email protected]

2222:localhost:2222 – proxy all requests from 127.0.0.1:2222 of CH to 127.0.0.1:2222 on TH. In fact, we forward traffic from CH:2222 to TH:22.
Checking of the tunnel can be done executing netstat -tunlp on the host where it starts, or simply using it.

SOCKS5 proxy

If you want to have access to some services on multiple ports from TH network you can use it as SOCKS5 proxy as follows. Execute following command on CH.

ssh -fND 1329 -p 2222 [email protected]

Now, simply navigate to Settings of your browser, type proxy in search bar, open proxy settings and set SOCKS5 proxy to localhost:1329 and do not forget to tick Proxy DNS over proxy.