ssh3 icon indicating copy to clipboard operation
ssh3 copied to clipboard

Remove unnecessary HTTP layer

Open SeanBurford opened this issue 1 year ago • 3 comments

The server currently uses an HTTP handler that expects a CONNECT method with a protocol of SSH3. ie. instead of GET / HTTP/1.0 it expects CONNECT / SSH3.

Current stack:

+------------------------------+
|          TLS / QUIC          |
+------------------------------+
|          HTTP Server         |
+-CONNECT SSH3-+-Other methods-|
| Shell Server | HTTP Server   |
+--------------+---------------+

That's easy to implement as a proof of concept, but the HTTP layer is unnecessary and makes it harder to multiplex a server (eg. as a web server and a shell server).

I propose that you could simplify the server and protocol by removing the HTTP layer. To do this, you would use these features of TLS:

  • NextProto: Negotiate the application protocol (eg. shell-over-quic) during the TLS handshake (https://www.rfc-editor.org/rfc/rfc7301.html#section-3.1). This is supported in Golang via NextProtos in tls.Config: https://pkg.go.dev/crypto/tls#Config
  • ServerName: Accept the server name during the TLS handshake (https://pkg.go.dev/crypto/tls#ConnectionState). This enables support for virtual hosts (https://github.com/francoismichel/ssh3/issues/43) and using the server as a proxy jump host.
  • MTLS: Authenticate using client certificates, removing the complex code for parsing Authorization headers, JWTs etc. If you want complicated auth mechanisms (such as PAM support), you could negotiate those inside the shell-over-quic protocol.

Proposed stack:

+-------------------------------+
|             TLS / QUIC        |
+-NextProto SHH--+-NextProto H2-+
| Shell Server   | HTTP Server  |
+----------------+--------------+

This way the application protocol (Shell, HTTP, others) is made at the TLS termination point rather than at the web server layer, enabling easier integration with existing services.

If you've considered this already you may want to mention the trade offs in the docs.

SeanBurford avatar Jan 23 '24 22:01 SeanBurford

HTTP is what brings all the interesting things to this protocol.

There are several reasons why removing HTTP degrades the design:

  • Routing based on hostnames pushes information into the SNI, which is sent in cleartext
  • Routing based on ALPN uses information sent in cleartext
  • No free seemless support across TLS and QUIC. HTTP is an abstraction layer that handles describing how common semantics can map to specific versions and describes the standard transforms.
  • No free multiplexing. A specification would be required to invent multiplexing on top of TLS, or to describe precisely how QUIC streams are used, if it was later determined it would be required.
  • No free metadata. A specification would be required to invent additional forms of metadata if it was later determined it would be required.

As feature creep happens, before we know it any SSH-over-QUIC design might start to look quite close to HTTP. The danger is it takes ages to get there before we realise.

LPardue avatar Jan 24 '24 11:01 LPardue

+1 to @LPardue. We get quite a few benefits from HTTP/3 here. In terms of integration with existing software, the difficulty should be the same, the h3 stack can easily send the contents of the CONNECT stream (+ datagrams) to another piece of software over loopback - just like the TLS terminator would.

DavidSchinazi avatar Jan 26 '24 18:01 DavidSchinazi

I have no concerns with using HTTP for client-to-server - but CONNECT in particular is not well supported by existing infra ( proxies ), it should at least support POST as an option. Using SSH over HTTP/2 is pretty common ( with the double encryption, which allows end-to-end security ).

Adoption is very unlikely to happen if it requires major changes to http reverse proxies ( load balancers, etc) - if you have to run a custom server you can better run real ssh.

costinm avatar Feb 29 '24 16:02 costinm