I have a situation where our Ubuntu servers were deployed across multiple remote locations. These servers were behind a carrier grade NAT and also an internal NAT. Now from a central location I want to access it any time I want, but I am also behind a NAT similar to those servers.
When those servers are online I want to access it (through SSH or SSH tunnel). I know I can't access like servers that have a public IP, but maybe somehow I can access it through TeamViewer's working principle. For this method if I need another public server I can manage it in Google Compute Engine.
Best Answer
If we have access to a server with public IP address, then we can use it as a gateway. We could achieve this via Reverse SSH Port Forwarding connections. Let’s say we have three instances:
Public Server: Here we have an operational SSH server and public IP address (and/or domain name). We are able to connect to this server with public-private key pair, which is not passphrase protected (setup reference).
Private Server: Here we have an operational SSH server. It is behind a Firewall (NAT, ISP, etc.) and doesn't have a public IP address, but we are able to establish a SSH connection from it to the Public Server, so here we have also SSH client.
Client Machine: Here we (need to) have only SSH client. We are able to establish a SSH connection to the Public Server. We want to establish a SSH connection from this instance to the Private Server.
The principal level
At principal level we could apply at least two scenarios.
Scenario 1. Where we don’t want to open an additional ports in the Public Server’s Firewall:
Scenario 2. Where we are inclined to open an additional port in the Public Server’s Firewall:
The main advantage of the Scenario 1 is that we don’t need to think how secure is our Private Server. The main advantage of the Scenario 2 is that we ommit one step, but in this case we should think about the security of the Private Server, because it becomes public accessible through the forwarded port. In addition, these scenarios could be applied to different port and services, not only SSH, for example to HTTP.
How to apply Scenario 1 within Ubuntu
Establish SSH connection with Port Forwarding from the Private Server to the Public Server
We could do that by the command:
-p 22
provides the SSH port of the Public Server (it is not mandatory).-i ~/.ssh/pass-less/id_rsa
provides the authentication key file.-R 2222:127.0.0.1:22
means that port2222
on the (remote) Public Server will be forwarded to the SSH port of the (local) Private Server that, in this case, is22
.We can push this connection into the background by adding the options
-fTN
(of the OpenSSH Client – reference). We could use also the toolautossh
to be sure the connection will be kept alive for a long period of time (reference):We can simplify the above command by implementation of the following lines in our
~/.ssh/config
file:In this case the above command will become:
We can easily automate this task on system reboot by the next Cron job (or we could create service that should be the better approach):
Once this connection is established we can connect to the Private Server from the Public Server, through the reverse tunnel, by the command:
Establish SSH connection with Port Forwarding from the Client Machine to the Public Server
We could do that by the command:
-L 1111:127.0.0.1:2222
means that port1111
on the (local) Client Machine will be forwarded to the (remote) Public Server’s port2222
(that is forwarded to the SSH port of the Private Server). Note we could use-L 2222:127.0.0.1:2222
.-fTN
these options will push the connection into the background as it is described above.We can implement also
autossh
and~/.ssh/config
file, with directiveRemoteForward
orLocalForward
.Connect to the Private Server from the Client Machine through itself
Once the above two steps are implemented, we can connect from the Client Machine to the Public Server by the command:
How to apply Scenario 2 within Ubuntu
Establish SSH connection with Port Forwarding from the Private Server to the Public Server
This step is identical as the first one from the Scenario 1, but few additional things should be done.
Open the forwarded port
2222
on the Public Server’s Firewall - this is out of the scope of this answer.Modify
/etc/ssh/sshd_config
of the Public Server and add the next directive, that will allow to open our SSH tunnel to public (don't forget to restart the server:sudo systemctl restart sshd.service
):Make our SSH tunnel open to public. This step is well described within the question: (How to make ssh tunnel open to public?). According to the answers there we could add the
-g
option to the commands that make a connection between the Private and the Public servers:Or, alternatively, instead that we could modify the
~/.ssh/config
file in this way:Finally we should
killall autossh
and establish the connection again.Connect to the Private Server from the Client Machine through the Public Server
Once the above step is performed, we can achieve our goal by the command: