0

I followed the instructions in this blog post, but when I test it with curl, nginx's $ssl_client_verify variable is always NONE. In fact, curl doesn't even give different output when I don't specify the --cert and --key options at all. It's as if it's ignoring my certs. How can I debug this?

I even tried making it so all of these places have the same value:

  • The Common Name on the CA and Server certs
  • The Server's hostname
  • NginX's virtual host name
  • The server's reverse DNS name
Nick Retallack
  • 151
  • 2
  • 8

2 Answers2

2

If by "Common Name" in CA and Server certs you mean the entire Subject name, which can contain other items besides Common Name although most people doing ad-hoc SSL certs like this don't bother with them, is the same -- don't do that. OpenSSL, which both nginx and curl use, cannot chain a child cert to a parent that has the same name; this is not a normal case in X.509 and may not be handled at least in general in other software either.

  • The CA cert should have as Subject (which automatically is also Issuer, since this is a root, see below) a name which is a name for the CA -- this doesn't need to be a domain name, but can be if you like.
  • The (SSL) server req and cert should have as Subject.CommonName the domain name of the server, which can be a wildcard if the server has multiple but closely related domain names, or the IP address if all clients will access by address (which in practice works only if the clients are all your very close coworkers or friends). The Issuer name in the server cert is automatically set to the CA name.
  • Similarly the/each client req and cert should have a Subject name different from the CA name, and Issuer becomes the CA name. If you want the client certs to securely identify the clients, which is presumably the purpose of this exercize, each client cert should have a name different from every other client cert, and preferably different from the server cert to avoid confusion.

With that I believe it should work. A more basic and probably better test tool is openssl commandline:

openssl s_client -connect $addr:$port -cert $clicert -key $clikey -CAfile $cacert 

which will output detailed information about the (attempted) SSL/TLS connection. If fairly near the end it says Acceptable client certificate CA names followed by the correct name of your CA, the server is setup correctly for client auth (as well as basic SSL). If it has some other name, or says No client certificate CA names sent, something is wrong. When s_client waits for input just enter EOF (Unix usually ^D, Windows ^Z).

Aside: the website is wrong to say signing the server request with your self-created ad-hoc CA key&cert is "self signing". Self-signing is specifically signing a cert with the same keypair whose public half is in that cert; in practice this is used only of a toplevel CA, called a "root". You are signing your server cert with your own CA, but you are not self-signing. Signing your server cert with your own CA is bad if you want to handle connections from strangers because it doesn't provide them any evidence to trust your server the way a "commercial" server cert from a well-known CA like Verisign or GoDaddy does. That is commonly the case for production as opposed to test, since test is often used only by developers and/or few beta testers, but some production systems can also be limited to few closely-related clients.

EDIT: getting ad-hoc CA (for client certs) signed by well-known CA: this would be difficult and expensive and is not necessary.

If a well-known CA gives you a "sub-CA" or "intermediate CA" cert allowing you to issue certs, they are betting the future of their business on your security -- so either you must provide security at the same level they do (custom hardware, specialized buildings, armed guards around the clock, multiple specially trained and certified personnel, regular external audits -- all expensive) or you have to buy out their business (so they are no longer at risk). In addition to your https://security.stackexchange.com/questions/25551/help-understanding-client-certificate-verification see:

But the only systems that need to trust the certs you issue your clients are your own servers; as long as you control your own servers you just configure them to trust your own CA cert.

dave_thompson_085
  • 3,262
  • 1
  • 16
  • 16
  • Shortly before you posted this, I got things working, but only with ```openssl s_client```. ```curl``` is still not sending the cert, even with the same arguments. I'm currently not passing ```-CAfile``` to either. Perhaps I have to specify the CA to curl? Also maybe I am experiencing this problem: http://curl.haxx.se/mail/archive-2013-10/0036.html . I am on OSX Mavericks, after all. Btw, I got it working by following instructions here http://security.stackexchange.com/questions/25551/help-understanding-client-certificate-verification and making the CNs all different domain-like names. – Nick Retallack Sep 04 '14 at 09:27
  • This would all still work if I used a server cert from a well-known CA instead of one that has anything to do with the CA I'm using for my client certificates, right? – Nick Retallack Sep 04 '14 at 09:32
  • Btw, by Common Name I did mean the CN, though after following the instructions on the other link I mentioned I guess it's also the DN now, since they do not specify any other items. – Nick Retallack Sep 04 '14 at 09:35
  • Would there be any purpose to getting my client CA signed by a well-known CA? Or is that one fine being self-signed? – Nick Retallack Sep 04 '14 at 09:38
  • @Nick You've added that your `curl` was an Apple/Mavericks one about which I can't comment, but using the "normal" openssl-based `curl` it needs `-CAfile` if (1) the server uses a cert under a root which is not in the client's default truststore -- apparently true in your case for now AND (2) you don't override with `-k` -- which the nategood instructions do. ... – dave_thompson_085 Sep 05 '14 at 07:21
  • ... Yes, obtaining and using a server cert from a well-known CA has no effect on your client certs and client auth, and is much better if you want to support what I call "stranger" clients, that is clients other than those you more or less control such as people in your workgroup or a small number of known-in-advance applications in other parts of your company. security 25551 on quick reading appears to be a more complicated version of the nategood instructions, so doing that with distinct DNs -- of which different CNs is a simple and easy case -- should be good. ... – dave_thompson_085 Sep 05 '14 at 07:25
  • ... "get CA signed by well-known CA" see edit – dave_thompson_085 Sep 05 '14 at 07:59
0

Yep, it's Mavericks.

The -E/--cert option also broke.

If I install curl with brew and specify the --openssl build option, it works.

Nick Retallack
  • 151
  • 2
  • 8