Setting up a SFTP server on Windows Server

Danang Priabada
5 min readAug 26, 2024

--

Before we start, check your network connection. If you have no internet connection, you can see last section of this articles to install offline.

PS C:\Windows\system32> Test-Connection www.google.com

Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
COM-TPD-1778 www.google.com 64.233.170.104 32 23
COM-TPD-1778 www.google.com 64.233.170.104 32 22
COM-TPD-1778 www.google.com 64.233.170.104 32 20
COM-TPD-1778 www.google.com 64.233.170.104 32 21

Check Existing OpenSSH Capabilities

First, ensure that OpenSSH is installed on your Windows Server. Open PowerShell as an administrator and run the following command to check the installed capabilities:

Get-WindowsCapability -Online | where Name -like "OpenSSH*"

The output should display the following if OpenSSH is not installed:

Name  : OpenSSH.Client~~~~0.0.1.0
State : Installed

Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent

Install OpenSSH Server

If the OpenSSH Server is not present, you can install it using the following command (Choose one):

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Wait Until Progress Bars is Full
dism /online /Add-Capability /CapabilityName:OpenSSH.Server~~~~0.0.1.0
Deployment Image Servicing and Management tool
Version: 10.0.22621.2792

Image Version: 10.0.22631.4037

[==========================100.0%==========================]
The operation completed successfully.

Verify that the installation was successful:

Get-WindowsCapability -Online | where Name -like "OpenSSH*"
Name  : OpenSSH.Client~~~~0.0.1.0
State : Installed

Name : OpenSSH.Server~~~~0.0.1.0
State : Installed

Start and Configure the SSHD Service

Get current status

Get-Service -Name "sshd"
Status   Name               DisplayName
------ ---- -----------
Stopped sshd OpenSSH SSH Server

Start the service

Start-Service sshd

WARNING: Waiting for service 'OpenSSH SSH Server (sshd)' to start...
PS C:\Windows\system32> Get-Service -Name "sshd"

Status Name DisplayName
------ ---- -----------
Running sshd OpenSSH SSH Server

Configure SSHD

By default, SSH listens on port 22. To change this, edit the sshd_config file. Find the current port configuration:

Get-Content "C:\ProgramData\ssh\sshd_config" | findstr Port
#Port 22
#GatewayPorts no

Change the port number by replacing Port 22 with your desired port number in the sshd_config file. Restart the SSHD service to apply the changes (This is optional):

(Get-Content "C:\ProgramData\ssh\sshd_config").replace("Port 22", "Port <your-new-port>") | Set-Content "C:\ProgramData\ssh\sshd_config" | Restart-Service sshd

You also can edit from notepad

notepad C:\ProgramData\ssh\sshd_config

Restart

Restart-Service -Name sshd

#You can use Command Prompt to restart the sshd service by leveraging the net command:

net stop sshd
net start sshd

Verify Port Listening

Ensure that the port is listening :

Get-NetTCPConnection -LocalPort 22 | select Local*, State,`
@{n="ProcessName";e={(Get-Process -Id $_.OwningProcess).ProcessName}},`
@{n="ProcessPath";e={(Get-Process -Id $_.OwningProcess).Path}} | ft -Auto

LocalAddress LocalPort State ProcessName ProcessPath
------------ --------- ----- ----------- -----------
:: 22 Listen sshd C:\Windows\System32\OpenSSH\sshd.exe
0.0.0.0 22 Listen sshd C:\Windows\System32\OpenSSH\sshd.exe

Create a User for SFTP Access

Create a new local user for SFTP access:

$userName = "sftpuser"
$password = "<your-password>"
New-LocalUser -Name $userName -Password (ConvertTo-SecureString $password -AsPlainText -Force) -FullName "SFTP User" -Description "SFTP Access User"
Name     Enabled Description
---- ------- -----------
sftpuser True SFTP Access User

If you need to change the password

# Change the password for the existing user
$newPassword = "<your-new-password>"
Set-LocalUser -Name $userName -Password (ConvertTo-SecureString $newPassword -AsPlainText -Force)

Review All Users

Verify that the sftpuser is correctly listed:

Get-LocalUser | Select-Object Name, Enabled
Name               Enabled
---- -------
Administrator False
DefaultAccount False
Guest False
MUSR_MQADMIN True
sftpuser True
Think True
WDAGUtilityAccount False

Enable or Disable

$userName= "sftpuser"
Disable-LocalUser -Name $UserName

$userName= "sftpuser"
Enable-LocalUser -Name $UserName

Set Up a Directory for SFTP

Create a directory that the user will have access to:

$folderPath = "C:\SFTPFolder"
New-Item -Path $folderPath -ItemType Directory -Force
PS C:\Windows\system32> New-Item -Path $folderPath -ItemType Directory -Force

Directory: C:\

Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 8/26/2024 11:42 AM SFTPFolder
$acl = Get-Acl $folderPath
$permission = "$env:COMPUTERNAME\$userName", "ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.AddAccessRule($accessRule)
Set-Acl -Path $folderPath -AclObject $acl

Verify User Permissions

Check that the user has the correct permissions:

$folderPath = "C:\SFTPFolder"
$acl = Get-Acl $folderPath
$acl.Access | Select-Object IdentityReference, FileSystemRights, AccessControlType
IdentityReference                           FileSystemRights AccessControlType
----------------- ---------------- -----------------
COM-TPD-1778\sftpuser ReadAndExecute, Synchronize Allow
BUILTIN\Administrators FullControl Allow
NT AUTHORITY\SYSTEM FullControl Allow
BUILTIN\Users ReadAndExecute, Synchronize Allow
NT AUTHORITY\Authenticated Users Modify, Synchronize Allow
NT AUTHORITY\Authenticated Users -536805376 Allow

Generate Report

$users = Get-LocalUser | Select-Object Name

This command retrieves a list of all local users on the system and selects their Name property. The result is stored in the $users variable.

$report = foreach ($user in $users) {
$access = $acl.Access | Where-Object { $_.IdentityReference -like "*$($user.Name)*" }
[PSCustomObject]@{
UserName = $user.Name
Permissions = if ($access) { $access.FileSystemRights -join ", " } else { "No Access" }
}
}
PS C:\Windows\system32> $report

UserName Permissions
-------- -----------
Administrator FullControl
DefaultAccount No Access
Guest No Access
MUSR_MQADMIN No Access
sftpuser ReadAndExecute, Synchronize
Think No Access
WDAGUtilityAccount No Access

Accsess SFTP

Access your SFTP server from CLI or Toolkit like WinSCP

Allow SSH Through Windows Firewall

Ensure that the Windows Firewall allows SSH connections:

netsh advfirewall firewall add rule name="OpenSSH Server (sshd)" dir=in action=allow protocol=TCP localport=22
Get-NetFirewallRule | Format-Table -Property Name, DisplayName, Enabled, Direction, Action, Profile | findstr OpenSSH

Install Package Offline

You need to download the Feature On Demand Package, inside the ISO there is file called OpenSSH-Server-Package~31bf3856ad364e35~amd64~~.cab place in folder LanguagesAndOptionalFeatures

Windows 11, version 22H2 Language and Optional Features ISO (Source)
Download the FOD ISO.iso

Windows 10, version 2004 (and later) Features on Demand #1 ISO (Source)
Download the FOD ISO.iso

The command-line syntax to install a FOD CAB file is below:

dism /online /add-package /packagepath:"<where-your-cab-placed>"
dism /online /add-package /packagepath:"C:\Users\danang.priabada\Documents\OpenSSH-Server-Package~31bf3856ad364e35~amd64~~.cab"
Deployment Image Servicing and Management tool
Version: 10.0.22621.2792

Image Version: 10.0.22631.4037
Processing 1 of 1 - Adding package OpenSSH-Server-Package~31bf3856ad364e35~amd64~~10.0.22621.1
[===========================61.0%=== ]
[===========================66.0%====== ]
[===========================67.6%======= ]
[===========================69.3%======== ]
[===========================71.0%========= ]
[===========================71.0%========= ]
[===========================72.6%========== ]
[===========================74.3%=========== ]
[===========================76.0%============ ]
[===========================80.0%=============== ]
[===========================87.0%===================== ]
[===========================98.0%======================= ]
[==========================100.0%==========================]
The operation completed successfully.
Get-WindowsCapability -Online | where Name -like "OpenSSH*"
Name  : OpenSSH.Client~~~~0.0.1.0
State : Installed

Name : OpenSSH.Server~~~~0.0.1.0
State : Installed

--

--

Danang Priabada
Danang Priabada

Written by Danang Priabada

Red Hat and IBM Product Specialist | JPN : プリアバダ ダナン | CHN : 逹男 | linktr.ee/danangpriabada

No responses yet