SSL证书,不通过thrift认证,但通过浏览器确定 [英] SSL Certificate, not authenticating via thrift, but OK via browser

查看:530
本文介绍了SSL证书,不通过thrift认证,但通过浏览器确定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我生成SSL证书,密钥等的方式:

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.key -out server.csr
openssl x509 -req -days 10000 -in server.csr -signkey new_key.pem -out server.crt

这个工作,我可以看到chrome输出,得到警告,我将首先获得病毒。

This works, i can see the output in chrome, although I get a warning that i'm going to get viruses first.

openssl s_server -cert server.crt -www -key new_key.pem

这是服务器的代码段。我会老实说,我不知道每行都在做什么,虽然我有一个好主意:

this is a snippet from the server. I'll be honest, i'm not sure exactly what every line is doing, though I have a good idea:

socketFactory->server(true); // this is the server
socketFactory->authenticate(false); // no auth?
socketFactory->loadCertificate("server.crt"); 
socketFactory->loadPrivateKey("new_key.pem");

客户:

socketFactory->loadTrustedCertificates("server.crt");
socketFactory->authenticate(true); //auth? wierd, right? This guy does this:[1]

[1] http://permalink.gmane.org/gmane.comp.lib.thrift.user/1651

如果我在客户端注释掉 loadTrustedCertificates ,那么我得到一个SSL未经验证的证书异常。
剩下的那一行,我得到了一个auth失败异常。

If i comment out loadTrustedCertificates in the client, then i get an SSL unverified certificate exception. With that line left in, i get an auth failure exception.

这里有2个更长的代码片段,把上面的代码片段放在更好的角度。 br>
server:

Here are 2 much longer code fragments, that put the above snippets in better perspective.
server:

shared_ptr<SkullduggeryHandler> handler(new SkullduggeryHandler());
shared_ptr<TBufferedTransportFactory> transportFactory =
        shared_ptr<TBufferedTransportFactory>(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
shared_ptr<TProcessor> processor(new SkullduggeryProcessor(handler));
shared_ptr<TSSLSocketFactory> socketFactory = 
      shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
socketFactory->server(true);
socketFactory->authenticate(false);
socketFactory->loadCertificate("server.crt");
socketFactory->loadPrivateKey("new_key.pem");
shared_ptr<TSSLServerSocket> socket(new TSSLServerSocket(port, socketFactory));
TThreadedServer server(processor,
                               socket,
                               transportFactory,
                               protocolFactory);
server.serve();

客户:

shared_ptr <TSSLSocketFactory> socketFactory = shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
socketFactory->loadTrustedCertificates("server.crt");
socketFactory->authenticate(false);
shared_ptr <TSSLSocket>socket = socketFactory->createSocket(configuration.ip, configuration.port);
shared_ptr<TBufferedTransport> transport(new TBufferedTransport(socket));
shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
SkullduggeryClient client(protocol);
transport->open();

感谢您花时间阅读。如果有明显的错误,我很高兴听到它。这是我的存在的痛苦太久了。太长了。

Thanks for taking the time to read this. If there are glaring errors, I'll be glad to hear of it. This has been the bane of my existense for too long now. Too long.

推荐答案

看来你正在生成自签名证书 openssl 实用程序很混乱。

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

第1行可以,它会生成一个私钥。

行2是无用的:输出键与输入键相同! (尝试 diff 两个键来查看)。

第3行生成CSR,第4行实际上是自签名的,因此可以合并

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 :-)

您正在使用SSL来验证和加密Thrift服务器和Thrift客户端之间的通信。我假设你想要两个:

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. 保护客户端免受流氓服务器(你的代码尝试做什么)

  2. 保护服务器免受恶意客户端(这对我来说更为重要)。

类比,(1)是典型的服务器证书,(2)通常是用户的用户名/密码。但是使用Thrift SSL,我们将通过向客户端发出证书来获得相互身份验证。

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.

生成服务器私钥:

openssl genrsa -out server-key.pem 2048

生成关联的公钥并对其进行自签名:

openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000

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

生成客户端私钥:

openssl genrsa -out client-key.pem 2048

生成关联的公钥并自签名:

openssl req -new -x509 -key client-key.pem -out client -cert.pem -days 10000

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

注意:当 openssl req code>通用名称(例如服务器FQDN或YOUR名称),输入Thrift程序将运行的主机的FQDN。这将允许不定制Thrift的 AccessManager 类。如果在另一方面FQDN不能预先知道,需要继承 AccessManager 并覆盖 verify()方法。请参阅 TSSLSocket.cpp

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.

很好,现在代码。

在服务器端:

socketFactory-> server(true); 删除它。

socketFactory-> authenticate(false)有点误导。一个更好的名字应该是 authenticatePeer 。如果你说 false ,它不会验证客户端,但我们在我们想要相互验证之前决定。

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.

,服务器的SSL前导是:

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) {
        ....
    }

其中 myKey server-key.pem myCert server-cert.pem trustedCerts 可信CA的证书,或者在自签名证书的情况下,客户端的证书。您可以在同一个文件中一个接一个地 cat 多个证书。在我们的示例中,我们将放置我们之前创建的 client-cert.pem

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.

客户端是完全相同的,具有正确的客户端私钥,客户端证书,并且 trustedCerts ,对等体的证书: server-cert.pem

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.

这是所有的:-)如果你没有清晰的图片,在跳转到代码之前尝试理解的SSL(互)认证如何工作,很难理解错误消息。我显示的代码经过测试可以工作。

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.

文档化,不幸的是Thrift几乎没什么。对于SSL,您可以看到: lib / cpp / README.SSL test / cpp / src / TestServer.cpp test / cpp / src / TestClient.cpp 。警告, TestServer.cpp 不进行相互验证,这是错误IMHO。

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.

这篇关于SSL证书,不通过thrift认证,但通过浏览器确定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆