Setting up a SFTP server on Windows Server 2022

Nowadays the process for setting up a SFTP under Windows is fairly simple. But there are still some things that won’t go that easy and will give you strange errors and can cost you a lot of time. Especially when you want to use Active Directory authentication and a network share as the home folder.

First off we have to install OpenSSH. In Windows 10, 11, Windows Server 2019 and Windows 2022 this is just an optional feature that can be selected for installation.

Go to Settings > Apps > Optional features > Add a feature. Select OpenSSH server from the list and click install.

Here you can come across your first hurdle: “Installation failed”.

There is not much to go on here, because “install failed” is all the feedback you’ll get. After checking all kinds of different things, a default GPO was the problem. To solve this you’ll need open gpedit.msc and go to Computer configuration > Administrative Templates > System. And there in the root of System find and open the policy “Specify settings for optional component installation and component repair”.

Enable the setting and also check “Download repair content and optional features directly from Windows Update instead of Windows Server Update Services (WSUS)”.

After this your install of OpenSSH should complete without an error and the binaries will be installed in C:\Windows\System32\OpenSSH.

On older installations you now should make a new rule in Windows Defender Firewall to allow incoming traffic on port 22, but I found that in Windows Server 2022 this is already done.

Now go to the Windows Services and change the OpenSSH Server service from manual to automatic and start the service. When the service is started for the first time the working directory will be created in C:\ProgramData\ssh.

Now that the OpenSSH service is running, you would think that you can connect to it, but when you try, you’ll get an access denied error. This is because you have to specify which accounts have access to the service and by default none are configured.

To configure authentication go to C:\ProgramData\ssh and open the file sshd_config with a text editor. According to the Microsoft documentation (https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_server_configuration#allowgroups-allowusers-denygroups-denyusers), you’ll simply have to add AllowUsers followed by the users you want to grant access to the config file and it should work.

This is the second hurdle in setting up the SFTP server. I tried many combinations of the allowed user syntax, including:
DNSdomainname.local\Username
DNSdomainname.local\Username
DNSdomainname.local\Username@Servername
DNSdomainname.local\Username@Servername
NetBIOSdomainname\Username
NetBIOSdomainname\Username
NetBIOSdomainname\Username@Servername
NetBIOSdomainname\Username@Servername
NetBIOSdomainname\Username@172.17.22.10
NetBIOSdomainname\Username@172.17.22.10
NetBIOSdomainname\sa_ftpbackup@Servername
Username?NetBIOSdomainname
Username?NetBIOSdomainname*
Username?DNSdomainname.local
Username?DNSdomainname.local*

But all failed miserably and I got “Access denied” in Putty and “Permission denied, please try again.” in PowerShell.

To get more information about why the access was denied, you can stop the OpenSSH service and start it manually from an elevated prompt with the debug parameter, like: sshd.exe -d

In this logging you’ll see that the group can’t be mached.

debug1: get_passwd: LookupAccountName() failed: 1332.
debug1: Can't match group at line 94 because user NetBIOSdomainname\\username@hostname does not exist
Invalid user NetBIOSdomainname\\username@hostname from x.x.x.x port 53784
debug1: userauth-request for user NetBIOSdomainname\\\\username@hostname service ssh-connection method keyboard-interactive [preauth]
debug1: attempt 1 failures 0 [preauth]
debug1: keyboard-interactive devs  [preauth]
debug1: auth2_challenge: user=NetBIOSdomainname\\\\username@hostname devs= [preauth]
debug1: kbdint_alloc: devices '' [preauth]
debug1: userauth-request for user NetBIOSdomainname\\\\username@hostname service ssh-connection method password [preauth]
debug1: attempt 2 failures 1 [preauth]
debug1: Windows authentication failed for user: NOUSER domain: . error: 1326
Failed password for invalid user NetBIOSdomainname\\username@hostname from x.x.x.x port 53784 ssh2
Connection closed by invalid user NetBIOSdomainname\\\\username@hostname x.x.x.x port 53784 [preauth]

Eventually the work-a-round was fairly easy. Create a local group and add your domain users in that local group. Now add that group to the sshd_config file like: AllowGroup SFTPUsers

Now when you try to login, you’ll get a different message “Connection reset by x.x.x.x port 22”. It’s not much, but it is something 😉

Looking at the logging it became clear that the problem had something to do with elevated and privileged processes.

Accepted password for NetBIOSdomainname\\username from x.x.x.x port 53735 ssh2
debug1: monitor_child_preauth: NetBIOSdomainname\\username has been authenticated by privileged process
debug1: monitor_read_log: child log fd closed
debug1: Not running as SYSTEM: skipping loading user profile
CreateProcessAsUserW failed error:1314
fork of unprivileged child failed
debug1: do_cleanup

This can also be solved very easily. Don’t start sshd from the command line, but start the service. The service has to be started under the system account, so it can reach all needed dependencies.

Now that we can access the server over SCP, we only need to alter the default home directory for the users. As long as that is a folder on the server you’re fine, but when you want to use a network location, you’re in for a treat. You can’t use UNC paths.

In the event viewer you’ll see errors like “sshd: error: chroot only support absolute paths”

And “sshd: fatal: chroot (“\\network path”): Operation not supported”

To get around this problem, you could use a symbolic link. Symbolic links or symlinks are “virtual” files or folders which reference a physical file or folder located elsewhere. To create such a symbolic link you have to open an elevated prompt and use the mklink commando. mklink -d <link> <target>

Now you should have a working setup. However, when you get a message stating that permission is denied, you’ll have to add the service account to the local administrators group. This is because of the rights assigned to the symbolic link. By default “Authenticated users”, “System” and “Administrators” are configured, but “Authenticated users only have read rights.

You can’t change these rights. If you try to change them you’ll get enumerating and access denied errors.

So when you add the service account to the local administrators group, you’ll get write rights. So far for the least privileged approach 😉

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *