SSL Certificate, not authenticating via thrift, but OK via browser

后端 未结 1 1119
野的像风
野的像风 2021-01-02 11:38

This is how I generate my SSL cert, key, etc:

openssl genrsa -out server.key 1024
openssl rsa -in server.key -out new_key.pem
openssl req -new -key server.ke         


        
相关标签:
1条回答
  • 2021-01-02 12:16

    It seems you are generating self-signed certificates (which is fine), but the operations you are making with the openssl utility are confusing.

    Line 1 is OK, it generates a private key.
    Line 2 is useless: the output key is the same as the input key! (Try to diff the two keys to see).
    Line 3 generates a CSR and line 4 actually self-signs it, so they can be merged together in one line as we will see.

    Now, let's take a step back and let's try to understand what we are doing :-)

    You are using SSL to authenticate and encrypt the communication between a Thrift server and a Thrift client. I assume you want to both:

    1. Protect the client from a rogue server (what your code is attempting to do)
    2. Protect the server from a rogue client (which seems even more important to me).

    To make an HTTPS analogy, (1) is the classic server certificate, (2) is normally a username/password for the user. But with Thrift SSL, we will obtain mutual authentication by issuing a certificate also to the client.

    The examples I will make will use self-signed certificates. They can easily be adapted to a mini CA managed by openssl, and I leave this as an exercise to the reader.

    Generate the server private key:
    openssl genrsa -out server-key.pem 2048

    Generate the associated public key and self-sign it:
    openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000

    Generate the client private key:
    openssl genrsa -out client-key.pem 2048

    Generate the associated public key and self-sign it:
    openssl req -new -x509 -key client-key.pem -out client-cert.pem -days 10000

    Note: when openssl req asks for "Common Name (e.g. server FQDN or YOUR name)", put the FQDN of the host on which the Thrift program will run. This will allow not to customize Thrift's AccessManager class. If on the other hand the FQDN can not be known in advance, one needs to inherit AccessManager and override the verify() methods accordingly. See TSSLSocket.cpp.

    Good, now to the code.

    On the server side:

    socketFactory->server(true); is redundant, remove it.

    socketFactory->authenticate(false) is a bit misleading. A better name would have been authenticatePeer. If you say false, it will not authenticate the client, but we decided before we want mutual authentication.

    So, a SSL preamble for a server is:

    try {
        signal(SIGPIPE, SIG_IGN); // See README.SSL
        shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory());
        sslSocketFactory->loadPrivateKey(myKey);
        sslSocketFactory->loadCertificate(myCert);
        sslSocketFactory->authenticate(true);
        sslSocketFactory->loadTrustedCertificates(trustedCerts);
        sslSocketFactory->ciphers("HIGH:!DSS:!aNULL@STRENGTH");
        ...
        } catch (TException& tx) {
            ....
        }
    

    Where myKey is server-key.pem, myCert is server-cert.pem and trustedCerts is... either the cert of a trusted CA, or, in case of a self-signed cert, the cert of the client. You can cat multiple certs one after the other in the same file. In our example, we will put client-cert.pem that we created before.

    A SSL preamble for a client is exactly the same, with the correct client private key, client cert and, for trustedCerts, the cert of the peer: server-cert.pem that we created before.

    That's all :-) Try to understand before jumping to code it, if you don't have a clear picture of how SSL (mutual) authentication works, it is difficult to understand the error messages. The code I showed is tested to work.

    Documentation-wise, unfortunately Thrift is close to nothing. For SSL, you can see: lib/cpp/README.SSL, test/cpp/src/TestServer.cpp and test/cpp/src/TestClient.cpp. Be warned that TestServer.cpp doesn't do mutual authentication, which is an error IMHO.

    0 讨论(0)
提交回复
热议问题