10 min read
Writing a replacement to OpenSSH using Go (1/2)
The second part is live: Writing a replacement to OpenSSH using Go (2/2) SSH is a well-known protocol to access remote servers and OpenSSH is the most common implementation. This article will explain how to build a SSH server and client using Go. TL;DR Why OpenSSH Server is not sufficient in a distributed environ

The second part is live: Writing a replacement to OpenSSH using Go (2/2)
SSH is a well-known protocol to access remote servers and OpenSSH is the most common implementation. This article will explain how to build a SSH server and client using Go.
TL;DR
Why OpenSSH Server is not sufficient in a distributed environment
What are the available tools and libraries in Go to use the SSH protocol
A few implementation examples
Git and SSH
In a Platform as a Service such as Scalingo, the standard way to deploy an application is to use git push. Underneath, git is simply using the ssh command. The two lines below explain the link between them:
Actually, it is possible to tell git to use another SSH client, by setting the environment variable GIT_SSH.
OpenSSH limitation
To authenticate a user to a remote server using OpenSSH Server, the user’s public SSH key has to be appended in the ~/.ssh/authorized_keys file of the target user. If OpenSSH finds the public key in this file, the authentication is considered successful. By default, it would execute the shell of the user, defined by its account.
It is possible to execute a custom command by prepending it to the public SSH key in the authorized_keys file:
In this case, instead of running the shell of the user, it will run the command “ssh-handler”. Our first prototype was using this feature to authenticate and authorize our users. However, as soon as you want to build a real distributed infrastructure, it’s not sufficient anymore. Indeed, with this method, it means that several hosts have to keep their authorized_keys file containing all the public keys of our users in sync. That’s two problems in one : we had to find a synchronization mechanism, and, sensitive data are spread out on several machines.
That’s why we decided it was time to build something more robust and scalable by writing our own custom SSH server, which would be able to use a custom backend to identify our users and then to forward the SSH connection to another host which will actually execute the GIT operation.
SSH in the Go world
We decided to write this custom SSH server with Go for different reasons. Except the fact that we had experience with the language, this official package (http://godoc.org/golang.org/x/crypto/ssh) implements everything we needed to build what we were looking for, while keeping it simple.
At Scalingo, we are looking to respect the KISS principle. If a software is simple, it is easier to conserve readability, modularity and easy maintenance. By the way, that’s also why Go has become one of our core languages.
The SSH RFCs
While the Go package implements SSH connections setup (that includes transport and crypto), you still have to understand and to use SSH applicative protocol to build your software.
To achieve this, it is important to get how SSH is working, the following RFCs define the protocol:
Architecture: https://tools.ietf.org/html/rfc4251
Authentication protocol: https://tools.ietf.org/html/rfc4252
Transport protocol: https://tools.ietf.org/html/rfc4253
Channel management and connection protocol: https://tools.ietf.org/html/rfc4254 (probably the most useful when building your server)
Anytime you need to get explanations about a method or a constant of the Go package, refering to the RFCs is pretty straightforward with a simple text search.
(RFCs 4255 and 4256 also concern SSH but are less useful in this scope)
Code Examples
1. Basic server
The following code example defines a simple SSH server: https://github.com/Scalingo/go-ssh-examples/blob/master/server.go
This server only displays the kind of SSH key used for authentication (if any), accepts it, then closes the connection.
Server:
Client:
As expected, our Go server succeeds to speak with OpenSSH, but then the connection is closed instantly.
2. Basic client
https://github.com/Scalingo/go-ssh-examples/blob/master/client.go
Usage:
This client has only one job, it connects to a server, creates a sessions, executes a command, then prints the output and disconnects.
Output:
Conclusion
This article introduces our problematic and how to use the SSH protocol with Go. In the next article we’ll explain how we use this library to solve our real problems (Authentication, Authorization, Connection Proxying).
To be continued…
… Ready? Second part is here: Writing a replacement to OpenSSH using Go (2/2)
Links
Package documentation: http://godoc.org/golang.org/x/crypto/ssh
Code snippets: https://github.com/Scalingo/go-ssh-examples
This article was the 2nd post of the serie #FridayTechnical, see you next time!
Credits
Gopher image by Renee French (Creative Commons Attributions 3.0) Puffy - OpenSSH logo
— Léo Unbekandt, CTO @ Scalingo

Léo Unbekandt
Léo is the founder and CTO of Scalingo. He studied in France as a cloud engineer (ENSIIE) and in England (Cranfield University). He is in charge of Scalingo's technical development and he manages Scalingo's tech team.
Stay Updated
Get articles and platform updates in your inbox.
Ready to Deploy with Confidence?
Experience zero-downtime deployments, intelligent auto-scaling, and fully managed infrastructure. Start deploying your applications on Scalingo today.
No credit card required • Deploy in minutes • Cancel anytime






