Accessing Local Services Remotely: SSH Port Forwarding with DigitalOcean
Ever needed to access a web service running only on your local development machine from a remote server, like a DigitalOcean droplet? Perhaps you want to test a webhook integration hitting your local instance, or demo a local site without deploying it fully. SSH Remote Port Forwarding provides a secure and relatively simple way to achieve this.
This guide walks through setting up a DigitalOcean droplet and configuring your local SSH client to forward ports from the remote droplet back to your local machine.
Prerequisites
- A DigitalOcean account.
- An SSH client installed on your local machine (common on Linux, macOS; available on Windows via WSL, Git Bash, PuTTY, etc.).
- An SSH key pair (recommended for secure authentication).
Step 1: Create a DigitalOcean Droplet
- Log in to your DigitalOcean account.
- Go to Create -> Droplets.
- Choose your desired region, Droplet type, and OS image (e.g., Ubuntu LTS).
- Authentication: This is crucial.
- Select SSH keys.
- Choose an existing SSH key you’ve uploaded to DigitalOcean, or click “New SSH Key” and paste your public key (
~/.ssh/id_rsa.pub
or similar). Using keys is more secure than password authentication.
- Choose any additional options (VPC, monitoring, etc.) as needed.
- Click “Create Droplet”.
- Once the droplet is created, DigitalOcean will display its public IP address. Copy this IP address – you’ll need it shortly.
Step 2: Configure Your Local SSH Client (~/.ssh/config
)
To make connecting and setting up forwarding easier, let’s configure your local SSH client. Open (or create) the SSH configuration file on your local machine. This is typically located at ~/.ssh/config
.
You can edit it using a text editor like vim
, nano
, or VS Code:
nano ~/.ssh/config
# or
vim ~/.ssh/config
Add an entry like the following, replacing <yourip address>
with the actual IP address of your droplet:
Host dev # A short alias for your droplet
HostName <yourip address> # The droplet's public IP
User root # Or your non-root user if you created one
ServerAliveInterval 60 # Send keepalive packet every 60 seconds
ServerAliveCountMax 120 # Try 120 times before disconnecting (2 hours total)
# --- Remote Port Forwarding Rules ---
# Format: RemoteForward <RemotePort> <LocalHost>:<LocalPort>
# Forwards connections TO the droplet's RemotePort TO your local machine's LocalPort
# Example 1: Access local port 3040 via droplet's port 4040
RemoteForward 4040 localhost:3040
# Example 2: Access local port 3000 via droplet's port 4000
RemoteForward 4000 localhost:3000
# Example 3: Access local port 3007 via droplet's port 4007
RemoteForward 4007 localhost:3007
Explanation:
Host dev
: Defines a shortcut name (dev
). You’ll usessh dev
to connect.HostName
: The IP address or domain name of your droplet.User
: The username to log in as on the droplet (oftenroot
initially, but a non-root user is recommended for general use).RemoteForward <RemotePort> <LocalHost>:<LocalPort>
: This is the core forwarding rule. It tells the remote SSH server (on the droplet) to listen on<RemotePort>
. Any connection received on that port on the droplet will be forwarded through the secure SSH tunnel back to your local machine, targeting<LocalHost>:<LocalPort>
.localhost
typically refers to your local machine itself.ServerAliveInterval
&ServerAliveCountMax
: These options help prevent your SSH connection from disconnecting due to inactivity, which is crucial for long-running port forwarding.
Step 3: Keeping the Connection Alive
Idle SSH connections often get terminated by network devices (routers, firewalls). ServerAliveInterval
and ServerAliveCountMax
combat this:
ServerAliveInterval 60
: Your local SSH client will send a “null packet” (keepalive message) to the server every 60 seconds to keep the connection active.ServerAliveCountMax 120
: If the server doesn’t respond to a keepalive message, the client will retry sending keepalives up to 120 times before giving up and disconnecting.
In our example (Interval 60
, CountMax 120
), the client will wait up to 60 * 120 = 7200
seconds (2 hours) for a response before disconnecting if the network appears down. This is generally much more robust than the default settings.
(Reference: Super User Question on preventing SSH disconnects)
Step 4: Configure the Server (Droplet) for Gateway Ports
By default, the RemoteForward
directive only makes the <RemotePort>
accessible from the droplet itself (i.e., connecting to localhost:<RemotePort>
on the droplet). If you want other computers on the internet to be able to connect to your droplet’s <RemotePort>
and have it forwarded to your local machine, you need to enable GatewayPorts
on the droplet’s SSH server.
- SSH into your droplet using the alias you configured:
ssh dev
- Edit the SSH server configuration file (
sshd_config
) using a text editor likenano
orvim
(you’ll needsudo
):sudo nano /etc/ssh/sshd_config # or sudo vim /etc/ssh/sshd_config
- Find the
GatewayPorts
line. It might be commented out (#GatewayPorts no
) or missing. - Change it or add it to enable gateway ports:
GatewayPorts yes
- Save the file and exit the editor (e.g.,
Ctrl+X
, thenY
, thenEnter
innano
). - Restart the SSH service to apply the changes:
sudo systemctl restart sshd
Security Warning: Setting GatewayPorts yes
makes the forwarded port on your droplet accessible from anywhere that can reach your droplet’s IP address. This effectively exposes the service running on your local machine (localhost:<LocalPort>
) to the internet via your droplet. Ensure that the local service is properly secured or that you understand the implications before enabling this. If you only need to access the forwarded port from the droplet itself, you can leave GatewayPorts
as no
(or commented out).
Step 5: Connect and Verify
Now, simply connect to your droplet using the alias:
ssh dev
As long as this SSH connection remains active, the port forwarding rules defined in your ~/.ssh/config
will be in effect.
To test:
- Ensure you have a service running on your local machine on one of the specified local ports (e.g., a web server on
localhost:3000
). - From the droplet’s command line, try accessing the corresponding remote port using
curl
ortelnet
:You should see the response from the service running on your local machine’s port 3000.# On the droplet, testing the forward from RemotePort 4000 to LocalPort 3000 curl localhost:4000
- If you enabled
GatewayPorts yes
, you could also try accessing<droplet-ip-address>:4000
from another machine (like your browser, or another server) to verify external access.
Conclusion
SSH remote port forwarding is a powerful technique for securely exposing local services via a remote server like a DigitalOcean droplet. By configuring your local ~/.ssh/config
with RemoteForward
rules and ensuring the connection stays alive with ServerAliveInterval
, you can create stable tunnels. Remember to enable GatewayPorts yes
on the server only if you need external access to the forwarded port, and be mindful of the security implications.