Websocket and Safari 6.0 - safari

I am using Safari 6 and websockets. My server is receiving the following handshake from the browser:
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: nomad.local:1299
Origin: file://
Sec-WebSocket-Key: WhZTuybN4i2ZshDBxco42w==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
There is no Protocol included. My server can deal with that, but when it tries to complete the handshake with the browser client I get the following message:
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
Is there an implied Protocol in the message sent to server that I need to return in the handshake to the client?
This worked before I upgraded to latest Safari

If the client does not send any sub-protocols in the handshake (Sec-WebSocket-Protocol) then the server must not send back a sub-protocol header (Sec-WebSocket-Protocol). If the server sends back the common default of "Sec-WebSocket-Protocol: chat" even though the client did not include a sub-protocol header, the client must refuse the connection. Some browsers were sloppy about this and have recently begun to tighten up their compliance.
If the client does send a sub-protocol list, then the server must select a single sub-protocol that it supports and send this back to the client as the chosen sub-protocol.

Well the protocol is WebSockets ;-) See the RFC for further explanations on Sec-WebSocket-Protocol: http://datatracker.ietf.org/doc/rfc6455/?include_text=1
The handshake from the client looks as follows:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
The handshake from the server looks as follows:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Don't know wether the Safari 6 implemenation differs, but protocols from RFC are usually a nightmare... There might be a standard implied?

Related

start-iap-tunnel unable to connect to a listening port

I'm installing OpenVPN Access Server on a Google Cloud instance. Its webUI listens on port 943 using https. It has a self-signed certificate whose name doesn't match the server's hostname (10.150.0.2). I can't start an SSH tunnel. I'm looking for a way to troubleshoot the connection from the IAP service to my server.
The command I'm running is gcloud compute start-iap-tunnel vpn 943 --local-host-port=localhost:943 I receive the normal Testing if tunnel connection works message.
It errs out with ERROR: (gcloud.compute.start-iap-tunnel) While checking if a connection can be made: Error while connecting [4003: 'failed to connect to backend']. (Failed to connect to port 943)
If I add --log-http to the command invocation the relevant information follows (it looks like a normal req/resp cycle with a 200 that I assume is from my client to the IAP service):
Testing if tunnel connection works.
=======================
==== request start ====
uri: https://oauth2.googleapis.com/token
method: POST
== headers start ==
b'content-type': b'application/x-www-form-urlencoded'
b'user-agent': b'google-cloud-sdk gcloud/367.0.0 command/gcloud.compute.start-iap-tunnel invocation-id/db27de82264f47fcb63f6680afaa8327 environment/None environment-version/None interactive/False from-script/False python/3.7.9 term/xterm-256color (Macintosh; Intel Mac OS X 21.2.0)'
== headers end ==
== body start ==
Body redacted: Contains oauth token. Set log_http_redact_token property to false to print the body of this request.
== body end ==
==== request end ====
---- response start ----
status: 200
-- headers start --
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Fri, 24 Dec 2021 02:11:52 GMT
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Pragma: no-cache
Server: scaffolding on HTTPServer2
Transfer-Encoding: chunked
Vary: Origin, X-Origin, Referer
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
-- headers end --
-- body start --
Body redacted: Contains oauth token. Set log_http_redact_token property to false to print the body of this response.
-- body end --
total round trip time (request+response): 0.246 secs
---- response end ----
----------------------
ERROR: (gcloud.compute.start-iap-tunnel) While checking if a connection can be made: Error while connecting [4003: 'failed to connect to backend']. (Failed to connect to port 943)
To my knowledge this is the limit of easily accessible troubleshooting for start-tap-tunnel.
Moving on to the local machine we can connect to 10.150.0.2:943 before puking a la certificate.
root#viongier:/usr/local/openvpn_as# wget https://10.150.0.2:943
--2021-12-24 02:01:47-- https://10.150.0.2:943/
Connecting to 10.150.0.2:943... connected.
ERROR: The certificate of ‘10.150.0.2’ is not trusted.
ERROR: The certificate of ‘10.150.0.2’ doesn't have a known issuer.
The certificate's owner does not match hostname ‘10.150.0.2’
It seems to me that my client happily connects to the IAP service which fails to connect to my server. I would expect to see an IAP error if it was erring out because of the cert. The only thing I can think of to test this is by generating a certificate whose issuer google likes. (LetsEncrypt for example.)
This message means that the backend does not have a socket open in the listening state. Common reasons are that no service has been started or a firewall is blocking the port.
To allow the Identity Aware Proxy into your VPC, allow traffic from 35.235.240.0/20.
ERROR: (gcloud.compute.start-iap-tunnel) While checking if a
connection can be made: Error while connecting [4003: 'failed to
connect to backend']. (Failed to connect to port 943)
This error means that the certificate provided does not match the address that the connection is made to:
ERROR: The certificate of ‘10.150.0.2’ is not trusted. ERROR: The
certificate of ‘10.150.0.2’ doesn't have a known issuer. The
certificate's owner does not match hostname ‘10.150.0.2’
Some clients, such as wget support ignoring SSL certificate validation. For wget see the --no-check-certificate flag.
Once you solve that problem you will run into another set of problems:
Under normal circumstances, you can not use HTTPS with tunnels. Tunnels are a form of man in the middle. There are tricks that can be employed, none of them secure.
Commercial SSL certificates do not support IP addresses only public domain names. You would need to create your own self-signed certificate, which would not be trusted or do not validate the certificate.
The last issue is that HTTPS endpoints require encryption negotiation from the client party. The start-iap-tunnel command does not initiate encryption (TLS negotiation). This command also does not do any form of certificate exchange and that is why you do not see an IAP error about certificates. This command only transfers data between the tunnel endpoints.
In summary, you cannot use HTTPS with TCP / SSH tunnels without deploying tricks and/or disabling features which defeats the purpose of HTTPS.
Allow IAP traffic through the firewall allowed my external client to connect to the internal port 943 via an IAP tunnel.
Allowing port 943 from 35.235.240.0/20 solved my problem.
More information is available at the GCP IAP docs

Cloudflare returning 520 due to empty server response from Heroku

My Rails app which has been working great for years suddenly started returning Cloudflare 520 errors. Specifically, api.exampleapp.com backend calls return the 520 whereas hits to the frontend www.exampleapp.com subdomain are working just fine.
The hard part about this is nothing has changed in either my configuration, or code at all. Cloudflare believes this is happening as the Heroku server is returning an empty response.
> GET / HTTP/1.1
> Host: api.exampleapp.com
> Accept: */*
> Accept-Encoding: deflate, gzip
>
{ [5 bytes data]
* TLSv1.2 (IN), TLS alert, close notify (256):
{ [2 bytes data]
* Empty reply from server
* Connection #0 to host ORIGIN_IP left intact
curl: (52) Empty reply from server
error: exit status 52
On the Heroku end, my logs don't even seem to register the request when I hit any of these urls. I also double-checked my SSL setup (Origin certificate created at Cloudflare installed on Heroku), just in case, and it seems to be correct and is not expired.
The app is down for a couple of days now, users are complaining, and no response from either customer care teams despite being a paid customer. My dev ops knowledge is fairly limited.
Welcome to the club: https://community.cloudflare.com/t/sometimes-a-cf-520-error/288733
It seems to be a Cloudflare issue introduced in late July affecting hundreds of sites running very different configurations. It's been almost a month since the issue was first reported, Cloudflare "fixed" it twice, but it's still there. Very frustrating.
Change your webserver logs to a info state and see if your application is not exceeding some HTTP/2 directive while processing the connection.
If this is the case, try to increase the directive size:
#nginx
server {
...
http2_max_field_size 64k;
http2_max_header_size 64k;
}

RTSP: Not receiving SDP from the server after sending "describe" request

I have a Bosch camera(server) and my end goal is to get the video content description via metadata from it. I am using LwIP Raw API's(1.4.0) for this purpose. At present, I am trying to authenticate with the camera and receive the SDP so I can setup the session. However, after I authenticate by resending the describe request with the digest, I don't get any response from the server and after a while the server resets the connection. Below is the sequence of operations I perform for authentication.
Step 1: Client to Server (mcu sends 1st describe request)
DESCRIBE rtsp://service:PRBUWPCs7*f40j#192.168.1.129/?enablevideo=0&vcd=1 RTSP/1.0
CSeq: 1
User-Agent: rtsp://service:PRBUWPCs7*f40j#192.168.1.129(LIVE555 Streaming Media v2018.02.28)
Accept: application/sdp
Step 2: Server to Client (server responds with nonce for authentication, rx via callback)
Payload:RTSP/1.0 401 Unauthorized
CSeq: 1
WWW-Authenticate: Digest realm="Please log in with a valid
username",nonce="7bd251bb670e45966c415838679f778f",opaque="",stale=FALSE,algorithm=MD5
Step 3: Client to Server (mcu computes the response and resends the describe command )
DESCRIBE rtsp://service:PRBUWPCs7*f40j#192.168.1.129/?enablevideo=0&vcd=1 RTSP/1.0
CSeq: 2
Authorization: Digest username="service", realm="Please log in with a valid username", nonce="7bd251bb670e45966c415838679f778f", uri="rtsp://service:PRBUWPCs7*f40j#192.168.1.129/?enablevideo=0&vcd=1", response="4c87974de2e3ecc3d534beddef9e6962"
User-Agent: rtsp://service:PRBUWPCs7*f40j#192.168.1.129(LIVE555 Streaming Media v2018.02.28)
Accept: application/sdp
Step 4: mcu waiting for SDP, but instead receives pbuf *p as null in the receive call back function.
After a few seconds, also receives a tcp err callback with err code ERR_RST i.e. connection reset.
Could anyone please clarify if my above procedure is correct and if so, any insights on what could likely cause the camera not to respond with the SDP description leading to connection reset and receiving pbuff as NULL in the receive callback? 
Fixed it. There was an issue with md5 module.

Boost asio GET with client certificate sslv3 hand shake failed

I want to do a simple C++ web get similar to what is done by this curl command. I can use asio from boost. I must use boost 1.49
curl https://mysite.dev/api/v1/search?q=test -k --cert
C:\work\testCert.pem
The server is requiring the client certificate.
I started by using this as an example http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/ssl/client.cpp
and I added modifications by adding calls to the context like
ctx.set_options(boost::asio::ssl::context::default_workarounds);
ctx.use_certificate_file("C:\\work\\testCert.pem", boost::asio::ssl::context_base::pem);
ctx.use_private_key_file("C:\\work\\testKey.pem", boost::asio::ssl::context_base::pem);
My Request Looks like this:
GET /api/v1/search?q=test HTTP/1.0
Host: mysite.dev
Accept: */*
but I keep getting messages like this
Error: sslv3 alert handshake failure
clearly there is a step I am missing in the handshake process
The solution was to disable SSLv3 support, appartently most servers disable this because of design flaws.
ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);

CouchDB Proxy Authentication Doesn't work

When I send a http request to my couchdb server like it is shown in the docs here CouchDB Proxy Authentication, it doesn't give the response shown in the docs, just empty data. What am I doing wrong?
Also, am I able to start a session with this Proxy Auth? If I try a POST /_session, I get 500 error code.
GET /_session HTTP/1.1
Host: 127.0.0.2:5984
User-Agent: curl/7.51.0
Accept: application/json
Content-Type: application/json; charset=utf-8
X-Auth-CouchDB-UserName: john
X-Auth-CouchDB-Roles: blogger
< HTTP/1.1 200 OK
< Cache-Control: must-revalidate
< Content-Length: 132
< Content-Type: application/json
< Date: Sun, 06 Nov 2016 01:10:58 GMT
< Server: CouchDB/2.0.0 (Erlang OTP/17)
<
{"ok":true,"userCtx":{"name":null,"roles":[]},"info":{"authentication_db":"_users","authentication_handlers":["cookie","default"]}}
I found in the CouchDB issue tracker that the Proxy Authentication is broken in version 2.0.0. Either that or the docs aren't updated to indicate that it only works with clusters or something. I changed back to version 1.6.1 and everything works fine. I must say that the documentation for how Proxy Authentication works is very poor.
How it works is you need your third party authentication server to have the "[couch_httpd_auth] secret" and when a client authenticates, you need to generate a HMAC-SHA1 token by combining the username and secret. Then, on any http requests you make from the client to the CouchDB server, if you include all the headers:
X-Auth-CouchDB-Roles
X-Auth-CouchDB-UserName
X-Auth-CouchDB-Token
that request will be authenticated as a user client.
Also, it is not mentioned in the docs, but POST on the /_session API using these headers does nothing.
It's not the Proxy Authentication itself which is broken in CouchDB 2.0, it's just that in the current release there's no way to configure the authentication handlers like there was in the old 1.6 days.
There are some patches mentioned in the issue tracker which add proxy authentication to the list of authentication handlers. Furthermore there was a pull request which was accepted and merged which brings back configurability to CouchDB 2.0.
However in order to take advantage of those I'm afraid you either have to wait until the next release, or build CouchDB 2.0 yourself from the sources.
Proxy authentication is fixed as of CouchDB 2.1.1. The latest (>2.1.1) documentation shows how to configure proxy authentication again, along with the important proxy_use_secret option.