SSH Tunneling Through Gateway Server: Secure HTTPS Access via Dynamic Port Forwarding


3 views

When working with restricted networks, many sysadmins first try this approach:

ssh -X user@serverB firefox https://serverA.example.com

While functional, this method has significant drawbacks:

  • Graphical latency over remote connections
  • Limited browser functionality
  • No local bookmark/cookie integration

We can establish a direct tunnel from your local machine to Server A through Server B:

ssh -L 8443:serverA.example.com:443 user@serverB

Now access the service via:

https://localhost:8443

For more flexible access (especially when dealing with multiple services):

ssh -D 1080 user@serverB

Configure your browser to use SOCKS proxy:

  • Host: 127.0.0.1
  • Port: 1080
  • Type: SOCKS5

For production environments, consider these enhancements:

# Auto-reconnect with autossh
autossh -M 0 -N -L 8443:serverA:443 user@serverB

# Multi-service configuration in ~/.ssh/config
Host tunnel-proxy
  HostName serverB.example.com
  User tunneluser
  LocalForward 8443 serverA.example.com:443
  LocalForward 8080 serverC.internal:80
  ServerAliveInterval 30
  ExitOnForwardFailure yes

Always add these security measures:

ssh -N -L 8443:serverA:443 -o ExitOnForwardFailure=yes \
    -o ServerAliveInterval=30 -C user@serverB

Key parameters:

  • -N: No remote command execution
  • -C: Compression for better performance
  • ServerAliveInterval: Detect broken connections

For Chrome/Edge users who want to avoid system-wide proxy settings:

google-chrome --proxy-server="socks5://localhost:1080" \
              --host-resolver-rules="MAP * ~NOTFOUND, EXCLUDE localhost"

Firefox users can create dedicated profiles for tunneling:

firefox -no-remote -P TunnelProfile

When working with restricted networks, we often encounter situations where direct HTTPS access to internal web services is blocked by firewall rules. Here's a common scenario:


+----------------+       +----------------+       +----------------+
| Your Local PC  | SSH → | Gateway Server | HTTP → | Web Server    |
| (Firewalled)   |       | (Server B)     | HTTPS  | (Server A)    |
+----------------+       +----------------+       +----------------+

The most straightforward approach is to create a local port forward. This makes Server A's HTTPS service appear as if it's running on your local machine:


ssh -L 8443:serverA:443 user@serverB

After establishing this tunnel, you can access the service at:


https://localhost:8443

When tunneling HTTPS, you might encounter certificate warnings because:

  • The certificate is issued for serverA's domain
  • Your browser sees the service as localhost

Solutions include:


# Option 1: Add exception in browser (temporary)
# Option 2: Use --insecure flag with curl
curl --insecure https://localhost:8443

# Option 3: Modify hosts file (requires admin)
echo "127.0.0.1 serverA" | sudo tee -a /etc/hosts

For production environments, consider using AutoSSH to maintain stable connections:


# Install autossh if needed
sudo apt-get install autossh

# Create persistent tunnel
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
        -L 8443:serverA:443 user@serverB -N

For accessing multiple services, a SOCKS proxy might be more flexible:


ssh -D 1080 user@serverB

Configure your browser to use:

  • Proxy type: SOCKS v5
  • Server: 127.0.0.1
  • Port: 1080

While tunneling provides access, remember:

  • SSH encryption protects traffic between your PC and Server B
  • HTTPS encryption remains between Server B and Server A
  • Monitor for unusual tunnel activity
  • Consider using SSH key authentication instead of passwords

# Generate SSH keys if needed
ssh-keygen -t ed25519
ssh-copy-id user@serverB

For complex scenarios, evaluate whether a VPN might be more appropriate:

Factor SSH Tunnel VPN
Setup Complexity Low Medium-High
Protocol Support Limited All traffic
Performance Good for few services Better for multiple