Heroku Hobby Dyno: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR, server verification OK but ALPN server does not agree to protocol - ssl

I have a simple app where the client is sending a request to join a websocket channel upon page load via a wss connection. I have deployed my app to heroku at domain my_app.heroku.com. Whenever I open my site, I get the error Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR. I understand that this is an SSL issue, and also that to use Heroku's SSL, you must be on a hobbyist account. So, I upgraded the app to hobbyist (one day ago), but it has not fixed the problem.
I have googled the issue, and from what I see it appears that additional setup beyond upgrading to Heroku Hobby should only be required if using a custom domain-name, which I am not. How can I get the SSL working on my my_app.heroku.com domain with the Hobby dyno?
EDIT: If I run curl -vI <my_app>.heroku_app.com I get the following:
curl -vI https://<my_app>.herokuapp.com
* Rebuilt URL to: https://<my_app>.herokuapp.com/
* Trying __.___.___.___...
* Connected to <my_app>.herokuapp.com (__.___.___.___) port 443
(#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 592 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: *.herokuapp.com (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: C=US,ST=California,L=San Francisco,O=Heroku\, Inc.,CN=*.herokuapp.com
* start date: Wed, 19 Apr 2017 00:00:00 GMT
* expire date: Mon, 22 Jun 2020 12:00:00 GMT
* issuer: C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert SHA2
High Assurance Server CA
* compression: NULL
* ALPN, server did not agree to a protocol
> HEAD / HTTP/1.1
> Host: <my_app>.herokuapp.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: Cowboy
Server: Cowboy
< Connection: keep-alive
Connection: keep-alive
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Content-Length: 1154
Content-Length: 1154
< Date: Thu, 22 Nov 2018 08:39:51 GMT
Date: Thu, 22 Nov 2018 08:39:51 GMT
< Via: 1.1 vegur
Via: 1.1 vegur

I found the answer after finally finding this question. I thought all along the issue was due to setting up SSL certificates on Heroku, however it was due to my client side code. Per the tutorial I was following, the WS connection was "wss://my_app.herokuapp.com:80/subscribe". Removing the port number was the fix.

Related

curl changes the URI in the authorization header for digest behind proxy

The bounty expires in 4 days. Answers to this question are eligible for a +50 reputation bounty.
Mirza Prangon is looking for an answer from a reputable source:
Details how what is going wrong, where it is going wrong and how to fix it.
I am trying to use curl for a http request.
I have to use it behind a enterprise proxy server. The remote host uses digest authentication.
I am using the following curl command.
curl -x "http://proxy_username:proxy_pass#proxyIp.xxx.xxx.xxx:8080" -L -X GET "https://remote-host.something.com:443/tomcat_servlet/UploadServlet" --digest -u digest_auth_user:digest_auth_pass -v -k
But I get 400 bad request from apache httpd. The full output from curl is
* Trying proxyIp.xxx.xxx.xxx:8080...
* Connected to proxyIp.xxx.xxx.xxx (proxyIp.xxx.xxx.xxx) port 8080 (#0)
* allocate connect buffer
* Establish HTTP proxy tunnel to remote-host.something.com:443
* Proxy auth using Basic with user 'proxy_username'
* Server auth using Digest with user 'digest_auth_user'
> CONNECT remote-host.something.com:443 HTTP/1.1
> Host: remote-host.something.com:443
> Proxy-Authorization: Basic <redacted>
> User-Agent: curl/7.83.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
< Via:HTTP/1.1 s_proxy_nrt
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed
* schannel: disabled automatic use of client certificate
* ALPN: offers http/1.1
* ALPN: server did not agree on a protocol. Uses default.
* Server auth using Digest with user 'digest_auth_user'
> GET /tomcat_servlet/UploadServlet HTTP/1.1
> Host: remote-host.something.com
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 307 Temporary Redirect
< Server: Cisco Umbrella
< Date: Tue, 14 Feb 2023 02:52:03 GMT
< Content-Type: text/html
< Content-Length: 190
< Connection: keep-alive
< Set-Cookie: swg_https_a2bc=1; Path=/; Expires=Tue, 14-Feb-23 03:02:03 GMT; domain=remote-host.something.com; SameSite=None; Secure
< Location: https://remote-host.something.com/tomcat_servlet/UploadServlet?swg_a2bc=1
< Via: HTTP/1.1 s_proxy_nrt
<
* Ignoring the response-body
* Connection #0 to host proxyIp.xxx.xxx.xxx left intact
* Issue another request to this URL: 'https://remote-host.something.com/tomcat_servlet/UploadServlet?swg_a2bc=1'
* Found bundle for host: 0x1a0ed47d970 [serially]
* Re-using existing connection #0 with proxy proxyIp.xxx.xxx.xxx
* Connected to proxyIp.xxx.xxx.xxx (proxyIp.xxx.xxx.xxx) port 8080 (#0)
* Server auth using Digest with user 'digest_auth_user'
> GET /tomcat_servlet/UploadServlet?swg_a2bc=1 HTTP/1.1
> Host: remote-host.something.com
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Date: Tue, 14 Feb 2023 02:52:03 GMT
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 381
< Connection: keep-alive
< Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1k
< WWW-Authenticate: Digest realm="https_transfer", nonce="redacted", algorithm=MD5, qop="auth"
< Via: HTTP/1.1 m_proxy_nrt
<
* Ignoring the response-body
* Connection #0 to host proxyIp.xxx.xxx.xxx left intact
* Issue another request to this URL: 'https://remote-host.something.com/tomcat_servlet/UploadServlet?swg_a2bc=1'
* Found bundle for host: 0x1a0ed47d970 [serially]
* Re-using existing connection #0 with proxy proxyIp.xxx.xxx.xxx
* Connected to proxyIp.xxx.xxx.xxx (proxyIp.xxx.xxx.xxx) port 8080 (#0)
* Server auth using Digest with user 'digest_auth_user'
> GET /tomcat_servlet/UploadServlet?swg_a2bc=1 HTTP/1.1
> Host: remote-host.something.com
> Authorization: Digest username="digest_auth_user",realm="https_transfer",nonce="redacted",uri="/tomcat_servlet/UploadServlet?swg_a2bc=1",cnonce="redacted",nc=00000001,algorithm=MD5,response="redacted",qop="redacted"
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Date: Tue, 14 Feb 2023 02:52:03 GMT
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 226
< Connection: keep-alive
< Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1k
< Via: HTTP/1.1 m_proxy_nrt
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
* Connection #0 to host proxyIp.xxx.xxx.xxx left intact
Is the server side, I get the following in httpd log.
[auth_digest:error] [pid 3052:tid 1928] [client xxx.xxx.xxx.xxx:xxx] AH01786: uri mismatch - </tomcat_servlet/UploadServlet?swg_a2bc=1> does not match request-uri </tomcat_servlet/UploadServlet>
Indeed, cURL is adding some query it is getting from the proxy server in the authentication header.
Settings of my httpd
<Location /tomcat_servlet>
ProxyPass http://localhost:8080/tomcat_servlet
ProxyPassReverse http://localhost:8080/tomcat_servlet
AuthType Digest
AuthName https_transfer
AuthUserFile ${SRVROOT}/conf/.htpasswd
Require valid-user
</Location>
How do I use cURL in this situation? Or should I change some settings in the httpd side?

Invalid client type getting verification code for limited input devices with google oauth

I'm trying to add google login for limited input devices as described here for a Web application type.
Using my client_id I cannot get the verification code because I keep getting this error:
$> curl -d "client_id=887293527777-tf5uf5q5skss8sbktp1vpo67p2v5b7i7.apps.googleusercontent.com&scope=email%20profile" https://accounts.google.com/o/oauth2/device/code
{
"error" : "invalid_client",
"error_description" : "Invalid client type."
}
And with verbose output:
$> curl -d "client_id=887293527777-tf5uf5q5skss8sbktp1vpo67p2v5b7i7.apps.googleusercontent.com&scope=email%20profile" https://accounts.google.com/o/oauth2/device/code -vvv
* Trying 209.85.203.84...
* TCP_NODELAY set
* Connected to accounts.google.com (209.85.203.84) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* ALPN, server accepted to use h2
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=accounts.google.com,O=Google Inc,L=Mountain View,ST=California,C=US
* start date: Feb 07 21:22:30 2018 GMT
* expire date: May 02 21:11:00 2018 GMT
* common name: accounts.google.com
* issuer: CN=Google Internet Authority G2,O=Google Inc,C=US
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x56450ea69cd0)
> POST /o/oauth2/device/code HTTP/1.1
> Host: accounts.google.com
> User-Agent: curl/7.51.0
> Accept: */*
> Content-Length: 104
> Content-Type: application/x-www-form-urlencoded
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* We are completely uploaded and fine
< HTTP/2 401
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< cache-control: no-cache, no-store, max-age=0, must-revalidate
< pragma: no-cache
< expires: Mon, 01 Jan 1990 00:00:00 GMT
< date: Fri, 23 Feb 2018 14:29:41 GMT
< server: ESF
< x-xss-protection: 1; mode=block
< x-frame-options: SAMEORIGIN
< alt-svc: hq=":443"; ma=2592000; quic=51303431; quic=51303339; quic=51303338; quic=51303337; quic=51303335,quic=":443"; ma=2592000; v="41,39,38,37,35"
< accept-ranges: none
< vary: Accept-Encoding
<
{
"error" : "invalid_client",
"error_description" : "Invalid client type."
* Curl_http_done: called premature == 0
* Connection #0 to host accounts.google.com left intact
}
This is really annoying given they give a curl example on their guide. I've tried from javascript too but with no luck.
Edit: I can curl using Other as the type so I don't think the problem is on my side, but using Other is no good to me because I need to use Web Application in order to set CORS.
That flow is only supported for client type "TVs and Limited Input devices". See https://developers.google.com/identity/sign-in/devices#get_a_client_id_and_client_secret

Heroku SSL host not working (Heroku | No such app)

I successfully used Letsencrypt to generate certificates and I uploaded them to Heroku using:
this-site ********$ heroku addons:create ssl:endpoint
Creating ssl-graceful-41756... done, ($20.00/month)
Adding ssl-graceful-41756 to this-site... done
Next add your certificate with `heroku certs:add CERT KEY`.
Use `heroku addons:docs ssl` to view documentation.
this-site ********$ sudo heroku certs:add /etc/letsencrypt/live/www.this-site.com/fullchain.pem /etc/letsencrypt/live/www.this-site.com/privkey.pem
Resolving trust chain... done
Adding SSL Endpoint to this-site... done
this-site now served by qwasf-34234.herokussl.com
Certificate details:
Common Name(s): www.this-site.com
Expires At: 2016-09-02 19:15 UTC
Issuer: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
Starts At: 2016-06-04 19:15 UTC
Subject: /CN=www.this-site.com
SSL certificate is verified by a root authority.
However, when I visit qwasf-34234.herokussl.com, it is not working. It has a page that says: Heroku | No such app ; There is no app configured at that hostname.
Perhaps the app owner has renamed it, or you mistyped the URL.
I am copy and pasting the exact new host that heroku gave me. Going to https://qwasf-34234.herokussl.com yields the same page.
I verified the certificate with:
this-site ********$ heroku certs
Endpoint Common Name(s) Expires Trusted
-------------------------- --------------------- -------------------- -------
qwasf-34234.herokussl.com www.this-site.com 2016-09-02 19:15 UTC True
More checks:
this-site *******$ curl -kvI https://www.this-site.com
* Rebuilt URL to: https://www.michaelsutyak.com/
* Trying 23.21.142.230...
* Connected to www.this-site.com (23.21.142.230) port 443 (#0)
* TLS 1.2 connection using TLS_********************
* Server certificate: *.herokuapp.com
* Server certificate: DigiCert ******
* Server certificate: DigiCert *******
> HEAD / HTTP/1.1
> Host: www.this-site.com
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: Cowboy
Server: Cowboy
< Connection: keep-alive
Connection: keep-alive
< Vary: Accept-Encoding
Vary: Accept-Encoding
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Date: Sat, 04 Jun 2016 20:57:00 GMT
Date: Sat, 04 Jun 2016 20:57:00 GMT
< Via: 1.1 vegur
Via: 1.1 vegur
<
* Connection #0 to host www.this-site.com left intact
What is going on here and how can this work? I just want https for my site.
You cannot access the Heroku SSL endpoint directly. That endpoint represents the hostname where you need to point your domain to, as explained in the DNS and domain configuration of the Heroku article.
If you want to point a subdomain (e.g. www.this-site.com), then create a DNS record CNAME in your DNS hosting provider that points the www record to the Heroku SSL endpoint:
www CNAME qwasf-34234.herokussl.com
If you want to point the root domain (this-site.com), then you need to use a provide that supports the CNAME-like record for the root domain, as explained in this Heroku article as you can't use a CNAME for the root domain.
Make sure your domain is not still pointing to the herokuapp.com hostname.
You can test my assertion by sending a cURL request to the SSL endpoint, but passing the Host header (as the browser would do).
$ curl -i qwasf-34234.herokussl.com -H "Host: www.this-site.com"
You cannot visit the qwasf-34234.herokussl.com domain that Heroku gives you. Instead, you are supposed to change your DNS to point to that as a CNAME, instead of qwasf-34234.herokuapp.com.

X509 parsing error, 'negative serial number' while pulling repository

Our server access internet through a proxy. When I try to run a pull command such as
sudo docker run -t -i ubuntu:14.04 /bin/bash
I get the below error:
Get https://index.docker.io/v1/repositories/ubuntu/images: tls: failed to parse
certificate from server: x509: negative serial number
The wget command wget -S -d -O - https://get.docker.io yields the below output:
Setting --output-document (outputdocument) to - DEBUG output created
by Wget 1.13.4 on linux-gnu.
URI encoding = UTF-8' URI encoding =UTF-8'
--2014-08-27 17:13:46-- https://get.docker.io/ Connecting to :... connected. Created socket 3. Releasing
0x00000000016829f0 (new refcount 0). Deleting unused
0x00000000016829f0.
---request begin--- CONNECT get.docker.io:443 HTTP/1.1 User-Agent: Wget/1.13.4 (linux-gnu) Proxy-Authorization: Basic
Y3RzXDMxMzMwMDpzd2VldGZlbC4yOQ==
---request end--- proxy responded with: [HTTP/1.1 200 Connection established Date: Wed, 27 Aug 2014 11:49:52 GMT Age: 0 Via: 1.0
xaahshshhds
] Initiating SSL handshake. Handshake successful; connected socket 3
to SSL handle 0x00000000016831c0 certificate: subject:
/emailAddress=aaa#bbbb.com/C=yy/ST=aa/L=xx/O=yy/OU=mycompany/CN=get.docker.io
issuer:
/emailAddress=aaa#bbbb.com/C=yy/ST=aa/L=xx/O=yy/OU=mycompany/CN=mycompany
ERROR: cannot verify get.docker.io's certificate, issued by
/emailAddress=aaa#bbbb.com/C=yy/ST=aa/L=xx/O=yy/OU=mycompany/CN=mycompany':
Unable to locally verify the issuer's authority. To connect to
get.docker.io insecurely, use--no-check-certificate'. Closed 3/SSL
0x00000000016831c0
Please give me some directions on how I should go about this issue.
EDIT:
I ve now disabled the proxy for this IP segment but I still get the same error.
The command: wget -S -d -O - https://get.docker.io gets the below output now:
Setting --output-document (outputdocument) to -
DEBUG output created by Wget 1.13.4 on linux-gnu.
URI encoding = `UTF-8'
--2014-09-04 11:26:12-- https://get.docker.io/
Resolving get.docker.io (get.docker.io)... 162.242.195.77
Caching get.docker.io => 162.242.195.77
Connecting to get.docker.io (get.docker.io)|162.242.195.77|:443... connected.
Created socket 3.
Releasing 0x00000000022d8fd0 (new refcount 1).
Initiating SSL handshake.
Handshake successful; connected socket 3 to SSL handle 0x00000000022dabd0
certificate:
subject: /serialNumber=exkd9EjUozUulWIyUDurQPMEPBLSc2Bq/OU=GT98568428/OU=See www.rapidssl.com/resources/cps (c)13/OU=Domain Control Validated - RapidSSL(R)/CN=*.docker.io
issuer: /C=US/O=GeoTrust, Inc./CN=RapidSSL CA
X509 certificate successfully verified and matches host get.docker.io
---request begin---
GET / HTTP/1.1
User-Agent: Wget/1.13.4 (linux-gnu)
Accept: */*
Host: get.docker.io
Connection: Keep-Alive
---request end---
HTTP request sent, awaiting response...
---response begin---
HTTP/1.1 503 Service Unavailable
Server: nginx/1.7.1
Date: Thu, 04 Sep 2014 06:03:28 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: no-cache
---response end---
HTTP/1.1 503 Service Unavailable
Server: nginx/1.7.1
Date: Thu, 04 Sep 2014 06:03:28 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: no-cache
Registered socket 3 for persistent reuse.
Skipping 108 bytes of body: [<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
] done.
2014-09-04 11:26:13 ERROR 503: Service Unavailable.
subject: /emailAddress=aaa#bbbb.com/C=yy/ST=aa/L=xx/O=yy/OU=mycompany/CN=get.docker.io
issuer: /emailAddress=aaa#bbbb.com/C=yy/ST=aa/L=xx/O=yy/OU=mycompany/CN=mycompany
It looks like the proxy in your company uses SSL interception to inspect SSL traffic, which means that you get a certificate signed by the proxy CA of your company instead of the original certificate. It also looks like that this proxy CA is not trusted by your system and thus the verification fails.
I would recommend that you contact your firewall administrator on how to deal with the problem. Either they will add an exception for the SSL inspection, or they will tell you which certificate you need to import as trusted in your system.
This should be fixed for any Docker compiled with Go 1.6+, see: https://github.com/golang/go/commit/a0ea93dea5f5741addc8c96b7ed037d0e359e33f.

Golang issue x509: cannot verify signature: algorithm unimplemented on net/http

I was writing a very simple Golang script and use this library golang-jenkins to connect with our internal HTTPS server. But I face the following x509 cert issue and wasn't sure what to do with the x509 cert problem. Our team has zero access to Jenkins and would like to know what else we can do to dig more about the issue.
$ go run jenkins.go
2014/07/28 22:00:29 [] Get https://jenkins.mydomain.com/api/json: x509: certificate signed by unknown authority (possibly because of "x509: cannot verify signature: algorithm unimplemented" while trying to verify candidate authority certificate "MyDomain Internal Root CA")
using curl:
$ curl -v "https://jenkins.mydomain.com/api/json"
* Adding handle: conn: 0x7f8469004000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f8469004000) send_pipe: 1, recv_pipe: 0
* About to connect() to jenkins.mydomain.com port 443 (#0)
* Trying 10.38.8.70...
* Connected to jenkins.mydomain.com (10.38.8.70) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: jenkins.mydomain.com
* Server certificate: MyDomain Server CA - 2014
* Server certificate: MyDomain Internal Root CA
> GET /api/json HTTP/1.1
> User-Agent: curl/7.30.0
> Host: jenkins.mydomain.com
> Accept: */*
>
< HTTP/1.1 200 OK
* Server nginx is not blacklisted
< Server: nginx
< Date: Tue, 29 Jul 2014 05:03:45 GMT
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: JSESSIONID.214ca1a4=1ry000odf815goiv7vl8tr627;Path=/;Secure
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< X-Jenkins: 1.554.3
< X-Jenkins-Session: c660ff91
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 is currently broken in Go, it will be supported in v1.4, the only workaround is to downgrade the TLS MaxVersion.
A quick look at golang-jenkins, it doesn't allow specifying the http.Client to use and just uses http.DefaultClient, the only ugly way to downgrade TLS's MaxVersion is to override http.DefaultClient.Transport.
You should be able to do something like this in func init() before you try to connect to anything:
cfg := &tls.Config{
MaxVersion: tls.VersionTLS11, // try tls.VersionTLS10 if this doesn't work
PreferServerCipherSuites: true,
}
http.DefaultClient.Transport = &http.Transport{
TLSClientConfig: cfg,
}
Keep in mind this will set the transport for anything that uses http.DefaultClient directly, like http.Get, however if you use your own instance, you will be fine.
Discussion about the bug: https://groups.google.com/forum/#!topic/golang-nuts/oK3EBAY2Uig