When accessing web services through SSH port forwarding, connections tend to drop unpredictably due to HTTP's stateless nature compared to persistent protocols like SMB. The browser-initiated TCP connections terminate after each request, causing the SSH tunnel to timeout.
First, modify your /etc/ssh/sshd_config
on the remote server:
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive yes
Use these SSH options for more resilient forwarding:
ssh -o ServerAliveInterval=30 \\
-o ServerAliveCountMax=3 \\
-o TCPKeepAlive=yes \\
-N -L 8080:localhost:80 user@host
Here's an improved version of your watchdog script using SSH ControlMaster:
#!/bin/bash
while true; do
if ! ssh -O check myapp.cloudapp.net &>/dev/null; then
ssh -fN -M -S ~/.ssh/control-%r@%h:%p \\
-o ExitOnForwardFailure=yes \\
-o ServerAliveInterval=30 \\
-o TCPKeepAlive=yes \\
-L 8080:localhost:80 \\
myapp.cloudapp.net
fi
sleep 10
done
The autossh
package provides automatic reconnection:
autossh -M 0 -f -N -L 8080:localhost:80 user@host \\
-o "ServerAliveInterval 30" \\
-o "ServerAliveCountMax 3"
Create a systemd unit for reliable operation:
[Unit]
Description=Persistent SSH tunnel
After=network.target
[Service]
Restart=always
ExecStart=/usr/bin/autossh -M 0 -N -L 8080:localhost:80 user@host
[Install]
WantedBy=multi-user.target
For HTTP services, consider these approaches:
- Configure your web server to use persistent connections
- Add a background websocket ping from client-side JavaScript
- Use
curl --keepalive-time 30
for API access
When working with cloud-based services like Azure VMs, SSH local port forwarding becomes essential for accessing internal services without exposing public ports. The standard approach:
ssh -L 8080:localhost:80 user@remote_host
works perfectly for persistent protocols like SMB or database connections. However, HTTP/HTTPS traffic presents unique challenges due to its stateless nature and connection pooling behaviors.
Several factors contribute to connection instability:
- HTTP/1.1 keep-alive timeouts
- Browser connection pooling behaviors
- SSH server TCP keepalive defaults
- Intermediate network devices dropping idle connections
1. Server-Side Configuration
Modify your SSH server config (/etc/ssh/sshd_config):
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive yes
2. Client-Side Optimization
Create a more resilient client script:
#!/bin/bash
while :
do
ssh -o ServerAliveInterval=60 \
-o ExitOnForwardFailure=yes \
-o TCPKeepAlive=yes \
-N -L 8080:localhost:80 user@remote_host
echo "Reconnecting at $(date)"
sleep 5
done
3. Advanced: Autossh for Automatic Reconnection
Install and configure autossh for bulletproof forwarding:
sudo apt install autossh
autossh -M 0 -f -N -o "ServerAliveInterval 60" \
-o "ServerAliveCountMax 3" \
-L 8080:localhost:80 user@remote_host
Add these verification techniques:
# Check established connections
ss -tnlp | grep ssh
# Continuous connectivity test
watch -n 1 curl -I http://localhost:8080
For critical production systems, consider:
- SSH multiplexing with ControlMaster
- VPN solutions like WireGuard
- Cloud-native solutions (Azure Private Link, AWS PrivateLink)
Remember that the optimal solution depends on your specific network environment and security requirements.