Overview: SSH and Telnet on Windows Server 2022

Windows Server 2022 ships with native OpenSSH support as a Windows optional feature, meaning you can install a fully functional SSH server and client without any third-party software. OpenSSH on Windows integrates with the standard Windows service infrastructure, the Windows Firewall, and Windows authentication — including public key authentication using the standard OpenSSH key formats. Telnet, by contrast, is a legacy unencrypted protocol that transmits credentials and data in cleartext. It still has legitimate uses in controlled lab environments and for testing raw TCP connectivity, but it should never be used across untrusted networks. This guide covers both, with full installation steps, configuration, and hardening guidance.

Installing OpenSSH Server and Client

OpenSSH on Windows Server 2022 is delivered as a Windows capability (not a Windows Feature — the distinction matters for the PowerShell cmdlets used). Open an elevated PowerShell session and check what is available:

# List available OpenSSH capabilities
Get-WindowsCapability -Online | Where-Object Name -like "OpenSSH*"

You will see two items: OpenSSH.Client~~~~0.0.1.0 and OpenSSH.Server~~~~0.0.1.0, each with a State of either Installed or NotPresent. Install both:

# Install the SSH client
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

# Install the SSH server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

Each command should return a RestartNeeded: False result, meaning no reboot is required. Verify the installation succeeded:

Get-WindowsCapability -Online | Where-Object Name -like "OpenSSH*"

Both should now show State: Installed.

Starting and Configuring the SSH Service

After installation, the sshd service exists but is not started and is set to manual startup. For a server that should always accept SSH connections, configure it to start automatically:

# Set sshd to start automatically
Set-Service -Name sshd -StartupType Automatic

# Start the service now
Start-Service sshd

# Verify it is running
Get-Service sshd

The installer automatically creates a firewall rule named OpenSSH Server (sshd) that allows inbound TCP on port 22. Verify it exists:

Get-NetFirewallRule -Name "*OpenSSH*" | Select-Object Name, DisplayName, Enabled, Direction, Action

If the rule is missing (for example if you installed OpenSSH manually), create it:

New-NetFirewallRule `
    -Name "OpenSSH-Server-In-TCP" `
    -DisplayName "OpenSSH Server (sshd)" `
    -Enabled True `
    -Direction Inbound `
    -Protocol TCP `
    -Action Allow `
    -LocalPort 22

Understanding sshd_config on Windows

The SSH daemon configuration file on Windows is located at:

C:ProgramDatasshsshd_config

This file follows the same syntax as OpenSSH on Linux, with a few Windows-specific additions. Open it in Notepad or VS Code:

notepad C:ProgramDatasshsshd_config

Key settings to review and harden for a production server:

# Change default port (optional — security through obscurity but reduces log noise)
Port 2222

# Disable password authentication once key-based auth is working
PasswordAuthentication no

# Disable root/administrator password login
PermitRootLogin prohibit-password

# Allow only specific users to connect
AllowUsers adminuser svcaccount

# Or allow only specific groups
AllowGroups "SSH Users" Administrators

# Set the subsystem for SFTP (already present by default)
Subsystem sftp sftp-server.exe

# Log level — use VERBOSE for debugging, INFO for production
LogLevel INFO

After editing sshd_config, restart the sshd service to apply changes:

Restart-Service sshd

Configuring SSH Key Authentication on Windows

Key-based authentication is far more secure than password authentication and is the recommended approach for server-to-server and automated connections. The setup on Windows differs slightly from Linux because of where Windows stores the authorised keys file for administrators.

On the client machine, generate an SSH key pair (if you do not already have one):

ssh-keygen -t ed25519 -C "[email protected]"

Accept the default location (C:Usersyourname.sshid_ed25519) or specify a custom path. Add a passphrase for additional protection. The public key is at id_ed25519.pub.

On the Windows SSH server, the location of the authorised keys file depends on whether the user is a local administrator or not. For non-administrator users, the authorised keys file is:

C:Users.sshauthorized_keys

For members of the local Administrators group, the authorised keys file is in a different location due to Windows OpenSSH’s special handling:

C:ProgramDatasshadministrators_authorized_keys

Create the file if it does not exist and add the public key content (the entire contents of id_ed25519.pub from the client). Then set the correct permissions — this file must be owned by SYSTEM or an administrator and must not have any group or world permissions, otherwise sshd ignores it as insecure:

# Set permissions on administrators_authorized_keys
$file = "C:ProgramDatasshadministrators_authorized_keys"
$acl = Get-Acl $file

# Remove inheritance
$acl.SetAccessRuleProtection($true, $false)

# Remove all existing rules
$acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) }

# Grant SYSTEM full control
$sysRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "NT AUTHORITYSYSTEM", "FullControl", "Allow")
$acl.AddAccessRule($sysRule)

# Grant Administrators full control
$admRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "BUILTINAdministrators", "FullControl", "Allow")
$acl.AddAccessRule($admRule)

Set-Acl $file $acl

Test connectivity from the client:

ssh [email protected]

If key authentication succeeds, go back to sshd_config and set PasswordAuthentication no, then restart sshd.

Using SFTP with OpenSSH

SFTP is included automatically with OpenSSH Server. No additional configuration is needed beyond the standard sshd setup. Connect from any SFTP client (including the Windows built-in sftp command, WinSCP, FileZilla in SFTP mode):

# From Windows command line
sftp [email protected]

# Common SFTP commands once connected
ls              # list remote directory
put localfile   # upload a file
get remotefile  # download a file
lcd C:local    # change local directory
cd /remote/path # change remote directory
quit            # disconnect

To restrict a specific user to SFTP only (no interactive shell), add a Match User block at the bottom of sshd_config:

Match User sftpuser
    ForceCommand internal-sftp
    ChrootDirectory C:SFTPRoot%u
    PermitTTY no
    AllowAgentForwarding no
    AllowTcpForwarding no

Installing the Telnet Client

The Telnet client on Windows Server 2022 is a Windows Feature (not a capability), installed via Install-WindowsFeature or through Server Manager. It is not installed by default:

# Install Telnet client
Install-WindowsFeature -Name Telnet-Client

# Verify
Get-WindowsFeature -Name Telnet-Client

After installation, use telnet from any command prompt:

telnet 192.168.1.50 23      # connect to a Telnet server
telnet smtp.example.com 25  # test SMTP port reachability
telnet 192.168.1.50 80      # test HTTP port reachability

The last two examples demonstrate using Telnet as a TCP port connectivity tester — a common sysadmin technique for verifying firewall rules without needing a full application-layer tool. If the connection opens (blank screen or a banner), the port is reachable. If you get Could not open connection to the host, the port is blocked or the service is not listening.

Troubleshooting SSH on Windows

If SSH connections fail, check the sshd event logs. OpenSSH on Windows logs to the Windows Application event log under Source OpenSSH, and also to a log file if configured. To increase logging verbosity temporarily, set LogLevel DEBUG3 in sshd_config and restart sshd, then review:

# Check Windows Event Log for sshd errors
Get-WinEvent -LogName Application | 
    Where-Object { $_.ProviderName -eq "OpenSSH" } |
    Select-Object TimeCreated, LevelDisplayName, Message |
    Select-Object -First 20 |
    Format-List

# Check if sshd is listening on port 22
netstat -ano | findstr ":22"

# Check if sshd process is running
Get-Process sshd -ErrorAction SilentlyContinue

# Test that port 22 is open from another machine
Test-NetConnection -ComputerName 192.168.1.100 -Port 22

Common issues and resolutions:

Permission denied (publickey) — usually means the authorized_keys or administrators_authorized_keys file has incorrect permissions or is in the wrong location. Re-run the ACL commands above and ensure the public key content is correct (no line wrapping or extra characters).

Connection refused on port 22 — sshd is not running, or the firewall rule is missing or disabled. Run Start-Service sshd and verify the firewall rule with Get-NetFirewallRule -Name "OpenSSH*".

Host key verification failed — on the client, the server’s host key has changed (possible after reinstalling OpenSSH). Remove the old entry from the client’s C:Usersusername.sshknown_hosts file and reconnect to accept the new key:

ssh-keygen -R 192.168.1.100

For domain environments, consider deploying the SSH server host key via Group Policy or DSC to ensure all clients trust the correct host key from day one, preventing man-in-the-middle warnings.