Safari failing to load images - 421 Misdirected Request [duplicate] - html

Error:
The client needs a new connection for this request as the requested host name does not match the Server Name Indication (SNI) in use for this connection.
I recently purchased a EV SSL certificate from Comodo, installed it on my VPS (cPanel/WHM) and everything worked great. I then upgraded to http2 and am now receiving the error when switching between each website on the certificate. The 3 websites share the same IP address. From what I can tell, this may be the issue. I do not want to reissue a SSL cert for each domain as I paid for the EV multi domain cert. Is the answer to purchase 2 additional IPs and make sure each domain has its own IP? Or is there a way I can edit the virtual hosts so that I can maintain the same setup I have now?
I should mention, this is only happening on Safari, not chrome.
SSL Labs Report
https://www.ssllabs.com/ssltest/analyze.html?d=www.deschutesdesigngroup.com&s=142.4.0.142&hideResults=on
EasyApache HTTP vhost configuration
https://pastebin.com/dNeFRGWJ
EasyApache HTTPS vhost configuration
https://pastebin.com/vgWAD5mg

You have enabled HTTP/2 on only two of the three sites.
HTTP/2 will try to reuse the connection for multiple domains if both the IP address matches and the certificate covers all the necessary domains. This is the case here and so HTTP/2 is reused.
However if you run SSLLabs on all three domains you see a slight difference in the protocol used for Chrome (for example):
Chrome 70 / Win 10 RSA 2048 (SHA256) TLS 1.2 > h2
Chrome 70 / Win 10 RSA 2048 (SHA256) TLS 1.2 > http/1.1
Chrome 70 / Win 10 RSA 2048 (SHA256) TLS 1.2 > h2
And similarly further down in the ALPN setting:
ALPN Yes h2 http/1.1
ALPN Yes http/1.1
ALPN Yes h2 http/1.1
So going to the middle domain first will work as it will connect via HTTP/1.1 and so not reuse the connection. However going to the middle domain after initiating a request to either the first or last domain will attempt to reuse the HTTP/2 connection and fail as the middle domain doesn't support HTTP/2.
Web servers should return a 421 Misdirected Request status code for any requests when the browser attempts to reuse the connection when it shouldn't, to say "Yeah you really shouldn't be attempting to reuse the connection here! Can you try again on another connection please?". The same thing happens if there are different SSL/TLS setup (e.g. the cipher suite used for the connection is not accepted on the other domain).
Chrome and Firefox correctly handle the 421 response and transparently resend the requests over a new connection, which in this case then uses HTTP/1.1 (check out developer tools in the browser and you'll see this is true). Other browsers, including Safari used by iOS, have not implemented support of the relatively new 421 status code yet and so fail with an error like below:
Misdirected Request
The client needs a new connection for this request as the requested
host name does not match the Server Name Indication (SNI) in use for
this connection.
I presume there is no reason not to enable HTTP/2 on all domains and this was a misconfiguration error? If so enable HTTP/2 in all domains and your issue should be sorted.
If you do not want HTTP/2 on all domains, then you ensure the browser doesn't think it can reuse the connection. That means either using a separate IP address for that domain, or getting the certificate reissued for only two domains, and a separate certificate for the other than shouldn't share connections.

Related

How Chrome browser know which client certificate to prompt for a site?

I'm setting up certificate authentication for my project using Tomcat. It works ok for command line client such as cURL.
I have many client certificates installed in Chrome browser. Some are using to connect to my site, others are used for different purposes and not relate to my project.
Every time I connect to my site, Chrome presents a list of client certificates for choosing. These are exactly the certificates that I installed and not others. My questions are:
How Chrome knows which client certificates are for a site to present for choosing?
Tomcat stores those client certificates in its trust store. During
SSL hanshake, Tomcat will request for client certificate. Does it
request for some specific certificates that it knows in its trusted
store so that Chrome knows what to show?
The client certificate authentication is ruled in the handshake phase of the SSL/TLS protocol implemented by browsers.
If the server requires a client certificate authentication (it is
optional), send a message to client with the list of the accepted
certificate authorities (CA). Can be void if server accepts any
certificate.
The client select the certificates installed in client keystore which have been issued by any of these CA's, and present the list to user. In case of Chrome, the browser selects the certificates installed by user from the operating system's Key Store.
User choose a certificate, and the client performs a signature with the private key of the certificate over a known data interchanged during handshake.
Only certificates with private key can be selected during step 2. This is the reason by with the browser does not select the certificates of trusted CA's installed in your device. You do not own the private key

Chrome WebRTC over TCP

I'm trying to have WebRTC media over TCP with a gateway in between but I'm having some interesting issues on the ICE connection phase. Before further advances, it's important to know that I have the same setup for UDP and everything works correctly.
In the gateway we modify the remote answer SDP to include a single TCP candidate (the media port is also modified to include the same port):
a=candidate:1 1 tcp 1 <gw_ip> <gw_port> typ host tcptype passive generation 0
Also I'm sending the attribute setup as passive:
a=setup:passive
Seconds after applying the remote description on Chrome, I'm receiving a STUN BIND request on the gateway which I'm answering with a Bind Success response (I've checked both Transaction ID and Message Integrity and they seem fine).
After this chrome simple doesn't continue the ICE checking (neither DTLS messages). I've enabled chrome logs to see if some error was happening and I've found an interesting output:
"Ignoring STUN binding response message on shared socket"
I've taken a look at chromium source code and it seems this is being shown because chrome is using a shared socket but I cannot understand it's reason.
Any ideas? Thanks!
After a deep investigation I've found out that the TCP stream wasn't being parsed correctly on the gateway side.
This stream in specific, uses a length framing mechanism that wasn't being applied on the inbound/outbound data, therefore provoking several issues on the process pipeline.
Refer to rfc5389 for more information regarding the framing mechanism:
https://www.rfc-editor.org/rfc/rfc5389

HTTPS connections duplicated

Additional, unexpected HTTPS connections are being made to GCE servers.
This started 2nd October and is affecting europe-west1-b and us-central1-b.
We have the same codebase running on servers in Amazon EC2 that are not affected.
Is anyone else seeing issues with HTTPS traffic to GCE?
UPDATE: Clarification of duplicated connections:
A single HTTPS request from a web browser for example
GET /favicon.ico HTTP/1.1
Results in 5 HTTPS connections opened, no http request is send and then they are closed (before timeout period).
Then a final connection is opened and the request is sent as it should.
Note:
This usually would go undetected. However we only allow 10 SSL connections from a single IP in the space of 1 second (velocity restriction).
I have temporarily increased this to 20 and everything is working OK.
What I don't understand is why this would suddenly start happening and only on GCE servers.
I will update this again when I have looked into the raw SSL traffic.

Orion and Rush - HTTPS notifications over port 443

I have been trying to set up an Orion instance which would support subscription notifications to HTTPS (using Rush), but the handling of this seems to be a bit incorrect. Setting the notification url to e.g. https://www.example.com/path/ ends up at Rush as www.example.com:443/path/.
This is unsafe and not up to standards, as such a request could actually avoid https by using the same port over http. In our company we have a proxy set up which refuses such requests as "Bad Request: You're speaking plain HTTP to an SSL-enabled server port". The same error comes up in the Rush consumer output, while direct curl requests to Rush without the port work ok. See this discussion for another argument that the current requests are incorrect: https://security.stackexchange.com/questions/46015/speaking-plain-http-over-an-ssl-enabled-server-port. Google refuses such requests as well.
Our proxy is set up to redirect any http requests to https, but these do not work either, as Rush does not seem to follow the redirects.
How can we avoid this issue? Modifying our proxy would be unsafe and not following standards, changing Orion would require recompiling from sources and changing Rush to remove the port would be a bit hacky. Any changes (like adding the port or removing/changing the protocol) to the notification URL do not help.
EDIT: The command to run Orion was:
/usr/bin/contextBroker -port 1026 -logDir /var/log/contextBroker -pidpath /var/log/contextBroker/contextBroker.pid -dbhost localhost -db orion -rush localhost:5001
Rush (v 1.8.3) was installed with default values and Orion was updated from v0.14.1 to v0.23.0.
Since verion 1.7.0, Orion implements native HTTPS notifications (i.e. without needing Rush). This could help to solve the situation described in this question.

WebSocket won't connect to anything other than 127.0.0.1 / localhost

I have a testapp consisting of an HTML5/WebSocket client and an HTTP/WS server. Both servers are in C#; the HTTP server is my own simple thing and the WS server is also homebrew based on concepts from http://nugget.codeplex.com/. HTTP server is listening on 0.0.0.0:5959 and WS server on 0.0.0.0:5960 (accept connections from any client, but on different ports).
My index.html includes some JavaScript that opens a WebSocket to 'ws://'+document.location.hostname+':5960/' (that is, to the same IP address that the webpage came from, but on port 5960). The WS server sends sample data every 100ms. All in all, it's a pretty straightforward demo.
I'm using Chrome 12.0 on Windows7.
I've found that the HTTP server works from any client, either a browser on my machine pointed to 127.0.0.1:5959 or localhost:5959, AND it works when any machine (mine or a remote machine... "remote" being a different PC on my desk :) hits my server machine's work-internal 10-net address 10.122.0.159:5959. Everything works as expected in HTTP land.
However, the WebSocket only works on 127.0.0.1 and localhost; remote machines can successfully fetch HTML from 10.122.0.159:5959 but the WebSocket will NOT connect to 10.122.0.159:5960. In fact, when I point my local browser to it's own 10-net address (10.122.0.159:5959) I get the same result - HTML loads but WebSocket does not connect.
Any ideas as to why this might be happening?
Does CORS require that the WS be using the same port as the HTTP request originated from? If so, is there a special exception to the rule for 127.0.0.1?
Many thanks,
-Dave
Update
It seems to be caused by a proxy server blocking ws:// requests. Our company employs a proxy server for content filtering and all the usual stuff, and our browsers are configured to use it.Chrome uses IE's proxy settings, and IE's default settings are for localhost to not use a proxy server. When I check the box to have local connections also use the proxy server, my ws:// requests to localhost get blocked. Conversely, when I uncheck the "use proxy server" box my server does rx the WS request. Similarly with the remote machine, if I turn off the proxy on the remote machine my server does rx the ws:// request.
So it's a proxy thing, not a CORS or socket thing, and now I'm off to explore proxy settings with our IT folks.
There is no WebSocket limitation on cross-origin except what is governed by the CORS security in the handshake.
It sounds like something is wrong with your WebSocket server and it is only listening on localhost for connections. I would add some debug output to the OnClientConnect routine in Nugget (WebSocketServer.cs) so you can see when socket connections happen. If you really think it isn't a problem with the server then I would suggest using wireshark and comparing the localhost connection to the remote connection.
Also, if you are using the SilverLight WebSocket prototype (README) in IE 9, then you are restricted to ports 4502-4534 for WebSocket connections. It's possible that for localhost this restriction is lifted.
It is/was indeed a proxy thing.
Rather than asking our IT folks to make changes (good luck with that, eh?) I simply turned off proxy for 10.122.0.159 ([Howto for IE/Chrome][1]). I briefly experimented with turning it off for the ws:// protocol but couldn't get it to work, so for now just opening that one IP address does the trick.