Kelvin DeCosta

Accessing NAT restricted servers

23 Mar 2020
7 min

Have you ever needed secure access to a system while operating outside of its local network?

For quite some time now, I have been using on a powerful server. Unfortunately, I could only connect to it while within its network.

The situation

In this guide, I will walk you through how I bypassed this restriction.

Network administrators have their reasons for restricting specific systems. To avoid trouble, please consult them before trying this out.


I will be using the following convention when referring to the 3 systems.

Host User Description
local kelvin Your personal computer
proxy middle A proxy server
restricted hacker The restricted system


You will need prior access to restricted to set up the tunnel.

A case with the main requirement

This “hack” works by setting up a reverse SSH tunnel from the NAT-restricted system to a proxy server.

Once the tunnel is up and running, you can securely connect to restricted via proxy.

Cloud hosting platforms like Amazon Web Services, Microsoft Azure & Google Cloud provide services to set up virtual servers that can perform the necessary functionality.


I should advise you to read the steps carefully before executing any of the commands. Do not blindly copy and paste the commands into your terminal. Almost all of them require a slight correction.

Setup proxy

In my case, I used an AWS EC2 instance running Ubuntu. This guide assumes that proxy is running Linux. Keep this in mind before setting things up.

A case with a freshly set up proxy server

  • Secure access to proxy

    Regardless of your choice of a cloud platform, you would have received a key file that enables you to connect to proxy.

    To use this file, restrict the permissions on it.

    chmod 400 <path to 'proxy.pem'>

    In this guide, you will need to transfer this key to restricted. Instead of this, you could create a new key pair and set proxy to work with it.

  • Filter incoming connections

    Create a security rule allowing inbound TCP connections on a non-standard port of your choice, port-A.

    We will be forwarding traffic on port port-A of proxy to port 22 of restricted.

    Here is an interesting article on how 22 became the default port for SSH.

Configure local

Setup up an SSH config file. This will alow you to easily connect to a server by simply specifying an alias.

touch ~/.ssh/config

Use the following skeleton template and make the necessary changes to it.

Host restricted
    HostName <The address for 'restricted' within the network>
    User hacker
Host proxy
    HostName <The DNS address for 'proxy'>
    User middle
    IdentityFile <path to 'proxy.pem'>
Host restricted-via-proxy
    HostName <The DNS address for 'proxy'>
    User hacker
    IdentityFile <path to 'proxy.pem'>
    Port 'port-A'

The configuration is in effect as soon as the file is saved.

A case with a configured local system

This configuration is not necessary for actually setting up the tunnel. It just makes the process very convenient.

I should mention that all the following commands use the aliases set in this template.

Configure proxy

  • Connect to proxy from local

    ssh proxy
  • Configure the system wide SSH configuration file

    sudo nano /etc/ssh/sshd_config

    Set GatewayPorts to yes.

    #AllowAgentForwarding yes
    #AllowTcpForwarding yes
    GatewayPorts yes
    X11Forwarding yes
    #X11DisplayOffset 10
    #X11UseLocalhost yes
    #PermitTTY yes
  • Restart the SSH service

    sudo service ssh restart

A case with a configured proxy server

Once the tunnel is set up, we would be able connect to restricted by first connecting to proxy explicitly. The above set of steps lets us do this implicitly with just one command, as we will see later.

Configure restricted

  • Securely transfer proxy key file from local to restricted

    As mentioned previously, in order to set up the tunnel, we need the key file for proxy.

    scp <path to 'proxy.pem'> restricted:~/.ssh/keys
  • Connect to restricted from local

    ssh restricted
  • Setup up an SSH Config file

    touch ~/.ssh/config

    Once again, use the following template and make the necessary changes to it.

    Host proxy
      HostName <The DNS address for 'proxy'>
      User middle
      IdentityFile <path to 'proxy.pem'>
  • Restrict permissions on the key file

    chmod 400 <path to 'proxy.pem'>
  • Create the tunnel

    Install autossh if necessary.

    autossh -M 'port-B' -N -f -R 'port-A':localhost:22 proxy
    Flag Value Description
    -M port-B Sets a monitoring port
    -N - Without this flag, autossh opens a shell for proxy
    -f - Set the tunnel to work in the background
    -R port-A:localhost:22 Sets reverse tunnel from port-A on proxy to 22 on restricted

A case with a configured restricted system

Tunnel Automation

If restricted is restarted frequently, it might be helpful to automate the creation of the tunnel at the time of boot. This can be done with a cron job.

  • Create a script

    # Create the tunnel after some time (3 mins) has passed
    sleep 180
    /usr/lib/autossh/autossh -M 'port-B' -N -f -R 'port-A':localhost:22 proxy
  • Add the script to your cron jobs

    crontab -e
    # Edit this file to introduce tasks to be run by cron.
    # Each task to run has to be defined through a single line
    # indicating with different fields when the task will be run
    # and what command to run for the task
    # To define the time you can provide concrete values for
    # minute (m), hour (h), day of month (dom), month (mon),
    # and day of week (dow) or use '*' in these fields (for 'any').#
    # Notice that tasks will be started based on the cron's system
    # daemon's notion of time and timezones.
    # Output of the crontab jobs (including errors) is sent through
    # email to the user the crontab file belongs to (unless redirected).
    # For example, you can run a backup of all your user accounts
    # at 5 a.m every week with:
    # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
    # For more information see the manual pages of crontab(5) and cron(8)
    # m h  dom mon dow   command
    @reboot /absolute/path/to/


  • Monitor the running processes

    Check for processes on your system that are listening on certain ports.

    sudo lsof -i -P -n | grep LISTEN

    You should see sshd processes listening on port-A and port-B and allowing traffic from * (anywhere).

  • Test the tunnel

    Using the tunnel, connect to restricted.

    ssh restricted-via-tunnel

    The indirect connection between your local system and the restricted server

If you followed the instructions carefully, you would have set up an indirect SSH connection linking local to restricted via the reverse SSH tunnel from restricted to proxy.

The result

You can now connect to restricted from outside its local network.