Installing and configuring SFTP server on Windows Server 2016
For a recent customer engagement we needed to provide internal and external users with the ability to upload/download files through SFTP to a specific backend-server. For security reasons we decided to tunnel the SFTP traffic through the customer’s Netscaler, and so for this setup you need to do some Netscaler configuration and then the actual SFTP server configuration on the backend server.
The native FTP software available as an addon in IIS does not support SFTP, and we do not wish to use regular FTP since username/passwords will be sent in clear text over the network. FTPS was not an option for us since the FTP client the users will be using does not support it.
Another important factor or requirement is to have AD authentication available, so admins don’t have to manage specific SFTP accounts and also so users don’t have to remember an additional username/password for SFTP. So I looked at a few freeware options for SFTP server (Turbo SFTP for example), but none of them really worked that great. Finally I ended up using the OpenSSH version for Windows (https://github.com/PowerShell/Win32-OpenSSH/releases) since this satisfied all the requirements.
Below are the steps to installing and configuring OpenSSH for Windows.
- Download “OpenSSH-Win64.zip” from https://github.com/PowerShell/Win32-OpenSSH/releases
- Extract downloaded zip file
- Create folder “C:\Program Files (x86)\OpenSSH-Win64\” and copy the extracted files there
- Run below in cmd (run cmd as admin):
powershell.exe -file “C:\Program Files (x86)\OpenSSH-Win64\install-sshd.ps1”
- Run services.msc and change Startup Type from Manual to Automatic for the two new services “OpenSSH Authentication Agent” and “OpenSSH SSH Server”
- Edit file “C:\ProgramData\ssh\sshd_config” in notepad and add below text at top of file. Note that any group names and folder paths specified in the config must be specified using lowercase letters (but whether the real group/folder names are lowercase or not doesn’t matter). See https://github.com/PowerShell/Win32-OpenSSH/wiki/sshd_config for more info
123456789101112131415161718192021#CUSTOM#Restricts logon through SFTP to only these usersAllowGroups mydomain\somerandomadgroup#We specify that we only allow logons for connections originating from IP 192.168.1.101. #In this case this IP is the Netscaler Subnet IP, the IP the Netscaler will use to communicate with the backend server.#We don't want to allow any device/person, except our Netscaler, to be able to connect to our SFTP server.AllowUsers *@192.168.1.101#Specifies that we're using passwords and not SSH keys to authenticateAuthenticationMethods password#Forcing SFTP functionality, needed for ChrootDirectory parameter belowForceCommand internal-sftp#Specify the default folder the user sees after SFTP authentication. Without this, users will see C:\users\myuser\ as default folder, which is not usually preferable.ChrootDirectory C:\inetpub\wwwroot\ftpfolder#Below three parameters are recommended as best practice to prevent certain security bypassingAllowTcpForwarding noPermitTunnel noGatewayPorts no
- Restart service “OpenSSH SSH Server” (any changes to config file above won’t take effect until service is restarted)
- Optional: Open port 22 in the Windows Firewall on the backend server so Netscaler can communicate with it.
- Now you can use SFTP to connect to this server using AD credentials (just entering sAMAccountName is sufficient). Only users in AD grup ‘mydomain\SomeRandomADGroup’ are allowed to logon. Access to any subfolders in C:\inetpub\wwwroot\ftp\ through SFTP will be dictated by NTFS rights. I suggest using AD groups + NTFS rights to control which subfolders the users should be able to read/write to.
The Netscaler configuration is quite trivial. After below you probably want to create an internal and external dns, such as ‘myapp.mydomain.com’, pointing to 192.168.1.15 internally and the external IP (which gets NATed to 172.16.1.155 in firewall) so that users can specify ‘myapp.mydomain.com’ in their SFTP client (instead of IP addresses).
add ns acl A-ANY-CS-INTERNAL_15_SFTP-TCP_22 ALLOW -destIP = 192.168.1.15 -destPort = 22 -protocol TCP -priority 70
add ns acl A-ANY-CS-DMZ_155_SFTP-TCP_22 ALLOW -destIP = 172.16.1.155 -destPort = 22 -protocol TCP -priority 80
add server myserver.mydomain.local 192.168.2.25 -comment "SFTP server"
add service SVC-APPNAME-SFTP myserver.mydomain.local TCP 22 -healthMonitor YES -gslb NONE -maxClient 0 -maxReq 0 -usip NO -useproxyport YES -cltTimeout 180 -svrTimeout 360 -CKA NO -TCPB NO -CMP NO -appflowLog DISABLED -CIP ENABLED X-MS-Forwarded-Client-IP -netProfile NP_INTERNAL_SNIP
add lb monitor MON-APPNAME-SFTP TCP -LRTM ENABLED -destPort 22 -interval 20 -resptimeout 15 -netProfile NP_INTERNAL_SNIP-MON
bind service SVC-APPNAME_SFTP -monitorName MON-APPNAME-SFTP
add lb vserver LB-EXT_APPNAME_SFTP TCP 192.168.1.15 22 -persistenceType SOURCEIP -timeout 30
add lb vserver LB-INT_APPNAME_SFTP TCP 172.16.1.155 22 -persistenceType SOURCEIP -timeout 30
bind lb vserver LB-INT_APPNAME_SFTP SVC-APPNAME_SFTP
bind lb vserver LB-EXT_APPNAME_SFTP SVC-APPNAME_SFTP