4 Commits

5 changed files with 406 additions and 15 deletions
Split View
  1. +3
    -3
      content/2019/rudder-outil-conformite.rst
  2. +403
    -0
      content/2024/ssh_over_haproxy.rst
  3. +0
    -12
      content/_drafts/fairphone-2-et-open-os.md
  4. BIN
      content/images/ssh-openssl-haproxy/ssh_over_ssl.png
  5. BIN
      content/images/ssh-openssl-haproxy/ssh_simple.png

+ 3
- 3
content/2019/rudder-outil-conformite.rst View File

@ -1,6 +1,6 @@
Suivre vos serveurs avec rudder
###############################
:subtitle: - conformité et maîtrise opérationnelle
:subtitle: \- conformité et maîtrise opérationnelle
:date: 2019-07-28 18:32
:authors: Victor
:slug: rudder-outil-conformite
@ -8,7 +8,7 @@ Suivre vos serveurs avec rudder
:tags: rudder, mco, conformité, ansible
:keywords: rudder, mco, conformité, ansible
:status: published
:summary: - conformité et maîtrise opérationnelle
:summary: conformité et maîtrise opérationnelle
.. contents::
@ -218,4 +218,4 @@ C'est un outil vraiment très pratique et qui laisse une grande part à l'imagin
Avoir un pool de serveurs à gérer n'a jamais été aussi agréable !
Si cet article vous a plu, ou si vous souhaitez que j'aborde plus en détails certains points de rudder, n'hésitez pas à laisser un commentaire !
Si cet article vous a plu, ou si vous souhaitez que j'aborde plus en détails certains points de rudder, n'hésitez pas à laisser un commentaire !

+ 403
- 0
content/2024/ssh_over_haproxy.rst View File

@ -0,0 +1,403 @@
SSH over Openssl over Haproxy
###############################
:subtitle: \- contourner les blocages
:date: 2024-02-23 10:22
:authors: Victor
:slug: ssh-openssl-haproxy
:category: Réseaux
:tags: ssh, astuces, openssl, haproxy
:keywords: ssh, astuces, openssl, haproxy
:status: draft
:summary: contourner les blocages
.. contents::
Contexte
=======================
Parfois, en entreprise ou dans les hôtels, des règles de sécurité sont mises en place pour empêcher les employés de sortir sur d'autres ports que l'http⋅s (ports 80 et 443)
Selon l'intelligence du matériel utilisé, il sera capable de détecter si le flux est de l'http, du ssh, ou un autre protocole interdit et en conséquence, contourner ce genre de protection peut s'avérer complexe.
Bien entendu, jamais je ne conseillerai de contourner les protections mises en place par votre entreprise 😇
Par contre, rien n'empêche de donner un coup de main à votre SI en pointant les failles du système qu'une personne mal intentionnée pourrait utiliser.
Je vous invite à consulter votre charte informatique quand aux éventuelles conséquences, mais sachez que **si protection il y a, vous devez légalement en être informé par écrit**.
Cela étant posé, je vais ici vous proposer d'utiliser Haproxy pour passer outre 2 types de protections :
1. Un blocage des ports autres que 80/443 sans vérification du type de protocole
2. Un blocage des ports autres que 80/443, avec vérification du type de protocole
L'objectif sera de faire passer **un flux ssh** sur le port 443 (étape 1), puis de **l'encapsuler dans du SSL** (étape 2).
Je partirai du principe que vous avez un serveur avec Haproxy installé et fonctionnel, par exemple pour servir vos sites habituels.
**Disclaimer 1 :** Cette technique vous permettra d'utiliser toutes les fonctionnalités de SSH. J'écris cet article depuis le boulot en committant via un tunnel SSH sur openssl vers mon repo git. Toujours dans l'optique d'entretenir la forme de l'équipe sécurité bien sûr. 🤫
**Disclaimer 2 :** Retrouvez à la fin de l'article les configurations complètes si vous êtes pressés ^^
PS: Dans le cas où le filtrage se ferait avec un système de `Deep Packet Inspection
<https://fr.wikipedia.org/wiki/Deep_packet_inspection>`_ qui désencapsule les flux SSL pour les analyser, cela ne fonctionnera pas. Mais si vous avez une protection de ce genre, ça sous-entends que l'entreprise peut (et le fait) voir absolument tout ce que vous faites en https, que ça soit les mots de passe de votre banque ou les messages privés envoyés sur votre discord. Je vous invite à insulter votre DSI (Avec virulence) puis à changer de boite 😄
Étape 1 : SSH sur 443
=====================
La première étape va consister à assez simplement faire passer votre flux SSH sur le port 443. Si vous rencontrez un simple pare-feu qui bloque tous les ports sauf le 443, cela permettra de contourner le blocage sans problème.
Côté serveur on pourrait simplement faire écouter sshd sur ce port, ou utiliser iptables pour NATer le port 443 vers le port 22 de votre serveur **mais** c'est moins fun, et puis si vous avez déjà des sites web votre port 443 est déjà utilisé.
C'est là qu'Haproxy va intervenir car il est capable de détecter si le flux entrant est du SSH ou de l'http !
Cette étape est assez simple, on va demander à Haproxy de rediriger le flux http (plus précisément, ssl) vers votre frontend habituel, et le flux ssh **vers un serveur particulier**. On verra ensuite une technique pour dire à Haproxy quel serveur ssh on souhaite joindre 😄
.. figure:: {static}/images/ssh-openssl-haproxy/ssh_simple.png
:width: 500px
:alt: Description de l'objectif à atteindre : Un frontend Public 443 redistribue les flux vers un backend SSH et un backend SSL, ce dernier renvoyant ensuite vers le fronted HTTP SSL habituel
Première étape : séparer SSH et SSL
.. _frontend-tcp-ssl-ssh:
Frontend TCP SSL/SSH
--------------------
Tout d'abord on va modifier votre frontend qui écoute sur le port 443. En toute logique, il devrait écouter sur l'adresse IP exposée vers l'extérieur, mais on va lui dire d'écouter plutôt sur l'adresse localhost, afin de créer ensuite un nouveau frontend qui s'occupera des accès entrants.
Modifiez donc votre frontend existant :
.. code-block:: bash
frontend ft_tcpssl
# Local frontend
bind 127.0.0.1:1443 ssl crt /etc/your/certs accept-proxy
mode http
[...] # Vos acl et traitement http classiques
Modifiez bien sûr le chemin ``/etc/your/certs`` par votre répertoire habituel pour stocker vos certificats.
L'option `accept-proxy
<http://docs.haproxy.org/2.4/configuration.html#5.1-accept-proxy>`_ indique de n'accepter que les connexions de type PROXY, ce qui sera le cas via notre chaine de frontend/backend Haproxy et assure de garder un maximum d'information sur la connexion d'origine.
Ensuite, on va configurer un nouveau frontend qui se chargera de recevoir le flux sur 443 et de filtrer le flux chiffré en SSL (typiquement de l'https) de celui chiffré via SSH
Pour cela :
.. code-block:: bash
frontend 443-in
bind YOUR_IP:443
mode tcp # On est en TCP ici et pas encore en http
# On verifie les types de trafics parmi tcp over ssl, http et SSH
tcp-request inspect-delay 5s # Une connexion ssh peut être longuette à s'établir, on prends le temps d'inspecter le flux
acl trafic_ssl req.ssl_ver gt 0
acl trafic_ssh_raw req.payload(0,7) -m str SSH-2.0
Ici on définit **deux ACLs** :
* L'acl ``trafic_ssl`` se base simplement sur le fait que le flux est chiffré avec ssl
* l'acl ``trafic_ssh_raw`` quand à elle, vérifie les 7 premiers bits de payload de la connexion TCP, qui contiennent ``SSH-2.0`` dans le cas d'une transaction SSH !
Sur la base de ces ACL, on peut facilement rediriger vers les backends qui vont bien
.. code-block:: bash
# Si SSL on envoie au backend TCP pour dechiffrement
use_backend bk_tcpssl if trafic_ssl
# Si ssh direct on envoie au backend ssh
use_backend bk_ssh if trafic_ssh_raw
Backends SSL et SSH
-------------------
On va pouvoir établir les backends :
.. code-block:: bash
backend bk_tcpssl
mode tcp
timeout server 2h
server ft_tcpssl 127.0.0.1:1443 send-proxy
backend bk_ssh
mode tcp
timeout server 2h
server ssh SSH_IP_SERVER:22
On retrouve ici le frontend ``ft_tcpssl``, votre frontend habituel qui gère l'https, avec le mot clef ``send-proxy`` pour transmettre le flux sur localhost en mode PROXY.
Le bk_ssh quand à lui reste très simple, vous indiquez l'adresse IP du serveur sur lequel vous souhaitez vous connecter en ssh comme cible du backend.
(Rappel, on verra ensuite comment se connecter à plusieurs serveurs ssh sans devoir en indiquer un en dur 😜 )
Cette première configuration est assez simple, et vous permettra simplement en lançant une connexion SSH sur le port 443 de vous retrouver sur votre serveur habituel.
Les connexions pourront se faire par clef ou par mot de passe, de la manière dont vous fonctionnez en général !
.. code-block:: bash
ssh -p 443 YOUR_IP
Étape 2 : SSH sur SSL
=====================
Dans cette 2eme étape, on va ajouter une brique qui permettra d'injecter un flux SSH dans une connexion chiffrée avec SSL.
Bien que techniquement plus complexe à utiliser et à configurer, on ajoute ici 2 gros avantages.
1. Un pare-feu intelligent capable de faire la différence entre https et ssh sera incapable de bloquer ce nouveau flux, qu'il ne pourra que considérer comme de l'https
2. La possibilité d'utiliser l'en-tête SNI des connexions SSL pour choisir dynamiquement la cible de notre connexion SSH
On garde la configuration précédente, mais on va ajouter une nouvelle vérification de flux **une fois le SSL déchiffré**, pour voir si on à affaire à de l'http ou du SSH !
.. figure:: {static}/images/ssh-openssl-haproxy/ssh_over_ssl.png
:width: 700px
:alt: Description de l'objectif à atteindre : Un frontend Public 443 redistribue les flux vers un backend SSH et un backend SSL, ce dernier renvoyant ensuite vers un nouveau frontend SSL. Ce nouveau frontend va se charger de déchiffrer le flux SSL, puis de rediriger le flux final vers le frontend HTTP habituel ou vers le serveur SSH demandé.
Deuxième étape : Séparer SSH et HTTP depuis le flux SSL
Modifications du frontend SSL
-----------------------------
La première modification va se faire sur le **frontend SSL**, qui va porter en plus du déchiffrement classique du flux, de nouveaux tests pour détecter une connexion SSH.
On va en gros faire le même traitement sur les en-têtes des paquets que dans notre première étape de `<frontend-tcp-ssl-ssh_>`_, mais cette fois sur le flux SSL déchiffré.
Comme ce ne sera plus votre frontend http standard qui déchiffrera le flux, on va le modifier de nouveau pour écouter sur le port 80 sans chiffrement (rien ne sort, tout reste en interne)
.. code-block:: bash
frontend http_in
# Local frontend
bind 127.0.0.1:80 accept-proxy
mode http
[...] # Vos acl et traitement http classiques
Et **on récupère le port 1443 du localhost** vers lequel notre backend TCP déjà existant renvoie le flux pour traiter notre flux SSL :
.. code-block:: bash
frontend ft_tcpssl
bind 127.0.0.1:1443 ssl crt /etc/haproxy/cert/ accept-proxy
mode tcp # On reste en TCP pour le moment
# On enrichit les logs avec les infos venant du TCP
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq dst:%[var(sess.dst)] http:%[var(sess.ishttp)] ssh:%[var(sess.isssh)] "
tcp-request content set-var(sess.dst) ssl_fc_sni
tcp-request content set-var(sess.ishttp) req.proto_http
tcp-request content set-var(sess.isssh) req.payload(0,7)
# Une fois le flux ssl déchiffré on peut verifier la payload pour du SSH
tcp-request inspect-delay 5s
acl trafic_ssh req.payload(0,7) -m beg "SSH-2.0"
tcp-request content accept if trafic_ssh # accept SSH
# Et enfin, on transmet vers les backends
use_backend bk_local_https if HTTP
use_backend bk_sshssl if trafic_ssh
On a déjà vu la plupart de ces options dans la première partie, mis à part le fait qu'on déchiffre le flux, rien de nouveau ici 😄
L'intelligence va se faire dans les backends ! Notamment celui du SSH
Backend SSH enrichit au SSL
---------------------------
Le premier backend est très simpliste, il va renvoyer vers votre frontend http classique, pour un traitement du flux HTTP sans plus de fioriture :
.. code-block:: bash
backend bk_local_https
mode http
http-request add-header X-Forwarded-Proto https
server httplocal 127.0.0.1:80 send-proxy
Là où on va prendre un peu plus de temps, c'est sur le backend SSH :
.. code-block:: bash
backend bk_sshssl
mode tcp
timeout server 2h
# Avec le SSL et ses headers SNI on peut choisir le serveur cible
## NEED haproxy > 2.0
tcp-request content set-dst var(sess.dst)
server ssh 0.0.0.0:22
Ici, on reste en TCP, mais la magie se passe avec la ligne ``set-dst``. Grâce à ça, en utilisant la variable ``sess.dst`` définie plus haut dans le frontend, on est capable de modifier à la volée la destination de notre flux SSH.
Cela va nous permettre de taper sur **n'importe quel serveur SSH**, rien qu'en modifiant le champs SNI de notre commande ``ssh`` ! C'est donc beaucoup plus souple que la redirection en dure vers un mono-serveur comme dans notre première partie.
C'est également **plus risqué**, puisque techniquement n'importe qui sachant que vous avez implémenté ça pourrait s'en servir pour rebondir vers n'importe quel serveur en SSH, comme si la connexion venait de votre propre connexion.
Notamment, on pourrait initier des attaques (DDOS, bruteforce, crawl, ...) en traversant haproxy et en se planquant derrière votre IP.
On va donc voir comment limiter ces exploits !
Sécuriser l'accès SSH
---------------------
J'ai mis en place plusieurs garde-fou :
* Frapper avant d'entrer : pour tromper les bots, on va faire en sorte qu'il faille initier 3 connexions à la suite avant de réellement se connecter
* Pas plus de 50 connexions simultanées autorisée
* Connexion uniquement à une liste de serveurs autorisés
On va devoir créer une sticky table dédiée à travers un backend dummy, car de base il n'existe qu'une seule ``stick-table`` par proxy (http://docs.haproxy.org/2.8/configuration.html#stick-table)
On va également enrichir notre backend ``bk_sshssl``
**Note** : À l'exception de l'acl utilisant le SNI, ces sécurités peuvent être ajoutée au backend ssh ``bk_ssh`` tout simple vu plus haut !
.. code-block:: bash
# Pour avoir plusieurs sticky-table, on utilise un dummy backend
backend dummy_st_sshssl_src
stick-table type ip size 1m expire 12h store conn_rate(30m)
backend bk_sshssl
mode tcp
timeout server 2h
# Serveurs autorisés
acl allowed_destination var(sess.dst) -m ip RESEAU/24 IP/32
tcp-request content reject if ! allowed_destination
# On frappe avant d'entrer !
tcp-request content track-sc0 src table dummy_st_sshssl_src
tcp-request content reject if { sc0_conn_rate(dummy_st_sshssl_src) le 3 }
# Pas plus de 50 requêtes simultanees
tcp-request content reject if { sc0_conn_rate(dummy_st_sshssl_src) gt 50 }
# Avec le SSL et ses headers SNI on peut choisir le serveur cible
## NEED haproxy > 2.0
tcp-request content set-dst var(sess.dst)
server ssh 0.0.0.0:22
Modifiez comme bon vous semble ``RESEAU/24`` ou ``IP/32`` pour indiquer les réseaux ou serveurs autorisés à être joint par ces connexion SSH. Il vous suffit de les séparer par des espaces.
Et voila, votre proxy SSH overs SSL est fin prêt à affronter les pare-feu que vous voudriez bien lui fournir !
Et comment qu'on s'y connecte ?
-------------------------------
Pour vous y connecter, il faudra indiquer à SSH d'encapsuler son flux dans du SSL :
.. code-block:: bash
ssh -o ProxyCommand="openssl s_client -quiet -connect IP_HAPROXY:443 -servername IP_A_SSH" -l USER dummy.name
Avec :
* ``IP_HAPROXY``: Le hostname ou l'adresse IP de votre proxy
* ``IP_A_SSH``: L'adresse IP que vous souhaitez réellement atteindre en ssh
* ``-l USER`` : L'utilisateur ssh à utiliser
* ``dummy.name``: Contrairement à une connexion ssh classique, ce nom ne sera jamais ni résolu ni utilisé pour joindre le serveur ssh. **Néanmoins** c'est sous ce nom que l'empreinte SSH du serveur sera enregistrée dans votre fichier known_hosts, donc je vous conseille de le changer pour un nom pertinent en rapport avec ``IP_A_SSH``
Au final
========
Et voila, votre proxy SSH over SSL est prêt à affronter le monde et ses pare-feux !
.. code-block:: bash
##############
### TCP IN ###
##############
frontend 443-in
bind YOUR_IP:443
mode tcp # On est en TCP ici et pas encore en http
# On verifie les types de trafics parmi tcp over ssl, http et SSH
tcp-request inspect-delay 5s # Une connexion ssh peut être longuette à s'établir, on prends le temps d'inspecter le flux
acl trafic_ssl req.ssl_ver gt 0
acl trafic_ssh_raw req.payload(0,7) -m str SSH-2.0
# Si SSL on envoie au backend TCP pour dechiffrement
use_backend bk_tcpssl if trafic_ssl
# Si ssh direct on envoie au backend ssh
use_backend bk_ssh if trafic_ssh_raw
# Pour avoir plusieurs sticky-table, on utilise un dummy backend
backend dummy_st_sshssl_src
stick-table type ip size 1m expire 12h store conn_rate(30m)
backend bk_tcpssl
mode tcp
timeout server 2h
server ft_tcpssl 127.0.0.1:1443 send-proxy
backend bk_ssh
mode tcp
timeout server 2h
# On frappe avant d'entrer !
tcp-request content track-sc0 src table dummy_st_ssh_src
tcp-request content reject if { sc0_conn_rate(dummy_st_ssh_src) le 3 }
# Pas plus de 50 requêtes simultanees
tcp-request content reject if { sc0_conn_rate(dummy_st_ssh_src) gt 50 }
server ssh SSH_IP_SERVER:22
####################
### TCP OVER SSL ###
####################
frontend ft_tcpssl
bind 127.0.0.1:1443 ssl crt /etc/haproxy/cert/ accept-proxy
mode tcp # On reste en TCP pour le moment
# On enrichit les logs avec les infos venant du TCP
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq dst:%[var(sess.dst)] http:%[var(sess.ishttp)] ssh:%[var(sess.isssh)] "
tcp-request content set-var(sess.dst) ssl_fc_sni
tcp-request content set-var(sess.ishttp) req.proto_http
tcp-request content set-var(sess.isssh) req.payload(0,7)
# Une fois le flux ssl déchiffré on peut verifier la payload pour du SSH
tcp-request inspect-delay 5s
acl trafic_ssh req.payload(0,7) -m beg "SSH-2.0"
tcp-request content accept if trafic_ssh # accept SSH
# Et enfin, on transmet vers les backends
use_backend bk_local_https if HTTP
use_backend bk_sshssl if trafic_ssh
backend bk_local_https
mode http
http-request add-header X-Forwarded-Proto https
server httplocal 127.0.0.1:80 send-proxy
backend bk_sshssl
mode tcp
timeout server 2h
# Serveurs autorisés
acl allowed_destination var(sess.dst) -m ip RESEAU/24 IP/32
tcp-request content reject if ! allowed_destination
# On frappe avant d'entrer !
tcp-request content track-sc0 src table dummy_st_sshssl_src
tcp-request content reject if { sc0_conn_rate(dummy_st_sshssl_src) le 3 }
# Pas plus de 50 requêtes simultanees
tcp-request content reject if { sc0_conn_rate(dummy_st_sshssl_src) gt 50 }
# Avec le SSL et ses headers SNI on peut choisir le serveur cible
## NEED haproxy > 2.0
tcp-request content set-dst var(sess.dst)
server ssh 0.0.0.0:22
####################
### HTTP & HTTPS ###
####################
frontend http_in
# Local frontend
bind 127.0.0.1:80 accept-proxy
mode http
[...] # Vos acl et traitement http classiques

+ 0
- 12
content/_drafts/fairphone-2-et-open-os.md View File

@ -1,12 +0,0 @@
---
Title: Fairphone 2 et Open OS
Subtitle: Déballage et retours après quelques semaines
date: 2017-11-04 15:45
Authors: Victor
Slug: fairphone-2-et-open-os
Category: Discussion
Tags: fairphone2, déballage, Open OS, Téléphone équitable, Téléphone Open Source
keywords: fairphone2, déballage, Open OS, Téléphone équitable, Téléphone Open Source
Status: draft
---
[TOC]

BIN
content/images/ssh-openssl-haproxy/ssh_over_ssl.png View File

Before After
Width: 768  |  Height: 231  |  Size: 30 KiB

BIN
content/images/ssh-openssl-haproxy/ssh_simple.png View File

Before After
Width: 501  |  Height: 171  |  Size: 17 KiB

Loading…
Cancel
Save