Securing Svnserve using SSH

This section provides a step-by-step guide to setting up Subversion and TortoiseSVN to use the svn+ssh protocol. If you already use authenticated SSH connections to login to your server, then you are already there and you can find more detail in the Subversion book. If you are not using SSH but would like to do so to protect your Subversion installation, this guide gives a simple method which does not involve creating a separate SSH user account on the server for every subversion user.

In this implementation we create a single SSH user account for all subversion users, and use different authentication keys to differentiate between the real Subversion users.

In this appendix we assume that you already have the subversion tools installed, and that you have created a repository as detailed elsewhere in this manual. Note that you should not start svnserve as a service or daemon when used with SSH.

Much of the information here comes from a tutorial provided by Marc Logemann, which has been archived at tortoisesvn.net. Additional information on setting up a Windows server was provided by Thorsten Müller. Thanks guys!

You can also watch a video tutorial created by Maximo Migliari which takes you through all the important steps. Watch it on Vimeo. or YouTube.

Setting Up a Linux Server

You need to have SSH enabled on the server, and here we assume that you will be using OpenSSH. On most distributions this will already be installed. To find out, look for ssh jobs by typing:

ps xa | grep sshd

One point to note is that if you build Subversion from source and do not provide any argument to ./configure, Subversion creates a bin directory under /usr/local and places its binaries there. If you want to use tunneling mode with SSH, you have to be aware that the user logging in via SSH needs to execute the svnserve program and some other binaries. For this reason, either place /usr/local/bin into the PATH variable or create symbolic links of your binaries to the /usr/sbin directory, or to any other directory which is commonly in the PATH.

To check that everything is OK, login in as the target user with SSH and test whether svnserve is now reachable by typing:

which svnserve

Create a new user which we will use to access the svn repository:

useradd -m svnuser

Be sure to give this user full access rights to the repository.

Setting Up a Windows Server

Install Cygwin SSH daemon as described in this article.

Create a new Windows user account svnuser which we will use to access the repository. Be sure to give this user full access rights to the repository.

If there is no password file yet then create one from the Cygwin console using:

mkpasswd -l > /etc/passwd

SSH Client Tools for use with TortoiseSVN

Grab the tools we need for using SSH on the windows client from the PuTTY site. Just go to the download section and get Putty, Plink, Pageant and Puttygen.

Creating OpenSSH Certificates

The next step is to create a key pair for authentication. There are two possible ways to create keys. The first is to create the keys with PuTTYgen on the client, upload the public key to your server and use the private key with PuTTY. The other is to create the key pair with the OpenSSH tool ssh-keygen, download the private key to your client and convert the private key to a PuTTY-style private key.

Create Keys using ssh-keygen

Login to the server as root or svnuser and type:

ssh-keygen -b 1024 -t dsa -N passphrase -f keyfile

substituting a real pass-phrase (which only you know) and key file. We just created a SSH2 DSA key with 1024 bit key-phrase. If you type

ls -l keyfile*

you will see two files, keyfile and keyfile.pub. As you might guess, the .pub file is the public key file, the other is the private one.

Append the public key to those in the .ssh folder within the svnuser home directory:

cat keyfile.pub >> /home/svnuser/.ssh/authorized_keys
.

In order to use the private key we generated, we have to convert it to a putty format. This is because the private key file format is not specified by a standards body. After you download the private key file to your client PC, start PuTTYgen and use Conversions -> Import key Browse to your file keyfile which you got from the server the passphrase you used when creating the key. Finally click on Save private key and save the file as keyfile.PPK.

Create Keys using PuTTYgen

Use PuTTYgen to generate a public-key/private-key pair and save it. Copy the public key to the server and append it to those in the .ssh folder within the svnuser home directory:

cat keyfile.pub >> /home/svnuser/.ssh/authorized_keys

Test using PuTTY

To test the connection we will use PuTTY. Start the program and on the Session tab set the hostname to the name or IP address of your server, the protocol to SSH and save the session as SvnConnection or whatever name you prefer. On the SSH tab set the preferred SSH protocol version to 2 and from Auth set the full path to the .PPK private key file you converted earlier. Go back to the Sessions tab and hit the Save button. You will now see SvnConnection in the list of saved sessions.

Click on Open and you should see a telnet style login prompt. Use svnuser as the user name and if all is well you should connect directly without being prompted for a password.

You may need to edit /etc/sshd_config on the server. Edit lines as follows and restart the SSH service afterwards.

PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no

Testing SSH with TortoiseSVN

So far we have only tested that you can login using SSH. Now we need to make sure that the SSH connection can actually run svnserve. On the server modify /home/svnuser/.ssh/authorized_keys as follows to allow many subversion authors to use the same system account, svnuser. Note that every subversion author uses the same login but a different authentication key, thus you have to add one line for every author. Note: This is all on one very long line.

command="svnserve -t -r <ReposRootPath> --tunnel-user=<author>",
         no-port-forwarding,no-agent-forwarding,no-X11-forwarding,
         no-pty ssh-rsa <PublicKey> <Comment>

There are several values that you need to set according to your setup.

<ReposRootPath> should be replaced with the path to the directory containing your repositories. This avoids the need to specify full server paths within URLs. Note that you must use forward slashes even on a Windows server, e.g. c:/svn/reposroot. In the examples below we assume that you have a repository folder within the repository root called repos.

<author> should be replaced with the svn author that you want to be stored on commit. This also allows svnserve to use its own access rights within svnserve.conf.

<PublicKey> should be replaced with the public key that you generated earlier.

<Comment> can be any comment you like, but it is useful for mapping an svn author name to the person's real name.

Right click on any folder in Windows Explorer and select TortoiseSVN -> Repo-Browser You will be prompted to enter a URL, so enter one in this form:

svn+ssh://svnuser@SvnConnection/repos

What does this URL mean? The Schema name is svn+ssh which tells TortoiseSVN how to handle the requests to the server. After the double slash, you specify the user to connect to the server, in our case svnuser. After the @ we supply our PuTTY session name. This session name contains all details like where to find the private key and the server's IP or DNS. Lastly we have to provide the path to the repository, relative to the repository root on the server, as specified in the authorized_keys file.

Click on OK and you should be able to browse the repository content. If so you now have a running SSH tunnel in conjunction with TortoiseSVN.

Note that by default TortoiseSVN uses its own version of Plink to connect. This avoids a console window popping up for every authentication attempt, but it also means that there is nowhere for error messages to appear. If you receive the error Unable to write to standard output, you can try specifying Plink as the client in TortoiseSVN's network settings. This will allow you to see the real error message generated by Plink.

SSH Configuration Variants

One way to simplify the URL in TortoiseSVN is to set the user inside the PuTTY session. For this you have to load your already defined session SvnConnection in PuTTY and in the Connection tab set Auto login user to the user name, e.g. svnuser. Save your PuTTY session as before and try the following URL inside TortoiseSVN:

svn+ssh://SvnConnection/repos

This time we only provide the PuTTY session SvnConnection to the SSH client TortoiseSVN uses (TortoisePlink.exe). This client will check the session for all necessary details.

At the time of writing PuTTY does not check all saved configurations, so if you have multiple configurations with the same server name, it will pick the first one which matches. Also, if you edit the default configuration and save it, the auto login user name is not saved.

Many people like to use Pageant for storing all their keys. Because a PuTTY session is capable of storing a key, you don't always need Pageant. But imagine you want to store keys for several different servers; in that case you would have to edit the PuTTY session over and over again, depending on the server you are trying to connect with. In this situation Pageant makes perfect sense, because when PuTTY, Plink, TortoisePlink or any other PuTTY-based tool is trying to connect to an SSH server, it checks all private keys that Pageant holds to initiate the connection.

For this task, simply run Pageant and add the private key. It should be the same private key you defined in the PuTTY session above. If you use Pageant for private key storage, you can delete the reference to the private key file in your saved PuTTY session. You can add more keys for other servers, or other users of course.

If you don't want to repeat this procedure after every reboot of your client, you should place Pageant in the auto-start group of your Windows installation. You can append the keys with complete paths as command line arguments to Pageant.exe.

The last way to connect to an SSH server is simply by using this URL inside TortoiseSVN:

svn+ssh://svnuser@100.101.102.103/repos
svn+ssh://svnuser@mydomain.com/repos

As you can see, we don't use a saved PuTTY session but an IP address (or domain name) as the connection target. We also supply the user, but you might ask how the private key file will be found. Because TortoisePlink.exe is just a modified version of the standard Plink tool from the PuTTY suite, TortoiseSVN will also try all the keys stored in Pageant.

If you use this last method, be sure you do not have a default username set in PuTTY. We have had reports of a bug in PuTTY causing connections to close in this case. To remove the default user, simply clear HKEY_CURRENT_USER\Software\SimonTatham\Putty\Sessions\Default%20Settings\HostName.