When setting up SSH tunnels on Windows servers, we need persistent connections that survive reboots and can be managed like other system services. The challenge lies in finding a CLI-compatible solution that doesn't require GUI tools or complex configuration.
Here are the most reliable CLI-capable tools for this purpose:
1. Plink (PuTTY Link) - Lightweight SSH client from PuTTY suite
2. Windows' native SSH client (since Windows 10 1809)
3. NSSM (Non-Sucking Service Manager) - For service wrapping
4. WinSW (Windows Service Wrapper) - Alternative to NSSM
This method uses Plink with NSSM for robust service creation:
# First, install NSSM:
choco install nssm -y
# Then create the service:
nssm install SSHTunnel "C:\path\to\plink.exe" -ssh -N -L 3306:localhost:3306 user@remotehost -i "C:\path\to\private_key.ppk" -P 22
# Configure service properties:
nssm set SSHTunnel AppDirectory "C:\path\to"
nssm set SSHTunnel DisplayName "MySQL SSH Tunnel"
nssm set SSHTunnel Start SERVICE_AUTO_START
For newer Windows versions (1809+):
# First generate SSH keys:
ssh-keygen -t rsa -b 4096 -f C:\ssh\tunnel_key
# Create batch script (tunnel.bat):
@echo off
ssh -N -L 3306:localhost:3306 -i C:\ssh\tunnel_key user@remotehost
# Then use WinSW to create the service:
<service>
<id>SSHTunnel</id>
<name>SSH Tunnel Service</name>
<description>Persistent SSH tunnel to remote host</description>
<executable>cmd.exe</executable>
<arguments>/C C:\path\to\tunnel.bat</arguments>
<log mode="roll"></log>
</service>
- Always use key-based authentication (passwordless SSH)
- Set up proper retry logic for connection drops
- Configure firewall rules to allow the tunnel ports
- Monitor tunnel health with logging or external tools
If the service fails to start:
# Check service logs:
nssm start SSHTunnel
nssm status SSHTunnel
# Test the SSH command manually first
# Verify network connectivity to the remote host
# Check permissions on private key files
When implementing SSH tunnels as Windows services, we have several robust command-line options:
# Plink (PuTTY command-line)
plink.exe -N -L 3306:localhost:3306 user@remote-server -pw password -batch
# OpenSSH for Windows (built-in)
ssh -N -L 8989:localhost:8989 user@example.com -f
The most reliable approach combines OpenSSH with NSSM (Non-Sucking Service Manager):
# Install NSSM
choco install nssm -y
# Create the service
nssm install SSH-Tunnel "C:\Windows\System32\OpenSSH\ssh.exe" -N -L 8080:localhost:80 user@server -i C:\keys\private.ppk
For production environments, implement a monitoring script:
@echo off
:loop
plink.exe -N -L 5432:localhost:5432 dbuser@dbserver -i C:\ssh\keyfile.ppk -batch
timeout /t 30
goto loop
- Always use key-based authentication
- Restrict service account privileges
- Implement connection logging
- Use non-standard ports when possible
For enterprise environments, Bitvise offers command-line configuration:
# Bitvise command-line configuration
bsshd.exe -install -svcName SSHTunnel -cmdFile "C:\tunnel_config.tbc"
Key problems and solutions:
# Check service status
sc query SSHTunnel
# View service logs
Get-EventLog -LogName Application -Source "OpenSSH" -Newest 20