web-dev-qa-db-fra.com

Nginx peut-il servir SSH et HTTP (S) simultanément sur le même port?

Le contexte

J'ai un serveur personnel que j'utilise pour le Web. J'ai parfois besoin de SSH/SFTP pour cela.

Disclamer: J'ai très peu d'expérience avec les internes nginx.

Problème

Ce matin, j'ai compris que le wifi gratuit dans une chaîne de cafés réputée bloquait SSH (en fait, ils bloquent tout ce qui n'est pas sur 80/443). Mais lorsque j'ai besoin de SSH, j'en ai besoin, alors j'ai cherché des moyens de partager SSH et HTTPS sur le même port.

Ce que j'ai regardé

J'ai examiné quelques solutions possibles pouvant s'exécuter sur le port 443:

  • SSHL: un multiplexeur SSH/OpenVPN/HTTPS;
  • OpenVPN: une solution VPN comporte un multiplexeur intégré pour OpenVPN et HTTPS;
  • HAProxy : un serveur Web/équilibreur de charge peut également tout multiplexer.

Tout cela semble assez simple mais je n'aime pas vraiment le fait d'ajouter des couches et de la complexité et éventuellement ralentir les choses juste dans le cas peu probable où je devrais SSH sur 443.

Mettre nginx dans le mélange

Je sais que nginx prend déjà en charge le traitement des flux bruts TCP. Je me demandais donc si je pouvais utiliser cela sur le port 443 trop directement dans nginx. L'idée étant que nginx pourrait choisir d'utiliser le module http s'il reconnaît HTTP (S) ou stream pour tout le reste.

Des questions

Dans ce contexte, j'ai deux questions:

  • nginx est-il même capable de faire une telle distinction? (Je ne suis même pas sûr de pouvoir écouter le port 443 dans les blocs http et stream en même temps.)
  • Si oui, y aurait-il un problème de performance flagrant avec cette configuration? (Je pense par exemple à la vitesse de transfert avec SFTP, mais pas vraiment à SSH.)
9
JohnW

Depuis la version 1.15.2 de nginx, nouvelle variable $ssl_preread_protocol ajoutée. Et dans le blog officiel, nous avons ajouté un article sur l'utilisation de cette variable pour multiplexer HTTPS et SSH sur le même port https://www.nginx.com/blog/running-non-ssl-protocols- over-ssl-port-nginx-1-15-2/

Exemple de configuration de SSH (par défaut) et HTTPS:

stream {
    upstream ssh {
        server 192.0.2.1:22;
    }

    upstream web {
        server 192.0.2.2:443;
    }

    map $ssl_preread_protocol $upstream {
        default ssh;
        "TLSv1.2" web;
    }

    # SSH and SSL on the same port
    server {
        listen 443;

        proxy_pass $upstream;
        ssl_preread on;
    }
}
8
sattellite

J'ai un tunnel de configuration de travail ssh sur tls sur le port 443, en utilisant le module de flux nginx. Je fais aussi XMPP sur TLS et HTTP normal sur le même port. Je fais le multiplexage via ALPN.

(Vous devez utiliser nginx> 1.13.10 pour utiliser le module ssl_preread avec alpn http://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html#ssl_preread )

Ma configuration utilise la version fixe de nginx, mais elle devrait également fonctionner sans menu fixe.

stream {
    # check ALPN for xmpp client or server and redirect to local ssl termination endpoints
    map $ssl_preread_alpn_protocols $ssl_multiplexer {
        "xmpp-client"     127.0.0.1:5422;
        "xmpp-server"     127.0.0.1:5469;
        "identifyssh"     127.0.0.1:8822;
        default           127.0.0.1:8443;
    }

    server {
        listen 443;
        ssl_preread on;
        proxy_pass $ssl_multiplexer;
        proxy_protocol on;
        set_real_ip_from  172.18.0.0/32;
    }

    # ssl termination for c2s connections
    server {
        listen 5422 ssl proxy_protocol;
        # ... <- tls keys and options here
        proxy_ssl off;
        proxy_pass ejabberd:5222;
    }

    # ssl termination for s2s connections
    server {
        listen 5469 ssl proxy_protocol;
        # ... <- tls keys and options here
        proxy_ssl off;
        proxy_pass ejabberd:5269;
    }

    # ssl termination for ssh connections
    server {
        listen 8822 ssl proxy_protocol;
        # ... <- tls keys and options here
        proxy_ssl off;
        proxy_pass yourserver:22;
    }
}

Si vous souhaitez utiliser le contenu XMPP, vous devez ajouter des enregistrements SRV pour pointer vers le port 443 de vos serveurs, voir https://xmpp.org/extensions/xep-0368.html

Si vous souhaitez vous connecter à votre serveur ssh, vous devez envelopper votre session ssh dans une session ssl qui envoie la chaîne ALPN que vous avez définie dans votre configuration de flux. J'ai utilisé "identifyssh" dans l'exemple ci-dessus. Vous pouvez utiliser n'importe quoi, mais essayez de ne pas vous heurter aux noms définis officiellement: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml # alpn-protocole-ids

Pour démarrer la session ssh à partir de votre client sur votre utilisation de serveur préparé:

ssh you@yourserver -o "ProxyCommand openssl s_client -alpn identifyssh -ign_eof -connect yourserver:443"

Et vous devriez être connecté.

Je dois également noter que j’utilise le proxy_protocol pour conserver les en-têtes et l’adresse IP des clients tout en les transmettant à mes serveurs.

Votre serveur http normal configuré dans la section http {} devrait s’occuper de ceci:

server {
  listen 8443 ssl proxy_protocol;
  # ...
}

La meilleure chose à faire est que vous n’avez pas besoin d’outils comme sslh, stunnel, proxytunnel ou autres pour que cela fonctionne. Vous n'avez besoin que des nouveaux nginx et openssl. J'espère que ça aide quelqu'un. Cela m'a aidé à creuser dans ce genre de choses.

4
tux

Ou, vous pouvez utiliser proxyshunnel ssh via votre nginx avec une connexion HTTP/S

Regardez: proxytunnel

4
mtsdev

Cette question est légèrement liée à une autre à laquelle j'ai déjà répondu:

https://stackoverflow.com/questions/34741571/nginx-tcp-forwarding-based-on-hostname/34958192#34958192

Oui, il est techniquement possible de différencier les trafics ssh et https et d’acheminer la connexion de manière appropriée; Cependant, à ma connaissance, nginx ne dispose actuellement pas d'un tel support.

Cependant, vous pouvez simplement exécuter sshd directement sur le port https en plus de celui ssh ( /usr/sbin/sshd -p 22 -p 443 ) et/ou utiliser le pare-feu et/ou le port frappant afin de différencier où les connexions au port 443 sont routées.

2
cnst

Vous pouvez configurer une règle iptables pour transférer les connexions de votre café bien connu sur le port 443 vers le port 22. Vous pouvez également faire rebondir le trafic d’un relais de port ailleurs sur Internet, en changeant le numéro de pirt.

Essayer de résoudre le problème avec nginx ne fonctionnera pas.

2
symcbean

Depuis la version 1.9.0 de Nginx, NGINX prend en charge le module ngx_stream_core_module. Il devrait être activé avec le flux --with-stream. Lorsque le module de flux est activé, il est possible d’utiliser le proxy TCP du protocole SSH.

stream {
upstream ssh {
    server 192.168.1.12:22;
}
    server {
    listen        12345;
    proxy_pass    ssh;

} }

https://www.nginx.com/resources/admin-guide/tcp-load-balancing/

1
Hendi Fauzi

Autant que je sache, nginx ne le prend actuellement pas en charge.

Dans SSH-2 , le client enverra un message d'accueil au serveur:

Lorsque la connexion a été établie, les deux côtés DOIVENT envoyer une chaîne d'identification. Cette chaîne d'identification DOIT être

 SSH-protoversion-softwareversion SP comments CR LF

Dans TLS 1.2 , les clients doivent d'abord envoyer:

  Client                                                Server

  ClientHello                   -------->
                                                   ServerHello
                                            [ChangeCipherSpec]
                                <--------             Finished
  [ChangeCipherSpec]
  Finished                      -------->
  Application Data              <------->     Application Data

Les clients peuvent utiliser ces informations pour la mise en œuvre.

1
Gea-Suan Lin

Peut-être que vous pouvez utiliser nginScript pour implémenter votre propre multiplexeur? Voir ici pour une introduction: https://www.nginx.com/blog/introduction-nginscript/

0
Thraidh

Il existe un correctif non maintenu permettant à nginx de prendre en charge le multiplexage de protocole pour SSH et HTTPS: https://github.com/shawnl/nginx-ssh

Cependant, il n'est plus maintenu, le projet non-nginx qui prend en charge ce que vous recherchez est: https://github.com/yrutschle/sslh

Je vous suggère d'utiliser SSLH en face de vos serveurs nginx et ssh.

0
kensai