How to Create Persistent SSH Tunnels as Windows Services Using CLI Tools


14 views

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