How can I receive the intial TLS SNI domain name, and delay providing a certificate to the client for a few seconds - node.js

When an incoming connection for https://myservice.example.com is received (for the first time) I would like to be able to take some action (based on the SNI name) before giving a valid certificate to the https server to use for that connection. I do not want to break the connection, just delay it for a few seconds.
The action I want to take, on the first connection of an unknown SNI name, is to get a certificate from Let's Encrypt for that (sub)domain. This will take a few seconds, but usually less than a minute, and and will only happen on the first connection.
I want to be able to tell users to set a CNAME or A record for myservicename.theirdomain.com (pointing to my server) and for my server to get a Let's Encrypt cert for myservicename.theirdomain.com on the first attempted connection, with no need for sign-up, etc.
If they first connect using http, there is no issue, as the server can get a certificate and then redirect them to https. It's the cases where they go to https first, that I'm trying to cover. These cases are not getting less common, as browsers ramp-up security and they become littered with permanent redirects to https.
How do I get nodejs to call me as soon as an https connection's SNI name is available, and let me set the certificate before calling it back?

Related

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.

When should HSTS be enabled?

If I am running a HTTPS only service, is there any reason not to enable HSTS? Is there a strategy to test HSTS without permanently enabling it or a way "out of" HSTS?
I'd like to add to Mike's answer the warning, that you are probably not running an HTTPS-only service. The reason is that when your server doesn't listen on port 80 then if you only type in the domain and not the protocol (stackoverflow.com instead of https://stackoverflow.com) your browser will not automatically try to connect on port 443 (https) and show a connection error. Thus for most sites an HTTPS only service is out of the question.
The classical way to ensure an https connection by forwarding every http page to an https page via 301/303 forwards is not a sufficient replacement for HSTS. In fact HSTS was build for that case exactly. The reason is that many bookmarks and links will still point to http and every time a user enters a URL without specifying the protocol - which is always - the browser will first try the http connection. An active attacker can hijack that first connection and never forward the user to the https site.
To give you a more vivid image of such an attack imagine a state who spoofs every DNS request to twitter and answers with its own IPs. When it receives an https request it forwards it to twitter without any action (and chance for interception). But when it receives an http request it uses the tool ssl strip Mike has mentioned to transparently forward the content of the connection to twitter's TLS port. Neither the user nor twitter notice that anything is off (except for the very alert users who checks for TLS encryption) but the state has access to every login password.
HSTS can protect those users that have had a legitimate https connection with the server before and have already seen an HSTS header. The header instructs the browser to exchange every http url of the domain with an https url itself (before an http connection is established at all) and deny any unencrypted connection to this domain. Thus in the scenario above almost all users will not end up on the compromised http connection and are safe against the nation wide attack.
From a defense in depth perspective, you should still enable HTTP Strict Transport Policy (HSTS). There are some issues that could crop up in the future that would benefit from HSTS, including:
Server misconfiguration, where HTTP is accidentally turned on. There's one site I visited recently that takes credit card details, it has a HTTPS site but Google links to their HTTP site so depending on how you got there, you could be submitting your details in the clear.
Malicious attacker poisons or hijacks DNS records to redirect the client to their own HTTP-only server, perhaps in conjunction with an ssl strip attack.
You should also ensure a sufficiently long HSTS lifetime, e.g. a year or more.
You can disable support for HSTS by setting the max-age to 0. You'll need to leave this header in place for as long as you had originally set the value. E.g. If you had set it to 2 years, and change your mind, you'll need to leave max-age=0 for at least 2 years (and continue to offer an HTTPS service on that domain) so past clients won't have any issues connecting to it.

node http proxy SSL transparent

In my setup, I have 2 layers of transparent proxies. When a client makes an SSL request, I wish to have the first proxy it meets simply forward the traffic to another one without attempting to do the handshake with the client.
The setup seems funny, but it is justified in my case - the 2nd proxy registers itself to the first one (through some other service) only occassionally. It tells the first: "I'm interested in some traffic that looks like___". In most cases, the 1st proxy simply does the work.
Can an httpProxy (in node-proxy) proxy SSL requests? Must I use an httpsProxy (which will then do the handshake with the client)?
You could do all of this with the existing httpsProxy if you wanted to. Unless you are wanting to use a non-Node proxy or proxy to a different server, I can't see what you would gain by having two.
Simply add the required the logging/signing logic to the existing httpsProxy.
Typically, I use https on the proxy to both restrict the number of open ports and to remove the need to do https on all of the Node servers running. You can also add Basic Auth using http-basic library too.
See my example code: https://github.com/TotallyInformation/node-proxy-https-example/blob/master/proxy.js
EDIT 2012-05-15: Hmm, after some thought, I wonder if you shouldn't be looking at something like stunnel to do what you want rather than Node?
(For reference, I've already made some of those points in my answer to your similar question on ServerFault.)
If you are after a MITM proxy (that is, a proxy that can look inside the SSL content by using its own certificates, which can work provided the clients are configured to trust them), it will hardly be fully transparent, since you will at least have to configure its clients to trust its certificates.
In addition, unless all your client use the server name indication extension, the proxy itself will be unable to determine reliably which host to issue its certificate for (something that a normal HTTPS proxy would have been able to know by looking at the CONNECT request issued by the client).
If you're not after a MITM proxy, then you might as well let the initial connection through via your router. If you want to record that traffic, your router might be able to log the encrypted packets.
Having your router catch the SSL/TLS packets to send them transparently to a proxy that will merely end up relaying that traffic untouched anyway to the target server doesn't make much sense. (By nature, the transparent proxy will imply the client isn't configured to know about it, so it won't even send its CONNECT method with which you could have had the requested host and port. Here, you'll really have nothing more than what the router can do.)
EDIT: Once again, you simply won't be able to use an HTTP proxy to analyse the content of the connection transparently. Even when using a normal proxy, an HTTPS connection is relayed straight through to the target server. The SSL/TLS connection itself is established between the original client and the target server. The point of using SSL/TLS is to protect this connection, and to make the client notice if something is trying to look inside the connection.
Plain HTTP transparent proxy servers work because (a) the traffic can be seen (in particular, the request line and the HTTP Host header are visible so that the proxy can know which request to make itself) and (b) the traffic can be altered transparently so that the initial client doesn't notice that the request wasn't direct and works as if it was.
Neither of these conditions are true with HTTPS. HTTPS connections that go through an HTTP proxy are simply tunnel, after explicit request from the client, which has sent a CONNECT command and was configured to make use of such a proxy.
To do something close to what you're after, you'd need an SSL/TLS server that accepts the SSL/TLS connection and deciphers it (perhaps something like STunnel) before your HTTP proxy. However, this won't be transparent, because it won't be able to generate the right certificates.

If you use HTTPS will your URL params will be safe from sniffing? [duplicate]

This question already has answers here:
Is a HTTPS query string secure?
(9 answers)
Closed 9 years ago.
Suppose I setup a simple php web server with a page that can be accessed by HTTPS. The URL has simple parameters, like https://www.example.com/test?abc=123.
Is it true that the parameter here in this case will be safe from people sniffing the packets? And would this be true if the server does not employ any SSL certificate?
Yes your URL would be safe from sniffing; however, one hole that is easily overlooken is if your page references any third party resources such as Google Analytics, Add Content anything, your entire URL will be sent to the third party in the referer. If its really sensitive it doesn't belong in the query string.
As for your second part of the question, you can't use SSL if you don't have a certificate on the server.
http://answers.google.com/answers/threadview/id/758002.html
HTTPS Establishes an underlying SSL
connection before any HTTP data is
transferred. This ensures that all URL
data (with the exception of hostname,
which is used to establish the
connection) is carried solely within
this encrypted connection, and is
protected from man-in-the-middle
attacks in the same way that any HTTPS
data is.
All HTTP-level transactions within an
HTTPS connection are conducted within
the established SSL session, and no
query data is transferred before the
secure connection is established.
From the outside the only data that is
visible to the world is the hostname
and port you are connecting to.
Everything else is simply a stream of
binary data which is encrypted using a
private key shared only between you
and the server.
In the example you provide your
browser would do this:
Derive
hostname (and port if present)
from URL.
Connect to host.
Check certificate (it must be 'signed'
by a known authority, applied specifically
to correct IP address and port, and be
current).
The browser and server
exchange cryptographic data and the
browser receives a private key.
The
HTTP request is made, and encrypted with
established cryptography.
HTTP response is received. Also encrypted.
HTTP is an 'Application Layer'
protocol. It is carried on top of the
secure layer. According to the SSL
specification, drawn up by Netscape,
it dictates that no application layer
data may be transmitted until a secure
connection is established - as
outlined in the following paragraph:
"At this point, a change cipher spec
message is sent by the client, and the
client copies the pending Cipher Spec
into the current Cipher Spec. The
client then immediately sends the
finished message under the new
algorithms, keys, and secrets. In
response, the server will send its own
change cipher spec message, transfer
the pending to the current Cipher
Spec, and send its finished message
under the new Cipher Spec. At this
point, the handshake is complete and
the client and server may begin to
exchange application layer data."
http://wp.netscape.com/eng/ssl3/draft302.txt
So yes. The data contained in the URL
query on an HTTPS connection is
encrypted. However it is very poor
practice to include such sensitive
data as a password in a 'GET'
request. While it cannot be
intercepted, the data would be logged
in plaintext server logs on the
receiving HTTPS server, and quite
possibly also in browser history. It
is probably also available to browser
plugins and possibly even other
applications on the client computer.
At most a HTTPS URL could be
reasonably allowed to include a
session ID or similar non-reusable
variable. It should NEVER contain
static authentication tokens.
The HTTP connection concept is most
clearly explained here:
http://www.ourshop.com/resources/ssl_step1.html
The requested URI (/test?abc=123) is sent to the web server as part of the HTTP request header and thus encrypted.
However URLs can leak in other ways, usually web browser toolbars, bookmarks, and sending links to friends. POSTing data may be more appropriate depending on the context/sensitivity of the data you're sending.
I believe an HTTPS connection requires an SSL certificate, even a self-generated one if you don't want to buy one.
Hope that helps a bit!
depends on what you mean by safe
SSL encrypts the entire HTTP request/response, so the URL in the GET portion will be encrypted. This does not stop MITM attacks and corruption of the integrity of the SSL session itself. If a non-authoritative certificate is used, this makes potential attack vectors simpler.
Are REST request headers encrypted by SSL?
Is a similar question.
The url:s will be stored both in the server logs and in the browser history so even if they aren't sniffable they are far from safe.
On the wire, yes. At the end points (browser and server) not necessarily. SSL/TLS is transport layer security. It will encrypt your traffic between the browser and the server. It is possible on the browser-side to peek at the data (a BHO for example). Once it reaches the server-side, it is available to the recipient of course and is only as secure as he treats it. If the data needs to move securely beyond the initial exchange and protected from prying eyes on the client, you should also look at message layer security.
The SSL/TSL is a Transport Layer Security, yes the data can be picked with BHO (as #JP wrote) or any add on but also with "out of browser" HTTP sniffers. They read messaging between winsock32 and the application. The encryption takes place in the winsock32 not in the browser.
Take a look (this part was taked from the page of IEinspector):
IEInspector HTTP Analyzer is such a handy tool that allows you to monitor, trace, debug and analyze HTTP/HTTPS traffic in real-time.

How long does SSL connection between a client and a server persist?

I've just started learning SSL and boy is it confusing
Q1 - How long does SSL connection between a client and server persist? Until client surfs to some other URL or…?
Q2
A) Assume a client (browser) establishes a SSL connection with a IIS server.
Now how does IIS figure out on each postback that it is dealing with same authenticated client/browser and thus that it already has a SSL connection established with that client?
B) Assuming SSL connection isn’t lost if browser surfs to some other URL:
Suppose that moments after SSL connection is established, client surfs to some other URL, and shortly there after it again requests ( via https ) the original page ( one with which it has SSL connection established).
How will IIS server be able to figure out that current request for a page comes from a client that already has SSL connection established with that page and thus will use already established SSL connection?
thanx
EDIT:
Assuming browser surfs to some other URL and if on returning back to original page the SSL connection is still established, how will browser "remember" the value of symetric encryption key, which the two sides used for communicating?
I realize it depends on what browser you use, but with IE and Firefox, I assume when you close a browser, it sends Connection.Close() ( or something to that effect ) to the server and thus SSL connection is immediately closed?
But if you browse away to some other URL, then if browsers doesn't send any notification to the server, wouldn't then SSL connection remain established for quite some time ( even 10 or more minutes ) and thus browser could easily surf back to that page as if nothing happened?!
I appreciate it
Q1. The SSL connection is only good for a single TCP connection between the client and the server. Current browsers (anything with HTTP/1.1 support) can reuse a single connection for downloading multiple resources. Current browsers also make multiple TCP connections to a server in order to download multiple resources in parallel. Because of this, you'll see multiple SSL connections for one page view.
Q2A. If the browser still has a TCP connection open with that server, it can reuse that connection. Otherwise, a new TCP connection with SSL and IIS authentication is negotiated.
Q2B. Same as Q2A. You can't depend on this, but the TCP connections won't be disposed of immediately. There's a chance you could reuse an existing one depending on your browser.
A1. An SSL connection persists until either the client or server closes it. When that happens depends on the protocol being used. For HTTP, most modern clients will make a few parallel connections to the server to fetch the page and its resources, and reuse those connections until the page is loaded.
A2A. The client must authenticate itself on each request if the authentication uses HTTP auth. If the client is using SSL certificate authorization, then this is obviously maintained on a per-connection basis so that subsequent requests on the same connection retain the same credentials.
A2B. The server would know this because presumably the request would come in on that already established SSL connection.
post-edit answers:
What I think you may be missing is that SSL is linked intrinsically to TCP. You cannot have an SSL "connection" to the server that doesn't ride on top of a TCP connection. You break one, you break the other.
Most SSL implementations include "shortcut" negotiation where subsequent new connections can leverage the public key encryption that has already taken place and instead directly use the most recently negotiated symmetric key. The details of this, however, are hidden within the SSL implementation. From the point of view of the user and/or client software, the fiction is maintained that the entire negotiation took place just like it did on the first connection.
If the SSL connection is still established, then it follows that the symmetric key information is still maintained on both ends.
Yes.
Yes, although it would be improbable for the client to keep a connection to a server once it has navigated away to some other site.

Resources