Search code examples
httpsslwebsockethttp2

Should Upgrade: TLS followed by Upgrade: h2c/websocket on port 80 still be secure?


https://en.m.wikipedia.org/wiki/HTTP/1.1_Upgrade_header

Given the following:

  • Connect on port 80
  • Request Upgrade: TLS/1.x
  • Request Upgrade: h2c or Upgrade: websocket

Will the resulting connection/protocol still be using TLS or will it be replaced by an unsecure one?

Note: I'm not primarily looking for the current status of popular clients/servers, but rather any hints in the specification(s) which may lead to a more desirable implementation.


Solution

  • I'm not sure if your request makes sense and, even if it did, if any implementation would support it - or if you could rely on what support that might be.

    Connect on port 80
    Request Upgrade: TLS/1.x
    

    Ok this bits fine. It would basically ask to speak TLS over port 80 and over http and is defined by RFC-2817. It's highly unusual as standard would be to speak TLS only over https scheme and on port 443 (or a non-standard port like 8443), but in theory this would work. Note also the Connection header must also be set to Upgrade.

    Connect on port 80
    Request Upgrade: TLS/1.x
    Request Upgrade: h2c
    

    This is where it starts to get tricky. The h2c protocol is an unsecured HTTP/2 connection (i.e. without TLS) but, combined with your first header, you are asking this to be over TLS (multiple headers are permitted over HTTP btw). I guess, in theory, this could work, similar to how it would work under HTTP/1.1 above, except that the HTTP/2 spec clearly states:

    the "h2c" protocol identifier describes a protocol that does not use TLS.

    and

    implementations that support HTTP/2 over TLS MUST use protocol negotiation in TLS [TLS-ALPN].

    I would therefore consider above connection a violation of spec and not confirm that upgrade.

    Connect on port 80
    Request Upgrade: TLS/1.x
    Request Upgrade: websocket
    

    The websocket spec is less clear on this. It does state:

    By default, the WebSocket Protocol uses port 80 for regular WebSocket connections and port 443 for WebSocket connections tunneled over Transport Layer Security (TLS) [RFC2818].

    and also:

    A |wss| URI identifies a WebSocket server and resource name and indicates that traffic over that connection is to be protected via TLS (including standard benefits of TLS such as data confidentiality and integrity and endpoint authentication).

    However there is nothing that I can see that forbids a TLS connection over the |ws| URI, or even using the |wss| URI over port 80. However I would imagine that, since this is not explicitly defined, there would be no guarantees as to whether this would work, or if the connection would be secure or not.