There are a number of blog posts already out there about how to go about setting up an ssh server on a Windows machine using Cygwin. That said, there wasn’t a step by step guide for the setup I wanted which is the ability to use public key authentication without the need of a password. Why? I want to be able to script services to log into and run some tasks on the Windows machine.
One note I should add is that, while this process worked for me, different Windows configurations may have different wrinkles. This setup was performed on a Surface Pro 2 running stock Windows 8.1 with all current services packs and I’ve got full admin access to the machine. No third party security or AV products are on the system which may require their own configuration tweaks when adding a system service like this.
Install and configure initial sshd setup
Installing Cygwin is covered on the Cygwin site.
The two additional packages you want to make sure get installed are:
- Net -> openssh
- Admin -> cygrunsrv
Once the install completes and the packages are in place, it is time to configure sshd. Cygwin should have configured a Cygwin Terminal. You will want to run this as administrator:
- Find the Cygwin Terminal icon (might be on the desktop or search on start screen)
- Right click the icon and select “Run As Administrator”
- Confirm the elevated privileges
- The terminal window is now open
Within the terminal window, you are going to want to run the ssh-host-config program which will prompt you for some questions and then initialize and configure the sshd service. The sequence:
$ ssh-host-config *** Query: Should privilege separation be used? <yes/no>: yes *** Query: New local account 'sshd'? <yes/no>: yes *** Query: Do you want to install sshd as a service? *** Query: <Say "no" if it is already installed as a service> <yes/no>: yes *** Query: Enter the value of CYGWIN for the deamon:  binmode ntsec *** Query: Do you want to use a different name? (yes/no) no *** Query: Create new privileged user account 'cyg_server'? (yes/no) yes *** Query: Please enter the password: *** Query: Renter:
At this point, the majority of the sshd configuration is in place. However, Cygwin, at least for me, had a couple of bugs where permissions on files and a directory needed to be updated in order for sshd to run. Specific examples of what I saw within /var/log/sshd.log were as follows:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0660 for '/etc/ssh_host_rsa_key' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. bad permissions: ignore key: /etc/ssh_host_rsa_key Could not load host key: /etc/ssh_host_rsa_key ... /var/empty must be owned by root and not group or world-writable.
The private key file error was present for each of the keys generated by ssh-host-config. In order to fix this, issue the following commands (still in the terminal window with administrator privileves):
$ chmod 600 /etc/ssh*key $ chmod 600 /var/empty
Configuring sshd public key authentication
The last remaining step before starting sshd and configuring your keys and client, is to update the sshd configuration to allow public keys. This is done by editing the /etc/sshd_config file. Note, that in addition to enabling the use of public keys, the configuration disables the use of passwords. The use of public keys is generally more secure than allowing password authentication.
In the same terminal window that has administrator privileges, open /etc/sshd_config. Look for a the two lines resembling:
#RSAAuthentication yes #PubkeyAuthentication yes
And change them to:
RSAAuthentication yes PubkeyAuthentication yes
Next look for the line:
And change it to:
The first two lines enable public key authentication. The last disables password authentication.
Allowing sshd through the Windows Firewall
If you are running the Windows Firewall (a wise thing to do), it is likely that you will need to enable sshd through. This opens up port 22 on your machine. In order to do this, the following steps are needed:
- Open Control Panel
- Select System and Security
- Under “Windows Firewall” select “Allow an app through Windows Firewall”
- The resulting window has a list of “Allowed apps and features”, click the “Change settings” button
- Next click the “Allow another app…” button
- In the dialog that comes up, click the “Browse” button
- In the file picker window, navigate to where Cygwin was installed, then to “/usr/sbin” under that location. For me it was C: -> Cygwin64 -> usr -> sbin
- Select “sshd” from the list of applications and click the “Open” button
- In the “Add an app” dialog, verify that “Path” points to sshd.exe and click “Add”
- Upon return to the “Allowed apps” dialog, click “OK” and you are done.
Starting the sshd server
Again within the terminal window, you can start sshd with the following command:
$ cygrunsrv -S sshd
The will schedule the service to run and it will persist across reboots, etc.
If you want to turn the sshd service off temporarily, for instance to change config settings, issue the command:
$ cygrunsrv -E sshd
If you want to completely disable and remove the sshd service from running, use the command:
$ cygrunsrv -R sshd
Setting up a key pair to enable user access
The basic idea behind the use of a public/private key pair for access via ssh is that the private key (which should be kept secure) is placed upon the machine you want to connect from and the machine you are connecting to is configured with one or more keys approved for the user you are logging in as. The assumption here is that you are accessing the machine running sshd either from a UNIX-based machine or another Windows machine also running Cygwin.
The basic steps are:
- Generate key pair on machine to be accessed
- Configure the user’s ssh config to allow this key pair for access
- Transfer the private key to the machine you will ssh from
- Configure the user’s ssh client config to use the key pair when connecting to the remote machine over ssh.
To generate the key pair, you need to be in a Cygwin terminal and enter the following command:
$ ssh-keygen -t rsa -b 2048 -C "email@example.com" Generating public/private rsa key pair. Enter file in which to save the key (/Users/randomperson/.ssh/id_rsa): /Users/randomperson/.ssh/randomperson_rsa Created directory '/home/randomperson/.ssh'. Enter passphrase (empty for no passphrase): <just hit return> Enter same passphrase again: <hit return again> Your identification has been saved in winders_rsa. Your public key has been saved in winders_rsa.pub. The key fingerprint is: 40:86:2d:b9:32:cc:77:ab:cd:c4:b7:02:40:57:f4:34 firstname.lastname@example.org The key's randomart image is: +--[ RSA 2048]----+ | *= E | | . =o.o . | | + . o. . | | * o .. | | = o .S | | . + . | | * . . | | . + . | | . | +-----------------+
For the password, leave it blank and press return for it and the confirmation.
If this is your first time generating a key pair, the “Created directory” line will be present. If not, it will not be there. The contents of the .ssh directory will resemble something like:
$ ls -ltra ~/.ssh total 9 drwxrwxr-x+ 1 randomperson randomperson 0 Aug 14 15:01 .. drwx------+ 1 randomperson randomperson 0 Aug 14 15:01 . -rw------- 1 randomperson randomperson 1679 Aug 14 15:01 randomperson_rsa -rw-r--r-- 1 randomperson randomperson 388 Aug 14 15:01 randomperson_rsa.pub
The file ending in “.pub” is the public key, the other is the private key.
To allow this newly created key to be used for connecting to the machine via ssh, we need to add it to the list of “authorized keys”. This is simply a file in the .ssh directory named authorized_keys.
To add the key, you copy the contents of the public key (randomperson_rsa.pub) into the file authorized keys. This can simply be done as follows:
$ cat ~/.ssh/randomperson_rsa.pub >> ~/.ssh/authorized_keys
The resulting content of ~/.ssh/authorized_keys should resemble:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC67ho4hv1oYlZWy+t0nKx1LhJSqafARKzJ2IfdgdrK91kRLf4nQ9IW+X2p0jjE 4MZekHiurzDKldA21uNp5iJjOweU+LBb00UpX7y9KmCbwaZgoRETy8o9pQO0/OzM5LznYkkX5Wr3LWamGWSzk/AOmWmANigXBv1v BPVIxJzg0U3Hv4O4pAfPtJlwA3+6O+TCe75Eeq4TEX87SgLuH5byWZ10uQP5yHgaYDgE7AUmgyyhf8D4xr0hu8vR44a6msta4t8A pvGZ6NW9Qp7NQDltzcaZWywsdxQyem8hmLZurARwzAJ4+qSuXe7OHApKuHhVeYBX5x9Wnskfv6h4DKQL randomperson@outloo k.com
SSH can be quite picky about permissions of files. And sometimes the Cygwin tools don’t always do the right thing. So, it is recommended that you issue the following set of commands. In them “USERNAME” refers to your username within the Cygwin terminal window.
chown -R USERNAME ~USERNAME/.ssh chmod 700 ~USERNAME/.ssh chmod 600 ~USERNAME/.ssh/authorized_keys
The final step in configuring client access to the machine is to actually configure the remote machine with the private key of the pair generated. It is an exercise for the reader to determine how to get the private key from where it was generated to the second machine. Once the key is on the second machine (it is assumed that it is in the home directory of the user for now), execute the following:
$ mkdir .ssh $ mv randomperson_rsa .ssh/
Then create (or edit) the file .ssh/config adding the following contents:
Host WINDOWSMACHINE User randomperson HostName WINDOWSMACHINE IdentityFile ~/.ssh/randomperson_rsa
WINDOWSMACHINE should be replaced with the machine name of the Windows machine you want to ssh into. And like other examples above “randomperson” should be replaced with your username on the remote Windows machine.
Again, like on the Windows machine, ssh can be picky about permissions. So, just to be sure, again issue the commands on this machine:
chown -R USERNAME ~USERNAME/.ssh chmod 700 ~USERNAME/.ssh chmod 600 ~USERNAME/.ssh/randomperson_rsa
There are many ways to setup ssh on windows. There are also other ssh servers available for Windows beyond openssh on Cygwin;. That said, the above is for the use case of wanting to remotely connect to a windows machine using ssh from either another machine running Cygwin or a UNIX-based machine. This post is the basis for a couple of upcoming posts about dual/cross platform development.
If you have questions, feel free to contact me.