AjaxTerm : accès SSH minimaliste via le navigateur (après correction CSS)

AjaxTerm permet d’accéder à son serveur SSH via une interface HTML.
A quoi ça sert? A pouvoir utiliser la ligne de commande dans un navigateur, via le protocole HTTP. C’est utile notamment quand le port SSH est bloqué par un proxy d’entreprise.

AjaxTerm est minimaliste et n’a pas évolué depuis des années. Mais il est très léger et facile à installer. Pour une utilisation ponctuelle hébergée sur un serveur peu puissant, je le trouve tout à fait adapté.

Le problème, c’est que, avec le package fourni par Debian, l’interface est quasi inutilisable sur un navigateur récent :
– le curseur n’est pas visible
– la police est proportionnelle donc les caractères ne sont pas alignés verticalement
– les passages à la ligne ne sont pas respectés

AjaxTerm CSS incorrect

Correctif du bug CSS

Tous ces problèmes viennent du style CSS qui ne s’applique pas correctement au HTML de AjaxTerm.
En le corrigeant un peu, AjaxTerm retrouve sa mise en forme normale :

AjaxTerm CSS corrigé

Il suffit de modifier le fichier /usr/share/ajaxterm/ajaxterm.css, pour remplacer son contenu par :

pre.stat {
    margin: 0px;
    padding: 4px;
    display: block;
    font-family: monospace;
    white-space: pre;
    background-color: black;
    border-top: 1px solid black;
    color: white;
}
pre.stat span {
    padding: 0px;
}
pre.stat .on {
    background-color: #080;
    font-weight: bold;
    color: white;
    cursor: pointer;
}
pre.stat .off {
    background-color: #888;
    font-weight: bold;
    color: white;
    cursor: pointer;
}
#term {
    float: left;
    margin: 0px;
    padding: 4px;
    display: block;
    font-family: monospace;
    white-space: pre;
    background-color: black;
    border-top: 1px solid white;
    color: #eee;
}
span.f0  { color: #000; }
span.f1  { color: #b00; }
span.f2  { color: #0b0; }
span.f3  { color: #bb0; }
span.f4  { color: #00b; }
span.f5  { color: #b0b; }
span.f6  { color: #0bb; }
span.f7  { color: #bbb; }
span.f8  { color: #666; }
span.f9  { color: #f00; }
span.f10 { color: #0f0; }
span.f11 { color: #ff0; }
span.f12 { color: #00f; }
span.f13 { color: #f0f; }
span.f14 { color: #0ff; }
span.f15 { color: #fff; }
span.b0  { background-color: #000; }
span.b1  { background-color: #b00; }
span.b2  { background-color: #0b0; }
span.b3  { background-color: #bb0; }
span.b4  { background-color: #00b; }
span.b5  { background-color: #b0b; }
span.b6  { background-color: #0bb; }
span.b7  { background-color: #bbb; }

body { background-color: #888; }

Le problème venait du fait que le CSS utilisait un sélecteur « pre.term » qui ne correspondait à aucune balise HTML. Par conséquent les styles qui l’utilisaient n’étaient pas appliqués.

Apparemment ce bug a été rapporté il y a peu de temps, mais n’avait pas encore été corrigé. J’ai donc proposé mon petit patch (à l’auteur de AjaxTerm, et dans le bug ouvert chez Debian).

Mais d’où vient ce bug?

Il parait trop gros pour ne jamais avoir été vu depuis qu’il a été développé (en 2006)…

En creusant un peu, je me suis rendu compte que AjaxTerm (sans mon correctif) fonctionnait très bien avec des navigateurs plus anciens. Sur Firefox 3.0, et jusqu’à Firefox 19, pas de problèmes. Idem avec IE8.

C’est à partir de la version 20 de Firefox que ça n’a plus marché.

Damned, serait-ce une régression de Firefox dans la prise en charge CSS?

Et bien non, c’est un peu + compliqué que ça : le DOM généré était légèrement différent dans les anciennes versions du navigateur. Et, en particulier, cela générait bien un nœud <pre class= »term »> à l’endroit attendu par le style CSS d’origine.

Dans les versions + récentes du navigateur (que ce soit Firefox ou Chromium/Chrome), ce nœud n’est pas généré. J’ai regardé rapidement le changelog de la version 20 de Firefox, mais je n’ai pas trouvé ce qui expliquerait ce petit changement.

NB : le CSS que je propose fonctionne à la fois sur les anciennes et récentes versions de navigateurs

Et la sécurité, dans tout ça?

D’abord une évidence : il faut crypter la communication HTTP pour que le trafic ne passe pas en clair sur le réseau. Donc cryptage SSL obligatoire.

D’autre part, à ma connaissance, on ne peut pas utiliser d’authentification par clé avec AjaxTerm : on est donc limité à l’authentification par mot de passe.

Mais au fait, avec mon beau Fail2ban qui contrôle les tentatives d’accès par SSH, qu’est-ce que ça donne avec AjaxTerm?

Sans surprise, les connexions semblent toutes venir de 127.0.0.1. Donc si Fail2ban bloque cette adresse, c’est tout AjaxTerm qui est bloqué.

Mais surtout, le gros problème est que, par défaut, Fail2ban ignore les échecs de connexion provenant de 127.0.0.1 : dans /etc/fail2ban/jail.conf :

# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1/8

Donc, par défaut, Fail2ban ne surveille pas les connexions SSH qui proviennent de AjaxTerm. Et ça, c’est pas cool.

Bien sûr, c’est paramétrable et on peut enlever 127.0.0.1 des IP ignorées. Mais  je n’ai pas osé le faire.

Au final, j’ai préféré protéger l’accès à AjaxTerm en configurant le VirtualHost Apache avec un autre login/mot de passe. Cette première authentification en Basic Authentication (sur HTTPS bien sûr) est bien surveillée par Fail2ban, qui bloquera bien uniquement l’IP qui pose problème.

Comme il s’agit d’une utilisation ponctuelle, cette double authentification n’est pas une grosse contrainte pour moi.

6 réflexions sur « AjaxTerm : accès SSH minimaliste via le navigateur (après correction CSS) »

  1. On peut aussi utiliser facilement Stylish sur Firefox pour ne pas toucher au serveur (style je cherche à me connecter depuis le boulot, ca marche pas et je peux pas modifier la CSS a distance sans… ajaxterm)

  2. Merci, idéal avec un Raspberry Pi Zero !
    La nouvelle forme; achilterm, ne marche pas sous Raspbian, il faut le compiler et il manque des pré-requis, mais ajaxterm est prébuild, et en effet, il à besoin d’un correctif au niveau CSS.

    Un simple replace de « .term » en « #term » au document suffit :)

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *