Node.js TLS connections without hostname verification - node.js

I'm playing with a swarm of "nodes" connecting to each other, and all I really care for is that they are connected securely to each other and are all authenticated.
For this I figured the TLS module would be a good fit. I created a CA and signed a bunch of certificates, one for each node. I then hit the issue that certificates are now validated against the host from which the node connects.
Is it possible somehow to disable or work around the Common Name validation?
Is there something fundamentally flawed about this setup?
Am I correct that, as long as these certificates are signed by my CA, the connection should be secure and I am certain only my nodes can connect?
It seems like just an annoyance having to sign certificates locked to a hostname or IP (or several in case of multiple interfaces). I've learned that the requirement to validate the host is actually not a part of TLS but HTTPS - in that light, it might be a Node.js bug to do so by default?

Is it possible somehow to disable or work around the Common Name validation?
This is possible by setting the checkServerIdentity option of tls.connect to a no-op function:
const tls = require('tls')
tls.connect({
checkServerIdentity: () => undefined,
...
})
Sources:
https://nodejs.org/api/tls.html#tls_tls_checkserveridentity_host_cert
https://github.com/nodejs/node/blob/df63e534584a54dcf02b37446e1e821382e3cef3/lib/tls.js#L168-L231
https://github.com/nodejs/node/blob/79261f3003719264bc03f6a5b54cf9eddbc8b48e/lib/_tls_wrap.js#L1046

Related

Trusting individual invalid certs in mitmproxy

I use mitmproxy to gather intel from outbound AS2 (HTTP) requests leaving our network. The schema goes like this:
Mendelson AS2 ➡ mitmproxy ➡ partner AS2 server
↘
redis
Where possible, I need to verify all SSL certs to make sure the business connection is safe. Some partners use less known CAs which I then add to a truststore used by the ssl_verify_upstream_trusted_ca option.
Some partners though don't really care about security and I need to trust their certificates no matter what. How do I do that in mitmproxy? Disabling the verification entirely isn't an option.
Thank you.
It's been a while since I've tried to solve this using a custom addon and it seems to work fine so I'll share it here:
https://gist.github.com/jsmucr/24cf0859dd7c9bba8eb2817d7b0bf4b6
This approach has a bit of disadvantage and that's the fact that it doesn't check if the peer certificate changes.

How to tell if a TLS server requested a client certificate

I'm making TLS client connections in Node.js. Some servers I communicate with request a client certificate. I'd like to be able to detect when this has been requested, so I can log it. At the protocol level I believe this is sent along with the TLS server hello, so the data is there, but I'm not sure how I can get at it.
I'm never actually providing a client certificate for now, I'm just aiming to report which servers requested one.
I think there's probably two cases here:
A cert has been requested, not provided, and the server has accepted the connection anyway (and then probably given my some kind of 'not authenticated' response).
A cert has been requested, not provided, and the server has rejected the TLS connection entirely.
At the moment I can't detect either case, solutions for either or both very welcome.

Node.js Multiple SSL Certificates

Is it possible to have Node.js use multiple SSL certificates? I am currently using one certificate but had a new certificate issued that matches other domains.
Since my server is behind a load balancer, there are two ways to get to it and I'd like to match them. Is there a way to use two certificates, instead of creating one with both matches?
See this answer for hosting multiple domains on a single https server
In short, you can use the SNI callback from the https server.
SNI stands for Server Name Identification and it is implemented by all modern browsers.
How it works:
The browser sends the hostname unencrypted (if it supports SNI). The rest of the request is encrypted by the certificate. The HTTPs module can then let you decide which SSL certificate is going to be used to decrypt the connection.
SNI Notes:
SNI is used by AWS Cloudfront and other services, if you require a secure connection
SNI requires a modern browser for it to work.. However given that AWS uses it gives me confidence in using it too.
Depending on how you implement it, it may slow down the request.
It may be better to put a nginx proxy in front of this.
Your connection then travels like this: Client -> (HTTPS) -> NGINX -> (HTTP) -> Node
Nginx could also serve static files, which may optimise your site.
I hope this helps you. I am posting this for documentation purposes.

How to broker secure connection across firewalls using untrusted host?

I have an interesting network security challenge that I can't figure out the best way to attack.
I need to provide a way to allow two computers (A and B) that are behind firewalls to make a secure connection to each other using only a common "broker" untrusted server on the internet (somewhere like RackSpace). (the server is considered untrusted because the customers behind the firewalls won't trust it since it is on an open server) I can not adjust the firewall settings to allow the networks to directly connect to each other because the connections are no known ahead of time.
This is very similar to a NAT to NAT connection problem like that handled by remote desktop help tools (crossloop, copilot, etc).
What I would really like to find is a way to open an SSL connection between the two hosts and have the public server broker the connection. Preferably when host A tries to connect to host B, it should have to provide a token that the broker can check with host B before establishing the connection.
To add another wrinkle to this, the connection mechanism needs to support two types of communication. First, HTTP request/response to a REST web service and second persistent socket connection(s) to allow for real-time message passing.
I have looked at the techniques I know about like OpenSSL using certificates, OAuth, etc, but I don't see anything that quite does what I need.
Has anyone else handled something like this before? Any pointers?
You can solve your problem with plain SSL.
Just have the untrusted server forward connections between the client hosts as opaque TCP connections. The clients then establish an end-to-end SSL connection over that forwarded TCP tunnel - with OpenSSL, one client calls SSL_accept() and the other calls SSL_connect().
Use certificates, probably including client certificates, to verify that the other end of the SSL connection is who you expect it to be.
(This is conceptually similar to the way that HTTPS connections work over web proxies - the browser just says "connect me to this destination", and establishes an SSL connection with the desired endpoint. The proxy just forwards encrypted SSL data backwards and forwards, and since it doesn't have the private key for the right certificate, it can't impersonate the desired endpoint).
In general, SSL is packet-based protocol (for the purpose of solving your task). If you can have the host forward the packets back and forth, you can easily have SSL-secured communication channel. One thing you need is something like our SSL/TLS components, which allow any transport and not just sockets. I.e. the component tells your code "send this packet to the other side" or "do you have anything for me to receive?" and your code communicates with your intermediate server.

Questions about SSL

I have a couple questions about SSL certificates.
I never used them before but my current project requires me to do so.
Question 1.
Where should you use SSL? Like I know places like logging in, resetting passwords are definite places to put it. How about once they are logged in? Should all requests go through SSL even if the data in there account is not considered sensitive data? Would that slow down SSL for the important parts? Or does it make no difference?(sort of well you got SSL might as well make everything go through it no matter what).
Question 2.
I know in smtp you can enable SSL as well. I am guessing this would be pretty good to use if your sending say a rest password to them.
If I enable this setting how can I tell if SSL if it is working? Like how do I know if it really enabled it? What happens if the mail server does not have SSL enabled and your have that boolean value enabled. Will it just send it as non SSL then?
With an SSL connection, one of the most expensive portions (relatively speaking) is the establishment of the connection. Depending on how it is set up, for example, it might create an ephemeral (created on the fly) RSA key for establishing a session key. That can be somewhat expensive if many of them have to be created constantly. If, though, the creation of new connections is less common (and they are used for longer periods of time), then the cost may not be relevant.
Once the connection has been established, the added cost of SSL is not that great although it does depend on the encryption type. For example, using 256-bit AES for encryption will take more time than using 128-bit RC4 for the encryption. I recently did some testing with communications all on the same PC where both client and server were echoing data back and forth. In other words, the communications made up almost the entire cost of the test. Using 128-bit RC4 added about 30% to the cost (measured in time), and using 256-bit AES added nearly 50% to the cost. But remember, this was on one single PC on the loopback adapter. If the data were transmitted across a LAN or WAN, then the relative costs is significantly less. So if you already have an SSL connection established, I would continue to use it.
As far as verifying that SSL is actually being used? There are probably "official" ways of verifying it, using a network sniffer is a poor man's version. I ran Wireshark and sniffed network traffic and compared a non-SSL connection and an SSL connection and looked at the raw data. I could easily see raw text data in the non-SSL version while the SSL "looked" encrypted. That, of course, means absolutely nothing. But it does show that "something" is happening to the data. In other words, if you think you are using SSL but can recognize the raw text in a network sniff, then something is not working as you expected. The converse is not true, though. Just because you can't read it, it does not mean it is encrypted.
Use SSL for any sensitive data, not just passwords, but credit card numbers, financial info, etc. There's no reason to use it for other pages.
Some environments, such as ASP.NET, allow SSL to be used for encryption of cookies. It's good to do this for any authentication or session-ID related cookies, as these can be used to spoof logins or replay sessions. You can turn these on in web.config; they're off by default.
ASP.NET also has an option that will require all authenticated pages to use SSL. Non-SSL requests get tossed. Be careful with this one, as it can cause sessions to appear hung. I'd recommend not turning on options like this, unless you really need them.
Sorry, can't help with the smtp questions.
First off, SSL is used to encrypt communications between client and server. It does this by using a public key that is used for encryption. In my opinion it is a good practice to use it for as anything that has personally identifiable information or sensitive information.
Also, it is worth pointing out that there are two types of SSL authentication:
One Way - in which there is a single, server certificate - this is the most common
Two Way - in which there is a server certificate and a client certificate - the client first verifies the server's identity and then the server ids the client's id - example is DOD CAC
With both, it is important to have up to date, signed, certificates by a reputable CA. This verifies your site's identity.
As for question 2, yes, you should use SSL over SMTP if you can. If your emails are routed through an untrusted router, they can be eavesdropped if sent without encryption. I am not sure about the 'boolean value enabled' question. I don't believe setting up SSL is simply as easy as checking a box though.
A couple people have already answered your Question 1.
For question 2 though, I wouldn't characterize SMTP over SSL as protecting the message. There could be plenty of points at which the message is exposed. If you want to protect the message itself, you need S/MIME, or something similar. I'd say SMTP over SSL is more useful for protecting your SMTP credentials, so that someone cannot grab your password.

Resources