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
.
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.
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.
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.
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.)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;
}
}
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.
Ou, vous pouvez utiliser proxyshunnel ssh via votre nginx avec une connexion HTTP/S
Regardez: proxytunnel
Cette question est légèrement liée à une autre à laquelle j'ai déjà répondu:
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.
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.
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/
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.
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/
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.