Node wont make connection to server with self signed certificate - node.js

A little background:
I have a Tesla Powerwall which has it's own built in web server that can be accessed on the local network. It only allows SSL connections and uses a self signed certificate. I have setup port forwarding that allows me to connect to the web server remotely. For a while, i've had working node.js apps both on a local Pi and also a remote AWS instance that made requests to the Powerwall web server to retrieve bits of information.
Since yesterday, Tesla updated my Powerwall and now everything has stopped working. I can only assume they have changed something regarding how the web server handles it's self signed SSL certificate.
Firstly, my Pi running on the local network would not make successful node.js requests to the local server. I managed to get this working by adding an entry to my /etc/hosts file like this:
192.168.1.42 powerwall
and now my node.js app can successfully connect again using https://powerwall
When using Safari or Chrome to connect remotely, I can connect if I use my IP address (After trusting the self signed cert) but cannot connect when using my DDNS address that points to home. (I have confirmed the DDNS is working). It gives me the error:
Safari can’t open the page “https://home.xxxxxx.com:4444” because Safari can’t establish a secure connection to the server “ home.xxxxxx.com”.
My AWS node.js app will not connect regardless of me using the IP address or DDNS address giving me the error:
Client network socket disconnected before secure TLS connection was established
This is how I am trying to connect:
request({
url: 'https://xx.xx.xx.xx:xxxx/api/system_status/soe',
method: 'GET',
rejectUnauthorized: false,
requestCert: true,
agent: false,
headers: headers
}
I have tried adding:
secureProtocol: 'TLSv1_method'
and attempted with the methods TLSv1_method TLSv1_1_method TLSv1_2_method in case it needed a specific method, with no luck.
Does the above sound like the SSL settings on the server have been screwed down?
What can I do to:
a) access the site remotely through a browser using the DDNS address
b) force node.js to not be interested in the SSL certificate at all and just connect
----- EDIT
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
46:.....
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=US, ST=California, L=Palo Alto, O=Tesla, OU=Tesla Energy Products, CN=335cbec3e3d8baee7742f095bd4f8f17
Validity
Not Before: Mar 29 22:17:28 2019 GMT
Not After : Mar 22 22:17:28 2044 GMT
Subject: C=US, ST=California, L=Palo Alto, O=Tesla, OU=Tesla Energy Products, CN=335cbec3e3d8baee7742f095bd4f8f17
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:ca...
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:teg, DNS:powerwall, DNS:powerpack, IP Address:192.168.90.1, IP Address:192.168.90.2, IP Address:192.168.91.1

With HTTPS, the domain needs to match what’s signed in the cert; it’s usually the public domain.
It’s not supposed to be the IP, and it certainly won't be the DDNS hostname (if I understood correctly) you’re pointing at it.
There are 3 possible approaches;
Add the certificate from the powerwall as a ‘known’ rootCA (as already suggested),
Tell node.js to skip checking the validity of the certificate, or
Try with HTTP 😬
Proper operation of the HTTPS connection process will also depend on you accessing the powerwall using the domain name registered in the certificate (which may require your DNS server to respond with the appropriate IP when the lookup is made ~> like DNS spoofing proof-of-concept for a CTF).
Also, to your musings in comments, while some browsers may allow you to override an expired or self-signed cert (or when connecting via IP), but it’s very sketchy to connect with a domain and get a cert that specifies and entirely different domain (which is why the browser might not even present you the option).
HTH
Post-resolution update:
How to get the DNS name to match what's on the certificate:
add an entry in the client system's /etc/hosts or equivalent
connect using the hostname (not the IP)
When connecting over public Internet:
How to get public-internet connections through to the local host:
get a public-facing HTTPS cert (e.g.) that matches your DDNS domain or /etc/hosts entry
Host a HTTP-proxy
relay requests from Internet (hopefully with filtering/validation) to the powerwall
(you will have 2 HTTPS connections: one from AWS -> proxy, one from proxy->powerwall)
Host a custom API that will return exactly the [minimum] info needed by the AWS service
How to trust a self-signed certificate? (this wasn't the blocking factor)

Try this for debugging:
openssl s_client \
-connect 192.168.1.42:4444 \
-CAfile /path/to/self-signed-cert \
-verify_hostname powerwall \
-debug
Can find more options in openssl s_client -help
Do you have any servers running on your home network (apache, nginx, etc)? You're probably trying to connect to https://my.ddns.com and you're passing it directly to powerwall, which has a certificate for powerwall.
Connecting to a host that returns a certificate which does not contain that hostname will cause a TLS error. You probably want to run a forward proxy, where your server hosts my.ddns.com, sets up the TLS connection and then forwards the traffic (without TLS) to 192.168.1.44.

Related

What key should I use to sign an intermediate SSL certificate for a reversed proxied HTTPS connection?

I have an Apache server hosting a couple webpages, and an express server running on another machine that connects via a reverse proxy to the apache server, providing an endpoint to the webpage. The webpage is already running on HTTPS with valid certificates, but now I have to configure the express server to do the same with the intermediate certificates, I believe Which private key should I use to setup this service? Or are the intermediate certs signed by the apache head? I don't think that is the case since the configuration dones't work without a key, but I still cannot get my head around how this works if the certificates are issued at the same time the private key of the server is generated. How is it possible to cofigure intermediate connections with intermediate certs if the intermediate servers didn't exist when the certificates where issued?
This is the express server configuration so far:
const options = {
// The same certificate apache uses. Is this right?
cert: fs.readFileSync(config.ssl.dir + config.ssl.cert)
// The three sections of the bundle the issuer provided
ca: [],
// The private key I don't have (its in the other server)
key: fs.readFileSync(config.ssl.dir + config.ssl.key),
};
config.ssl.ca.forEach((value) => {
if (value) options.ca.push(fs.readFileSync(config.ssl.dir + value));
});
server = https.createServer(options, app);
Some more information, I have three files:
certificate.csr, the one the apache server uses and works, so I think it is the root certificate
certificate.pem, with the exact same contents as certificate.csr
a_bundle.csr, with three sections. I believe those are the intermediate certs.
These files were provided by GoDaddy.com when buying the ssl certificates, but with meaningless names.

TLS handshake fail. HTTPS request to HAproxy to http and then encrypt it again to forward request to ssl server

Need help!!! . I have an https request and need to intercept it, read values and forward the same ssl request to the destination. I have all the required crt, key, CA with me. I am aware that Haproxy ACL does not work with L4 layer but I'm trying to find a workaround to decrypt the message, read the message, encrypt it again and forward. The reason for reading message is to using ACL i need to read the path difference in carious request and route the request to different servers accordingly. I am trying to intercept the client request to server, the request by default is SSL and server is expecting an SSL request
ssl crt: created a new user with new crt-key pair and used Certificate Signing Requests of server to authenticate it against CA in server
The scenario is that I have an incoming SSL request which I'm capturing into frontend of haproxy with the server certificate, while forwarding that request to a test webserver I am able to see that it has changed from HTTPS to HTTP. Now when I try re-encrypt it, the original destination is not able to accept the request since it is not SSL, I have tried to add the certs in the backend but not useful. Please check my current Haproxy config and please help if possible. I am not an expert in Network communication/ Encryption/ HaProxy.
frontend test
bind IP:6443 ssl crt <location>
option httplog
mode http
default_backend testback
backend testback
mode http
balance roundrobin
option http-check
server <host> IP:6443 check fall 3 rise 2 ssl verify required ca-file <loc> crt <loc>
To verify my certicates are valid and connecting:
openssl s_client -connect :6443 -cert myuser.crt -key myuser.key -CAfile ca.crt
Output:
SSL handshake has read 1619 bytes and written 2239 bytes
Verification: OK
So no problem with Certicates i presume, problem while using Ha proxy for connection
Error:
Unable to connect to the server: x509: certificate specifies an incompatible key usage
Ha proxy error:
2021-08-12T14:45:36.930478+02:00 parasilo-27 haproxy[21562]: :34672 [12/Aug/2021:14:45:36.927] server/1: SSL handshake failure
2021-08-12T14:45:37+02:00 localhost haproxy[21562]: :34674 [12/Aug/2021:14:45:37.438] server/1: SSL handshake failure
To sum up what was analyzed in the comments, as asked. Perhaps it will be useful to somebody someday.
Haproxy's config turned out to be correct, but generated certificates had wrong extended key usage (X509v3 extension).
Command to list extended key usage:
openssl x509 -in /path/to/cert.pem -noout -ext extendedKeyUsage
Often, when bought on internet, it shows X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication. Original Poster used self-signed, self-generated certificates and his certificate used on haproxy's frontend had only TLS Web Client Authentication, where frontend requires TLS Web Server Authentication if this extensions is used at all.
That resulted in the error message:
Error: kubectl get po: Unable to connect to the server: x509: certificate specifies an incompatible key usage
As a consequence haproxy logged SSL handshake failure without any more details, as is its habit.
After adding TLS Web Server Authentication to certificate in haproxy's frontend section and TLS Web Client Authentication to certificate in haproxy's backend section Original Poster reported success.

EMR Presto LDAPS: authenticator not loaded

LDAPS is correctly set up using docker-openldap.
Certificates correctly generated and deployed (also tried self generated certificates)
ldapwhoami and ldapsearch both works
Presto complains authenticator not loaded, with DEBUG level logging it says "simple bind failed: outbound connection failed"
It turns out by default osixia/openldap container will run with TLS client certificate verification on (demand). This requires a local certificate and a private key, i.e. the ldap server will try to validate client owns a valid certificate.
ldapwhoami works because the client certificate was imported to local machine, but on Presto node only a root certificate was imported during initialization.
The error message was not clear, showing UncheckedException, authenticator not loaded, simple bind failed, etc.
The solution is to disable client certificate verification. When launching the docker, add --env LDAP_TLS_VERIFY_CLIENT=try or never.
Importing the private key to default Java keystore might also work if client verification is desired.

Insomnia and NodeJS: "Error: Peer certificate cannot be authenticated with given CA certificates"

I'm trying to send a GET request using the Insomnia app to a NodeJS server app -- I didn't write the app but have joined the team.
Although I get a reasonable JSON response when I hit the URL -- https://127.0.0.1:9999 -- from the browser, I get the error "Error: Peer certificate cannot be authenticated with given CA certificates" when I'm using Insomnia. Using a Mac, MacOS 10.12.4. Node v6.3.1.
The Insomnia timeline says:
* Preparing request to https://127.0.0.1:9999/
* Enable automatic URL encoding
* Enable SSL validation
* Enable cookie sending with jar of 2 cookies
* Hostname in DNS cache was stale, zapped
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 9999 (#8)
* WARNING: using IP address, SNI is being disabled by the OS.
* SSL certificate problem: Invalid certificate chain
* Curl_http_done: called premature == 1
* Closing connection 8
Thanks for any help!
There is little documentation on how Insomnia handles certificates. As long as they are normal certificates that are signed by a typical CA authority there is typically no problem. Since you also refer to your loopback address (127.0.0.1) I assume that you're also testing with a self-signed certificate.
I noticed that Insomnia uses the Mozilla list of certificate authorities. It does not use the list of your operating system.
The list is stored in a text-file in a directory like C:\Temp\insomnia_5.12.4. In my case it was for example 2017-01-18.pem. You can add your own signing authority certificate to this file.
I didn't look into how stable this file is or how it is created.
You can also workaround the certificate errors by disabling them in your settings (settings > Validate SSL Certificates).

Node.js SSL client connection with wrong certificate

I am trying to use the TLS module to perform an SSL connection to a server which happens to provide a wrong certificate (the hostname of server (xxx.example.com) does not match the common name of the certificate (yyy.example.com)).
I managed to get the client connecting without throwing an error by adding the option rejectUnauthorized: false.
However when the client is connected it is still unauthorized and the authorizationError is Hostname/IP doesn't match certificate's altnames.
How can I get around this? I obviously have no power on changing the server certificate (I did however contact them to try to get them amend the certificate).

Resources