How can a rewrite from http to https could possibly work? - https

I know that it is possible to either redirect or rewrite http to https. Redirect is trivial. But how can a rewrite possibly change the protocol? At the time the proxy gets the request and performs the rewrite, the http connection has already been established and data was sent in un-encrypted, isn't it too late to switch protocol and does it make sens to only switch protocol on the server-side??

Related

What is the HTTP/1 equivalent of the HTTP/2 `:scheme` header?

I'm writing a proxy from HTTP/2 to HTTP/1 and vice-versa.
When I have an incoming HTTP/2 request, which defines :scheme, what header should I map that to for my proxied HTTP/1 request?
The closest thing I can find is https://www.rfc-editor.org/rfc/rfc7239#section-5.4
Mapping the HTTP/2 :scheme pseudo header to HTTP/1.1 X-Forwarded-Proto header would be correct.
You basically shouldn't map it.
For a start HTTP has no direct equivalent to the :scheme pseudo-header. The request was a relative path (e.g. /path/page/) rather than an absolute path (e.g. https://www.example.com/path/page/) and the Host header contained just the server name and not the scheme.
So the connection knows whether it is HTTP or HTTPS and this is exposed to webservers and the like (e.g. in the REQUEST_SCHEME variable for Apache) but at an HTTP level it doesn't know.
If acting as an intercepting proxy and taking one HTTP/2 connection, and forwarding requests to another, then you should open a HTTP or HTTPS connection for that second connection, as you see fit depending what the downstream system supports.
As sbordet points out if you want to make the downstream system aware of what the original scheme was then you can use X-Forwarded-Proto header (technically obseleted but still used) or the Forwarded header, but that's more for informational purposes rather than a direct mapping of what was in the original request. The scheme is related to the current request.
According to RFC 7540, section 8.1.2:
While HTTP/1.x used the message start-line (see [RFC7230],
Section 3.1) to convey the target URI, the method of the request, and
the status code for the response, HTTP/2 uses special pseudo-header
fields beginning with ':' character (ASCII 0x3a) for this purpose.
And:
The ":scheme" pseudo-header field includes the scheme portion of
the target URI ([RFC3986], Section 3.1).
":scheme" is not restricted to "http" and "https" schemed URIs. A
proxy or gateway can translate requests for non-HTTP schemes,
enabling the use of HTTP to interact with non-HTTP services.
So, if you're proxing HTTP, it should be "http" and if you're proxying HTTPS, it should be "https".
Reading again, I can see that I may have had the sense of the question the wrong way around (I was thinking HTTP1 client, HTTP2 server). But the above two quotes are still the relevant ones. You don't put :scheme in an HTTP1 header - it forms part of the URI that you place in the message start line.

ApiController.RedirectToRoute Using HTTPS

I have an API that returns a RedirectToRoute. I have noticed that it will want to fall back to HTTP instead of HTTPS.
Is it possible to make this work with HTTP or HTTPS depending on the original request?
Like if the link is http://example.com/api/myaction then myaction's result would use HTTP. Of course if it were https://example.com/api/myaction then the result would use HTTPS.

HTTPS and HTTP CORS

My questions is simple, but I cannot find an answer and I haven't got any resources to test it myself.
Can I make HTTPS CORS request from one domain to another HTTPS domain?
Can I make HTTP CORS request from one domain to another HTTPS domain?
I know that I can do HTTP CORS request from one domain to another HTTP domain, but I don't know if there is any difference when I use HTTPS.
Yes you can do a CORS request from a HTTPS domain to another HTTPS domain.
The only difference is because HTTPS is a secure origin, you can only make call to secure origin, so not to HTTP, the browser will block it with a message like:
Mixed Content: The page at 'https://example.com/index.html' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example2.com/endpoint'. This request has been blocked; the content must be served over HTTPS.
Warning: If you allow http requests to call your https webpage, it will be insecure because it means an attacker can force requests to your https webpage with the cookies of a victim and read the answer
Beware if you still need to support IE8/IE9 and are using XDomainRequest as it does not support cross-protocol requests. As per MDN:
The origin's security protocol must match that of the requested URL. (http to http, https to https). If these do not match, the request will error "Access is Denied".

Should I move from http to https?

From what I understand good practices are now to use more and more https.
I was wondering if I can redirect all my websites from http to https, or are there cases where https cannot be used?

Ensure WebSockets only connecting from known domain

How can I make sure only a script hosted on a specific list of domains is allowed to connect to my WebSocket application?
Or to prevent opinion based closevotes, is there a state-of-the-art or native way?
I do not intend to implement user authentication.
The mechanism for this with WebSocket is the origin header.
This HTTP header is set by browsers to the domain of the host that served the HTML that contained the JavaScript which opened the WebSocket connection.
A WebSocket server can inspect the origin header during the initial opening handshake of the WebSocket protocol. The server can then only allow proceeding of the connection if the origin matches a known whitelist.
The header cannot be modified from JavaScript, and all browsers are required by the RFC6455 specification to include it.
Caution: a non-browser WebSocket client can of course fake the origin header to any value it likes.
#oberstet gave you the right answer.
If you are worried about bots or programmatic HTTP agents, then you are going to have a bad time. Everything in a HTTP request can be spoofed. Your only option is to use cookies to attach a token with limited time validity that certify the user went through an allowed website to get that script. Get that cookie in the WebSocket handshake and decide if you allow it or not.
E.g.: When a user visit your site, or one of your sites, return a cookie with a symmetrically encrypted token based on the user IP address, User-Agent header, and Origin header; when the user initiates a WebSocket connection, if it is in the same 2nd domain, it will send the cookie, then if the data adds up allow the connection, otherwise, reject it. If the WS is in another domain, then you will have to forget about cookies and rely on a web socket message once the connection is established to check the validity of the connection.

Resources