Skip to content

Commit 473059b

Browse files
authored
Added SSL Error Trace Log and mTLS Samples (#222)
1 parent 09f8a20 commit 473059b

File tree

4 files changed

+236
-4
lines changed

4 files changed

+236
-4
lines changed

trantor/net/inner/TcpConnectionImpl.cc

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,19 @@ std::shared_ptr<SSLContext> newSSLServerContext(
321321
throw std::runtime_error("SSL_CTX_check_private_key error");
322322
}
323323

324+
if (!SSL_CTX_set_ecdh_auto(ctx->get(), 1))
325+
{
326+
LOG_TRACE << "Failed to set_ecdh_auto, set_ecdh_auto DISABLED";
327+
}
328+
else
329+
{
330+
LOG_TRACE << "set_ecdh_auto ENABLED";
331+
}
332+
324333
if (!caPath.empty())
325334
{
326335
auto checkCA =
327336
SSL_CTX_load_verify_locations(ctx->get(), caPath.c_str(), NULL);
328-
LOG_DEBUG << "CA CHECK LOC: " << checkCA;
329337
if (checkCA)
330338
{
331339
STACK_OF(X509_NAME) *cert_names =
@@ -335,6 +343,7 @@ std::shared_ptr<SSLContext> newSSLServerContext(
335343
SSL_CTX_set_client_CA_list(ctx->get(), cert_names);
336344
}
337345
ctx->mtlsEnabled = true;
346+
LOG_TRACE << "mTLS session ENABLED";
338347
}
339348
else
340349
{
@@ -2005,6 +2014,17 @@ bool TcpConnectionImpl::validatePeerCertificate()
20052014
}
20062015
}
20072016

2017+
std::string TcpConnectionImpl::getOpenSSLErrorStack()
2018+
{
2019+
BIO *bio = BIO_new(BIO_s_mem());
2020+
ERR_print_errors(bio);
2021+
char *buf;
2022+
size_t len = BIO_get_mem_data(bio, &buf);
2023+
std::string ret(buf, len);
2024+
BIO_free(bio);
2025+
return ret;
2026+
}
2027+
20082028
void TcpConnectionImpl::doHandshaking()
20092029
{
20102030
assert(sslEncryptionPtr_->statusOfSSL_ == SSLStatus::Handshaking);
@@ -2013,8 +2033,9 @@ void TcpConnectionImpl::doHandshaking()
20132033
LOG_TRACE << "hand shaking: " << r;
20142034
if (r == 1)
20152035
{
2016-
// Clients don't commonly have certificates. Let's not validate
2017-
// that
2036+
// Clients don't commonly have certificates (except on mTLS).
2037+
// So if the SSL session is on server-side and without mTLS enabled,
2038+
// let's not validate the client certificate.
20182039
if (validateCert_ && (!sslEncryptionPtr_->isServer_ ||
20192040
sslEncryptionPtr_->sslPtr_->mtlsEnabled))
20202041
{
@@ -2059,8 +2080,8 @@ void TcpConnectionImpl::doHandshaking()
20592080
}
20602081
else
20612082
{
2062-
// ERR_print_errors(err);
20632083
LOG_TRACE << "SSL handshake err: " << err;
2084+
LOG_TRACE << "SSL error stack: " << getOpenSSLErrorStack();
20642085
ioChannelPtr_->disableReading();
20652086
sslEncryptionPtr_->statusOfSSL_ = SSLStatus::DisConnected;
20662087
if (sslErrorCallback_)

trantor/net/inner/TcpConnectionImpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ class TcpConnectionImpl : public TcpConnection,
370370
private:
371371
void doHandshaking();
372372
bool validatePeerCertificate();
373+
std::string getOpenSSLErrorStack();
373374
struct SSLEncryption
374375
{
375376
SSLStatus statusOfSSL_ = SSLStatus::Handshaking;

trantor/tests/MTLSClient.cc

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/**
2+
*
3+
* # Generate CA file
4+
* openssl req -new -x509 -days 365 -keyout ca-key.pem -out ca-crt.pem
5+
*
6+
* # Generate Key File (ie: same for client and server, but you can create one
7+
* for each one) openssl genrsa -out server-key.pem 4096
8+
*
9+
* # Generate Server certificate:
10+
* openssl req -new -sha256 -key server-key.pem -out ca-csr.pem
11+
* openssl x509 -req -days 365 -in ca-csr.pem -CA ca-crt.pem -CAkey ca-key.pem
12+
* -CAcreateserial -out server-crt.pem openssl verify -CAfile ca-crt.pem
13+
* server-crt.pem
14+
*
15+
*
16+
* # For client (to specify a certificate client mode only - no domain):
17+
* # Create file client_cert_ext.cnf:
18+
* cat client_cert_ext.cnf
19+
*
20+
* keyUsage = critical, digitalSignature, keyEncipherment
21+
* extendedKeyUsage = clientAuth
22+
* basicConstraints = critical, CA:FALSE
23+
* authorityKeyIdentifier = keyid,issuer
24+
* subjectAltName = DNS:Client
25+
*
26+
* Create client cert (using the same serve key and CA)
27+
* openssl x509 -req -in ca-csr.pem -days 1000 -CA ca-crt.pem -CAkey ca-key.pem
28+
* -set_serial 01 -extfile client_cert_ext.cnf > client-crt.pem
29+
*
30+
* openssl verify -CAfile ca-crt.pem client-crt.pem
31+
* openssl x509 -in client-crt.pem -text -noout -purpose
32+
*
33+
* # Compile sample:
34+
*
35+
* g++ -o MTLSClient MTLSClient.cc -ltrantor -lssl -lcrypto -lpthread
36+
*
37+
* # Tests
38+
*
39+
* # Listen generic SSL server
40+
* openssl s_server -accept 8888 -CAfile ./ca-crt.pem -cert ./server-crt.pem
41+
* -key ./server-key.pem -state
42+
*
43+
* # Listen generic SSL server with mTLS verification
44+
* openssl s_server -accept 8888 -CAfile ./ca-crt.pem -cert ./server-crt.pem
45+
* -key ./server-key.pem -state -verify_return_error -Verify 1
46+
*
47+
* # Test the mTLS client bin
48+
* ./MTLSClient
49+
*
50+
* **/
51+
52+
#include <trantor/net/TcpClient.h>
53+
#include <trantor/utils/Logger.h>
54+
#include <trantor/net/EventLoopThread.h>
55+
#include <string>
56+
#include <iostream>
57+
#include <atomic>
58+
using namespace trantor;
59+
#define USE_IPV6 0
60+
int main()
61+
{
62+
trantor::Logger::setLogLevel(trantor::Logger::kTrace);
63+
LOG_DEBUG << "TcpClient class test!";
64+
EventLoop loop;
65+
#if USE_IPV6
66+
InetAddress serverAddr("::1", 8888, true);
67+
#else
68+
InetAddress serverAddr("127.0.0.1", 8888);
69+
#endif
70+
std::shared_ptr<trantor::TcpClient> client[10];
71+
std::atomic_int connCount;
72+
connCount = 1;
73+
for (int i = 0; i < connCount; ++i)
74+
{
75+
client[i] = std::make_shared<trantor::TcpClient>(&loop,
76+
serverAddr,
77+
"tcpclienttest");
78+
std::vector<std::pair<std::string, std::string>> sslcmd = {};
79+
// That key is common for client and server
80+
// The CA file must be the client CA, for this sample the CA is common
81+
// for both
82+
client[i]->enableSSL(false,
83+
false,
84+
"localhost",
85+
sslcmd,
86+
"./client-crt.pem",
87+
"./server-key.pem",
88+
"./ca-crt.pem");
89+
client[i]->setConnectionCallback(
90+
[i, &loop, &connCount](const TcpConnectionPtr &conn) {
91+
if (conn->connected())
92+
{
93+
LOG_DEBUG << i << " connected!";
94+
char tmp[20];
95+
sprintf(tmp, "%d client!!", i);
96+
conn->send(tmp);
97+
}
98+
else
99+
{
100+
LOG_DEBUG << i << " disconnected";
101+
--connCount;
102+
if (connCount == 0)
103+
loop.quit();
104+
}
105+
});
106+
client[i]->setMessageCallback(
107+
[](const TcpConnectionPtr &conn, MsgBuffer *buf) {
108+
LOG_DEBUG << std::string(buf->peek(), buf->readableBytes());
109+
buf->retrieveAll();
110+
conn->shutdown();
111+
});
112+
client[i]->connect();
113+
}
114+
loop.loop();
115+
}

trantor/tests/MTLSServer.cc

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
*
3+
* # Generate CA file
4+
* openssl req -new -x509 -days 365 -keyout ca-key.pem -out ca-crt.pem
5+
*
6+
* # Generate Key File (ie: same for client and server, but you can create one
7+
* for each one) openssl genrsa -out server-key.pem 4096
8+
*
9+
* # Generate Server certificate:
10+
* openssl req -new -sha256 -key server-key.pem -out ca-csr.pem
11+
* openssl x509 -req -days 365 -in ca-csr.pem -CA ca-crt.pem -CAkey ca-key.pem
12+
* -CAcreateserial -out server-crt.pem openssl verify -CAfile ca-crt.pem
13+
* server-crt.pem
14+
*
15+
*
16+
* # For client (to specify a certificate client mode only - no domain):
17+
* # Create file client_cert_ext.cnf:
18+
* cat client_cert_ext.cnf
19+
*
20+
* keyUsage = critical, digitalSignature, keyEncipherment
21+
* extendedKeyUsage = clientAuth
22+
* basicConstraints = critical, CA:FALSE
23+
* authorityKeyIdentifier = keyid,issuer
24+
* subjectAltName = DNS:Client
25+
*
26+
* Create client cert (using the same serve key and CA)
27+
* openssl x509 -req -in ca-csr.pem -days 1000 -CA ca-crt.pem -CAkey ca-key.pem
28+
* -set_serial 01 -extfile client_cert_ext.cnf > client-crt.pem
29+
*
30+
* openssl verify -CAfile ca-crt.pem client-crt.pem
31+
* openssl x509 -in client-crt.pem -text -noout -purpose
32+
*
33+
* # Compile sample:
34+
*
35+
* g++ -o MTLSServer MTLSServer.cc -ltrantor -lssl -lcrypto -lpthread
36+
*
37+
* # Tests
38+
*
39+
* # Should Fail
40+
* openssl s_client -connect 0.0.0.0:8888 -state
41+
*
42+
* # Should Connect (the CA file must be the server CA), for this sample the CA
43+
* is common for both openssl s_client -connect 0.0.0.0:8888 -key
44+
* ./server-key.pem -cert ./server-crt.pem -CAfile ./ca-crt.pem -state
45+
*
46+
* **/
47+
48+
#include <trantor/net/TcpServer.h>
49+
#include <trantor/utils/Logger.h>
50+
#include <trantor/net/EventLoopThread.h>
51+
#include <string>
52+
#include <iostream>
53+
using namespace trantor;
54+
#define USE_IPV6 0
55+
int main()
56+
{
57+
LOG_DEBUG << "test start";
58+
Logger::setLogLevel(Logger::kTrace);
59+
EventLoopThread loopThread;
60+
loopThread.run();
61+
#if USE_IPV6
62+
InetAddress addr(8888, true, true);
63+
#else
64+
InetAddress addr(8888);
65+
#endif
66+
TcpServer server(loopThread.getLoop(), addr, "test");
67+
std::vector<std::pair<std::string, std::string>> sslcmd = {};
68+
69+
// the CA file must be the client CA, for this sample the CA is common for
70+
// both
71+
server.enableSSL(
72+
"server-crt.pem", "server-key.pem", false, sslcmd, "ca-crt.pem");
73+
server.setRecvMessageCallback(
74+
[](const TcpConnectionPtr &connectionPtr, MsgBuffer *buffer) {
75+
// LOG_DEBUG<<"recv callback!";
76+
std::cout << std::string(buffer->peek(), buffer->readableBytes());
77+
connectionPtr->send(buffer->peek(), buffer->readableBytes());
78+
buffer->retrieveAll();
79+
connectionPtr->forceClose();
80+
});
81+
server.setConnectionCallback([](const TcpConnectionPtr &connPtr) {
82+
if (connPtr->connected())
83+
{
84+
LOG_DEBUG << "New connection";
85+
connPtr->send("Hello world\r\n");
86+
}
87+
else if (connPtr->disconnected())
88+
{
89+
LOG_DEBUG << "connection disconnected";
90+
}
91+
});
92+
server.setIoLoopNum(3);
93+
server.start();
94+
loopThread.wait();
95+
}

0 commit comments

Comments
 (0)