Blog

Écrire un remplacement à OpenSSH en utilisant Go (1/2)

Chargement...

10 min de lecture

Écrire un remplacement à OpenSSH en utilisant Go (1/2)

La deuxième partie est en direct : Écrire un remplacement d'OpenSSH en utilisant Go (2/2) SSH est un protocole bien connu pour accéder aux serveurs distants et OpenSSH est l'implémentation la plus courante. Cet article expliquera comment construire un serveur et un client SSH en utilisant Go. TL;DR Pourquoi le serveur OpenSSH n'est pas suffisant dans un environnement distribué.

La deuxième partie est en direct : Écrire un remplacement à OpenSSH en utilisant Go (2/2)

SSH est un protocole bien connu pour accéder à des serveurs distants et OpenSSH est l'implémentation la plus courante. Cet article expliquera comment construire un serveur et un client SSH en utilisant Go.

TL;DR

  • Pourquoi le serveur OpenSSH n'est pas suffisant dans un environnement distribué

  • Quels sont les outils et bibliothèques disponibles en Go pour utiliser le protocole SSH

  • Quelques exemples d'implémentation

Git et SSH

Dans une plateforme en tant que service comme Scalingo, la manière standard de déployer une application est d'utiliser git push. En arrière-plan, git utilise simplement la commande ssh. Les deux lignes ci-dessous expliquent le lien entre eux :

# With appsdeck remote: git@appsdeck.eu:myproject.git
~/myproject $ git push appsdeck master

# Git will execute:
~/myproject $ ssh git

# With appsdeck remote: git@appsdeck.eu:myproject.git
~/myproject $ git push appsdeck master

# Git will execute:
~/myproject $ ssh git

# With appsdeck remote: git@appsdeck.eu:myproject.git
~/myproject $ git push appsdeck master

# Git will execute:
~/myproject $ ssh git

# With appsdeck remote: git@appsdeck.eu:myproject.git
~/myproject $ git push appsdeck master

# Git will execute:
~/myproject $ ssh git

En fait, il est possible de dire à git d'utiliser un autre client SSH, en définissant la variable d'environnement GIT_SSH.

Limitation d'OpenSSH

Pour authentifier un utilisateur sur un serveur distant en utilisant le serveur OpenSSH, la clé SSH publique de l'utilisateur doit être ajoutée dans le fichier ~/.ssh/authorized_keys de l'utilisateur cible. Si OpenSSH trouve la clé publique dans ce fichier, l'authentification est considérée comme réussie. Par défaut, il exécuterait le shell de l'utilisateur, défini par son compte.

Il est possible d'exécuter une commande personnalisée en la préfixant à la clé SSH publique dans le fichier authorized_keys :

command="ssh-handler" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA[...]2bF26cl
command="ssh-handler" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA[...]2bF26cl
command="ssh-handler" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA[...]2bF26cl
command="ssh-handler" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA[...]2bF26cl

Dans ce cas, au lieu d'exécuter le shell de l'utilisateur, il exécutera la commande “ssh-handler”. Notre premier prototype utilisait cette fonctionnalité pour authentifier et autoriser nos utilisateurs. Cependant, dès que vous voulez construire une véritable infrastructure distribuée, ce n'est plus suffisant. En effet, avec cette méthode, cela signifie que plusieurs hôtes doivent garder leur fichier authorized_keys contenant toutes les clés publiques de nos utilisateurs synchronisées. C'est deux problèmes en un : nous devions trouver un mécanisme de synchronisation, et, des données sensibles sont éparpillées sur plusieurs machines.

C'est pourquoi nous avons décidé qu'il était temps de construire quelque chose de plus robuste et évolutif en écrivant notre propre serveur SSH personnalisé, qui serait capable d'utiliser un backend personnalisé pour identifier nos utilisateurs et ensuite transmettre la connexion SSH à un autre hôte qui exécutera réellement l'opération GIT.

SSH dans le monde Go

Nous avons décidé d'écrire ce serveur SSH personnalisé avec Go pour différentes raisons. Excepté le fait que nous avions de l'expérience avec le langage, ce package officiel (http://godoc.org/golang.org/x/crypto/ssh) implémente tout ce dont nous avions besoin pour construire ce que nous recherchions, tout en gardant cela simple.

Chez Scalingo, nous cherchons à respecter le principe KISS. Si un logiciel est simple, il est plus facile de conserver la lisibilité, la modularité et la facilité de maintenance. D'ailleurs, c'est aussi pourquoi Go est devenu l'un de nos langages principaux.

Les RFC SSH

Alors que le package Go implémente la configuration des connexions SSH (ce qui inclut le transport et le cryptage), vous devez toujours comprendre et utiliser le protocole applicatif SSH pour construire votre logiciel.

Pour y parvenir, il est important de comprendre comment SSH fonctionne, les RFC suivantes définissent le protocole :

Chaque fois que vous avez besoin d'explications sur une méthode ou une constante du package Go, il est assez simple de se référer aux RFC avec une simple recherche textuelle.

(Les RFC 4255 et 4256 concernent également SSH mais sont moins utiles dans ce contexte)

Exemples de code

1. Serveur de base

L'exemple de code suivant définit un simple serveur SSH : https://github.com/Scalingo/go-ssh-examples/blob/master/server.go

Ce serveur affiche uniquement le type de clé SSH utilisé pour l'authentification (le cas échéant), l'accepte, puis ferme la connexion.

Serveur :

> go run server.go
2014/12/05 15:41:27 [::1]:46428 authenticate with ssh-rsa
2014/12/05 15:41:27 Connection from [::1]:46428
> go run server.go
2014/12/05 15:41:27 [::1]:46428 authenticate with ssh-rsa
2014/12/05 15:41:27 Connection from [::1]:46428
> go run server.go
2014/12/05 15:41:27 [::1]:46428 authenticate with ssh-rsa
2014/12/05 15:41:27 Connection from [::1]:46428
> go run server.go
2014/12/05 15:41:27 [::1]:46428 authenticate with ssh-rsa
2014/12/05 15:41:27 Connection from [::1]:46428

Client :

> ssh localhost -p 2222
Connection to localhost closed by remote host.
Connection to localhost closed

> ssh localhost -p 2222
Connection to localhost closed by remote host.
Connection to localhost closed

> ssh localhost -p 2222
Connection to localhost closed by remote host.
Connection to localhost closed

> ssh localhost -p 2222
Connection to localhost closed by remote host.
Connection to localhost closed

Comme prévu, notre serveur Go réussit à communiquer avec OpenSSH, mais ensuite la connexion est immédiatement fermée.

2. Client de base

https://github.com/Scalingo/go-ssh-examples/blob/master/client.go

Utilisation :

go run client.go <user> <server:port> <command>
go run client.go <user> <server:port> <command>
go run client.go <user> <server:port> <command>
go run client.go <user> <server:port> <command>

Ce client a juste un travail, il se connecte à un serveur, crée une session, exécute une commande, puis imprime la sortie et se déconnecte.

Sortie :

> go run client.go foobar example.com:22 'ls /'
Password: *********
bin
boot
conf.d
dev
etc
home
initrd.img
lib[...

> go run client.go foobar example.com:22 'ls /'
Password: *********
bin
boot
conf.d
dev
etc
home
initrd.img
lib[...

> go run client.go foobar example.com:22 'ls /'
Password: *********
bin
boot
conf.d
dev
etc
home
initrd.img
lib[...

> go run client.go foobar example.com:22 'ls /'
Password: *********
bin
boot
conf.d
dev
etc
home
initrd.img
lib[...

Conclusion

Cet article présente notre problématique et comment utiliser le protocole SSH avec Go. Dans le prochain article, nous expliquerons comment nous utilisons cette bibliothèque pour résoudre nos vrais problèmes (Authentification, Autorisation, Proxy de connexion).

À suivre…

… Prêt ? La deuxième partie est ici : Écrire un remplacement à OpenSSH en utilisant Go (2/2)

Liens

Cet article était le 2ème post de la série #FridayTechnical, à la prochaine fois !

Crédits

Image Gopher par Renee French (Attribution Creative Commons 3.0) Puffy - Logo OpenSSH

— Léo Unbekandt, CTO @ Scalingo

Léo Unbekandt, Scalingo

Léo Unbekandt

Léo est le fondateur et CTO de Scalingo. Il a étudié en France en tant qu'ingénieur cloud (ENSIIE) et en Angleterre (Cranfield University). Il est responsable du développement technique de Scalingo et il gère notre équipe technique.

Restez informé

Recevez des articles et des mises à jour de la plateforme dans votre boîte de réception.

Prêt à déployer en toute confiance ?

Découvrez des déploiements sans temps d'arrêt, une mise à l'échelle automatique intelligente et une infrastructure entièrement gérée. Commencez à déployer vos applications sur Scalingo dès aujourd'hui.

Aucune carte de crédit requise • Déployez en quelques minutes • Annulez à tout moment

Déployez une première application ou base de données

Commencez à déployer

Rejoignez les équipes qui misent sur une plateforme conçue pour livrer rapidement, opérer sereinement, avec des valeurs européennes et un support humain.

Déployez une première application ou base de données

Commencez à déployer

Rejoignez les équipes qui misent sur une plateforme conçue pour livrer rapidement, opérer sereinement, avec des valeurs européennes et un support humain.

Déployez une première application ou base de données

Commencez à déployer

Rejoignez les équipes qui misent sur une plateforme conçue pour livrer rapidement, opérer sereinement, avec des valeurs européennes et un support humain.