Context
I have a personal server that I use for the web. I sometimes need to SSH/SFTP to it.
Disclamer: I have very little experience with nginx
internals.
Problem
This morning, I figured out that the free wifi in a well-know cafe chain was blocking SSH (actually, they are blocking anything that's not on 80/443). But when I need SSH, I need it, so I looked for ways to share SSH and HTTPS on the same port.
What I looked at
I have looked at a few possible solutions that can run on port 443:
SSHL
: a SSH/OpenVPN/HTTPS multiplexer;OpenVPN
: a VPN solution has a built-in multiplexer for OpenVPN and HTTPS;HAProxy
: a webserver/load balancer can also multiplex everything.
All of these seem pretty straight-forward but I don't really like the fact of adding layers and complexity and possibly slowing things down just in the unlikely event that I need to SSH on 443.
Putting nginx into the mix
I know that nginx
already supports raw TCP streams handling. So I was wondering if I could use that on port 443 too directly in nginx
. The idea being that nginx
could choose to use the http
module if it recognizes HTTP(S) or stream
for everything else.
Questions
In that context, I have two questions:
- Is
nginx
even capable of doing such a distinction? (I am not even sure I would be able to listen on port 443 in both thehttp
and thestream
block at the same time.) - If so, would there be any blatant performance issue with that setup? (I am thinking about transfer speed with SFTP for instance, not really SSH per se.)
stream
does not sound like a feature capable of doing any protocol detection. Regardless of what you use on the server side, you will need to either encapsulate the SSH traffic inside another protocol or use an SSH client which is recent enough to be capable of speaking before the server. Relying on the server to detect the protocol of a client which hasn't spoken yet would be fragile.nginx
support seems quite small indeed and it seems that it is only relying on the port number to "route" the traffic. From what I've understood, thehttp
bloc is merely a way to load the right module for the right corresponding server listening to a given port. That module, in turn, will do all theSNI
magic. But I am no expert and I just wanted to make sure I understood that correctly.SNI
is occurring at the TLS level: if there is noSNI
,nginx
may default to stream instead.