How To Securely Open Ports (SSH, RDP etc.) On-Demand For Dynamic IPs Through iptables

An encrypted SSH connection allows complete access to your machine. However, unless you diligently manage all security updates to your OS and SSH Server, there is a possibility that your SSH server gets compromised.

Typically, system administrators restrict access to the SSH Server (Port 22) to selected IPs. The limitation in opening the Port 22 to selected Static IPs is that you will not be able to connect to it when you are on the move, and need to access your machine from, say a mobile phone.

To overcome this limitation, I have written a script that uses a combination of a web server and iptables firewall, and grants access to Port 22 (or any other Port) on demand to an IP you prefer. It can also work equally well on an AWS EC2 machine where you open Port 22 for all IPs (0.0.0.0/0) using a Security Group, and then restrict access via iptables to that EC2 instance.

I will be using

  • Ubuntu
  • Apache with PHP
  • iptables Firewall
  • sudo Access

Step 1 – Grant Access to iptables to www-data user

On Ubuntu, Apache runs with www-data as a user. We will allow www-data user to execute iptables via sudo without a password

Edit the sudoers file

sudo visudo

At the end of the file, add the following

www-data ALL=NOPASSWD: /sbin/iptables

The line above allows www-data access to the command iptables, without a password.

Verify if sudo is indeed working for www-data user.

Run the following command to verify.

sudo -H -u www-data bash -c 'sudo iptables -L'

Note: It should not ask any password for www-data and show the data related to iptables as shown in the screenshot above.

Step 2 – Allow Authenticated Access to Ports via The Web

We will now create a file that we’ll put on a web server for easy access. Save the following in a file, and place it on a safe, https protected location on your web server.

  1. Get the code at GitHub –https://github.com/technotablet/open-port-dynamically/blob/master/openport.php
  2. Change the password and the port that you wish to open in openport.php

Now access the openport.php script from your browser.

Complete GitHub Repository at https://github.com/technotablet/open-port-dynamically

For example: https://yourdomain.com/openport.php (Replace the URL with your domain & script name)

Maintenance

  1. The ports that you open via the script tend to remain open like forever. You should ideally setup a firewall script via iptables and reset the rules at a pre-defined interval.
  2. Instead of using a fixed password, you can try out an OTP version (tutorial coming soon).
  3. For RDP and other ports that are not on the same machine, but are within the same network, you can setup Port Forwarding based on iptables and do the relevant NAT based redirection.
Advertisement

Port Forwarding in AWS LightSail or EC2 machines via SSH

I have a Smart Lighting system at home powered by Philips Hue. I was trying to connect to my Philips Hue Bridge’s IP remotely without implementing Port Forwarding on my WiFi Router.

Instead of setting up an EC2 instance, I moved ahead with a Lightsail instance, which unlike EC2, is much less complicated, and also provides the download of private key, the firewall changes etc. upfront for easy and convenient access.

Disclaimer: The process I mention below may not be optimum if you are opening up sensitive/unprotected ports without appropriate security measures. Use your own judgement before you implement Port Forwarding.

Following is an example of what I planned to do. Basically, I wanted to access Port 9090 on my Lightsail instance to reach the Philips Hue Bridge at my home.

Port Forwarding Setup using AWS Lightsail/EC2

  • I had opened Port 9090 through the Firewall option in Lightsail
  • I also had set a password for root user by using the command sudo passwd

However, the port forwarding did not work because Lightsail’s SSH does not support port forwarding by default.

I made the following changes in /etc/ssh/sshd_config to enable port forwarding.

# Changed the following line
PermitRootLogin yes

# Added at the bottom the following
UseDNS no

ClientAliveInterval 180
ClientAliveCountMax 3

GatewayPorts yes

Then I restarted ssh using root

/etc/init.d/ssh restart

After that I was able to do the port forwarding smoothly by executing the following command on my Desktop at home (your needs may vary, so modify accordingly)

ssh -i key.pem -R *:9090:192.168.0.75:80 root@101.102.103.104

Now from a remote machine, if I reach out to Port 9090 on 101.102.103.104, it works well. The command man ssh will help you understand the -L (Local Forward to Remote) & -R (Remote Forward to Local) option better. You can also use PuTTY to implement Port Forwarding.