Improved TLS error handling and teach getpeerinfo about cipher of each connection
This commit is contained in:
@@ -11,6 +11,9 @@
|
|||||||
#include "utiltls.h"
|
#include "utiltls.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
// store our preferred cipherlist so we can use it for debug/etc later on
|
||||||
|
std::string TLS_CIPHERLIST;
|
||||||
|
|
||||||
namespace hush
|
namespace hush
|
||||||
{
|
{
|
||||||
static WOLFSSL_EVP_PKEY *mykey;
|
static WOLFSSL_EVP_PKEY *mykey;
|
||||||
@@ -229,6 +232,7 @@ WOLFSSL* TLSManager::connect(SOCKET hSocket, const CAddress& addrConnect, unsign
|
|||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
bConnectedTLS = true;
|
bConnectedTLS = true;
|
||||||
} else {
|
} else {
|
||||||
|
err_code = wolfSSL_ERR_get_error();
|
||||||
LogPrint("tls", "%s: timed out waiting for %s\n", __func__, addrConnect.ToString());
|
LogPrint("tls", "%s: timed out waiting for %s\n", __func__, addrConnect.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +246,11 @@ WOLFSSL* TLSManager::connect(SOCKET hSocket, const CAddress& addrConnect, unsign
|
|||||||
LogPrintf("TLS: connection to %s has been established (tlsv = %s 0x%04x / ssl = %s 0x%x ). Using cipher: %s\n",
|
LogPrintf("TLS: connection to %s has been established (tlsv = %s 0x%04x / ssl = %s 0x%x ). Using cipher: %s\n",
|
||||||
addrConnect.ToString(), wolfSSL_get_version(ssl), wolfSSL_version(ssl), wolfSSL_OpenSSL_version(), wolfSSL_lib_version_hex(), wolfSSL_get_cipher_name(ssl));
|
addrConnect.ToString(), wolfSSL_get_version(ssl), wolfSSL_version(ssl), wolfSSL_OpenSSL_version(), wolfSSL_lib_version_hex(), wolfSSL_get_cipher_name(ssl));
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("TLS: %s: %s():%d - TLS connection to %s timed out\n", __FILE__, __func__, __LINE__, addrConnect.ToString(), err_code);
|
if(err_code) {
|
||||||
|
LogPrintf("TLS: %s: %s():%d - TLS connection to %s failed with err_code=0x%X\n", __FILE__, __func__, __LINE__, addrConnect.ToString(), err_code);
|
||||||
|
} else {
|
||||||
|
LogPrintf("TLS: %s: %s():%d - TLS connection to %s timed out\n", __FILE__, __func__, __LINE__, addrConnect.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
wolfSSL_free(ssl);
|
wolfSSL_free(ssl);
|
||||||
@@ -270,7 +278,7 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bInitialized = false;
|
bool bInitialized = false;
|
||||||
WOLFSSL_CTX* tlsCtx = NULL;
|
WOLFSSL_CTX* tlsCtx = NULL;
|
||||||
|
|
||||||
byte *pem;
|
byte *pem;
|
||||||
@@ -279,7 +287,7 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType)
|
|||||||
if ((tlsCtx = wolfSSL_CTX_new(ctxType == SERVER_CONTEXT ? wolfTLSv1_3_server_method() : wolfTLSv1_3_client_method()))) {
|
if ((tlsCtx = wolfSSL_CTX_new(ctxType == SERVER_CONTEXT ? wolfTLSv1_3_server_method() : wolfTLSv1_3_client_method()))) {
|
||||||
wolfSSL_CTX_set_mode(tlsCtx, SSL_MODE_AUTO_RETRY);
|
wolfSSL_CTX_set_mode(tlsCtx, SSL_MODE_AUTO_RETRY);
|
||||||
|
|
||||||
// Disable TLS < 1.3 ... imho redundant, because v1.3 is required via method
|
// Disable TLS < 1.3, just in case
|
||||||
int ret = wolfSSL_CTX_set_min_proto_version(tlsCtx, TLS1_3_VERSION);
|
int ret = wolfSSL_CTX_set_min_proto_version(tlsCtx, TLS1_3_VERSION);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
LogPrintf("TLS: WARNING: %s: %s():%d - failed to set min TLS version\n", __FILE__, __func__, __LINE__);
|
LogPrintf("TLS: WARNING: %s: %s():%d - failed to set min TLS version\n", __FILE__, __func__, __LINE__);
|
||||||
@@ -293,12 +301,15 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType)
|
|||||||
if(GetRand(100) > 50) {
|
if(GetRand(100) > 50) {
|
||||||
if (wolfSSL_CTX_set_cipher_list(tlsCtx, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256")) {
|
if (wolfSSL_CTX_set_cipher_list(tlsCtx, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256")) {
|
||||||
LogPrintf("%s: Preferring TLS_AES256-GCM-SHA384\n", __func__);
|
LogPrintf("%s: Preferring TLS_AES256-GCM-SHA384\n", __func__);
|
||||||
|
TLS_CIPHERLIST = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256";
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("%s: Setting preferred cipher failed !!!\n", __func__);
|
LogPrintf("%s: Setting preferred cipher failed !!!\n", __func__);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (wolfSSL_CTX_set_cipher_list(tlsCtx, "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384")) {
|
if (wolfSSL_CTX_set_cipher_list(tlsCtx, "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384")) {
|
||||||
LogPrintf("%s: Preferring TLS_AES256-GCM-SHA384\n", __func__);
|
LogPrintf("%s: Preferring TLS_XCHACHA20_POLY1305\n", __func__);
|
||||||
|
// WolfSSL 4.6.0 added xchacha but calls it the same ciphersuite, which causes compatibility issues
|
||||||
|
TLS_CIPHERLIST = "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384";
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("%s: Setting preferred cipher failed !!!\n", __func__);
|
LogPrintf("%s: Setting preferred cipher failed !!!\n", __func__);
|
||||||
}
|
}
|
||||||
@@ -359,11 +370,10 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType)
|
|||||||
*/
|
*/
|
||||||
bool TLSManager::prepareCredentials()
|
bool TLSManager::prepareCredentials()
|
||||||
{
|
{
|
||||||
mykey = NULL;
|
mykey = NULL;
|
||||||
mycert = NULL;
|
mycert = NULL;
|
||||||
|
|
||||||
// Generating key and the self-signed certificate for it
|
// Generating key and the self-signed certificate for it
|
||||||
//
|
|
||||||
mykey = GenerateEcKey();
|
mykey = GenerateEcKey();
|
||||||
if (mykey) {
|
if (mykey) {
|
||||||
mycert = GenerateCertificate(mykey);
|
mycert = GenerateCertificate(mykey);
|
||||||
@@ -579,15 +589,12 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds
|
|||||||
__FILE__, __func__, __LINE__, error_str);
|
__FILE__, __func__, __LINE__, error_str);
|
||||||
}
|
}
|
||||||
// socket closed gracefully (peer disconnected)
|
// socket closed gracefully (peer disconnected)
|
||||||
//
|
|
||||||
if (!pnode->fDisconnect)
|
if (!pnode->fDisconnect)
|
||||||
LogPrint("tls", "socket closed (%s)\n", pnode->addr.ToString());
|
LogPrint("tls", "socket closed (%s)\n", pnode->addr.ToString());
|
||||||
pnode->CloseSocketDisconnect();
|
pnode->CloseSocketDisconnect();
|
||||||
|
|
||||||
|
|
||||||
} else if (nBytes < 0) {
|
} else if (nBytes < 0) {
|
||||||
// error
|
// error
|
||||||
//
|
|
||||||
if (bIsSSL) {
|
if (bIsSSL) {
|
||||||
if (nRet != WOLFSSL_ERROR_WANT_READ && nRet != WOLFSSL_ERROR_WANT_WRITE)
|
if (nRet != WOLFSSL_ERROR_WANT_READ && nRet != WOLFSSL_ERROR_WANT_WRITE)
|
||||||
{
|
{
|
||||||
@@ -602,7 +609,6 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// preventive measure from exhausting CPU usage
|
// preventive measure from exhausting CPU usage
|
||||||
//
|
|
||||||
MilliSleep(1); // 1 msec
|
MilliSleep(1); // 1 msec
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -617,9 +623,7 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Send
|
// Send
|
||||||
//
|
|
||||||
if (sendSet) {
|
if (sendSet) {
|
||||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||||
if (lockSend)
|
if (lockSend)
|
||||||
@@ -640,17 +644,13 @@ bool TLSManager::initialize()
|
|||||||
bool bInitializationStatus = false;
|
bool bInitializationStatus = false;
|
||||||
|
|
||||||
// Initialization routines for the WolfSSL library
|
// Initialization routines for the WolfSSL library
|
||||||
//
|
|
||||||
wolfSSL_load_error_strings();
|
wolfSSL_load_error_strings();
|
||||||
wolfSSL_ERR_load_crypto_strings();
|
wolfSSL_ERR_load_crypto_strings();
|
||||||
wolfSSL_library_init();
|
wolfSSL_library_init();
|
||||||
|
|
||||||
// Initialization of the server and client contexts
|
// Initialization of the server and client contexts
|
||||||
//
|
if ((tls_ctx_server = TLSManager::initCtx(SERVER_CONTEXT))) {
|
||||||
if ((tls_ctx_server = TLSManager::initCtx(SERVER_CONTEXT)))
|
if ((tls_ctx_client = TLSManager::initCtx(CLIENT_CONTEXT))) {
|
||||||
{
|
|
||||||
if ((tls_ctx_client = TLSManager::initCtx(CLIENT_CONTEXT)))
|
|
||||||
{
|
|
||||||
LogPrint("tls", "TLS: contexts are initialized\n");
|
LogPrint("tls", "TLS: contexts are initialized\n");
|
||||||
bInitializationStatus = true;
|
bInitializationStatus = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -577,8 +577,8 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
|
|||||||
CNodeState *state = State(nodeid);
|
CNodeState *state = State(nodeid);
|
||||||
if (state == NULL)
|
if (state == NULL)
|
||||||
return false;
|
return false;
|
||||||
stats.nMisbehavior = state->nMisbehavior;
|
stats.nMisbehavior = state->nMisbehavior;
|
||||||
stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->GetHeight() : -1;
|
stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->GetHeight() : -1;
|
||||||
stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->GetHeight() : -1;
|
stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->GetHeight() : -1;
|
||||||
BOOST_FOREACH(const QueuedBlock& queue, state->vBlocksInFlight) {
|
BOOST_FOREACH(const QueuedBlock& queue, state->vBlocksInFlight) {
|
||||||
if (queue.pindex)
|
if (queue.pindex)
|
||||||
|
|||||||
48
src/net.cpp
48
src/net.cpp
@@ -394,8 +394,7 @@ CNode* FindNode(const CService& addr)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
CNode* ConnectNode(CAddress addrConnect, const char *pszDest) {
|
||||||
{
|
|
||||||
if (pszDest == NULL) {
|
if (pszDest == NULL) {
|
||||||
if (IsLocal(addrConnect))
|
if (IsLocal(addrConnect))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -429,7 +428,6 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
|||||||
|
|
||||||
WOLFSSL *ssl = NULL;
|
WOLFSSL *ssl = NULL;
|
||||||
|
|
||||||
#ifdef USE_TLS
|
|
||||||
/* TCP connection is ready. Do client side SSL. */
|
/* TCP connection is ready. Do client side SSL. */
|
||||||
unsigned long err_code = 0;
|
unsigned long err_code = 0;
|
||||||
ssl = tlsmanager.connect(hSocket, addrConnect, err_code);
|
ssl = tlsmanager.connect(hSocket, addrConnect, err_code);
|
||||||
@@ -438,11 +436,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
|||||||
CloseSocket(hSocket);
|
CloseSocket(hSocket);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_TLS
|
|
||||||
|
|
||||||
// Add node
|
// Add node
|
||||||
CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false, ssl);
|
CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false, ssl);
|
||||||
|
pnode->tls_cipher = wolfSSL_get_cipher_name(ssl);
|
||||||
pnode->AddRef();
|
pnode->AddRef();
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -619,23 +616,24 @@ void CNode::AddAllowlistedRange(const CSubNet &subnet) {
|
|||||||
|
|
||||||
void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
|
void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
|
||||||
{
|
{
|
||||||
stats.nodeid = this->GetId();
|
stats.nodeid = this->GetId();
|
||||||
stats.nServices = nServices;
|
stats.nServices = nServices;
|
||||||
stats.addr = addr;
|
stats.addr = addr;
|
||||||
// stats.addrBind = addrBind;
|
// stats.addrBind = addrBind;
|
||||||
stats.m_mapped_as = addr.GetMappedAS(m_asmap);
|
stats.m_mapped_as = addr.GetMappedAS(m_asmap);
|
||||||
stats.nLastSend = nLastSend;
|
stats.nLastSend = nLastSend;
|
||||||
stats.nLastRecv = nLastRecv;
|
stats.nLastRecv = nLastRecv;
|
||||||
stats.nTimeConnected = nTimeConnected;
|
stats.nTimeConnected = nTimeConnected;
|
||||||
stats.nTimeOffset = nTimeOffset;
|
stats.nTimeOffset = nTimeOffset;
|
||||||
stats.addrName = addrName;
|
stats.addrName = addrName;
|
||||||
stats.nVersion = nVersion;
|
stats.nVersion = nVersion;
|
||||||
stats.cleanSubVer = cleanSubVer;
|
stats.cleanSubVer = cleanSubVer;
|
||||||
stats.fInbound = fInbound;
|
stats.fInbound = fInbound;
|
||||||
stats.nStartingHeight = nStartingHeight;
|
stats.nStartingHeight = nStartingHeight;
|
||||||
stats.nSendBytes = nSendBytes;
|
stats.nSendBytes = nSendBytes;
|
||||||
stats.nRecvBytes = nRecvBytes;
|
stats.nRecvBytes = nRecvBytes;
|
||||||
stats.fAllowlisted = fAllowlisted;
|
stats.fAllowlisted = fAllowlisted;
|
||||||
|
stats.tls_cipher = tls_cipher;
|
||||||
|
|
||||||
// It is common for nodes with good ping times to suddenly become lagged,
|
// It is common for nodes with good ping times to suddenly become lagged,
|
||||||
// due to a new block arriving or other large transfer.
|
// due to a new block arriving or other large transfer.
|
||||||
@@ -1103,7 +1101,6 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
|
|||||||
|
|
||||||
SetSocketNonBlocking(hSocket, true);
|
SetSocketNonBlocking(hSocket, true);
|
||||||
|
|
||||||
#ifdef USE_TLS
|
|
||||||
/* TCP connection is ready. Do server side TLS */
|
/* TCP connection is ready. Do server side TLS */
|
||||||
unsigned long err_code = 0;
|
unsigned long err_code = 0;
|
||||||
ssl = tlsmanager.accept( hSocket, addr, err_code);
|
ssl = tlsmanager.accept( hSocket, addr, err_code);
|
||||||
@@ -1114,13 +1111,12 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_TLS
|
|
||||||
|
|
||||||
CNode* pnode = new CNode(hSocket, addr, "", true, ssl);
|
CNode* pnode = new CNode(hSocket, addr, "", true, ssl);
|
||||||
pnode->AddRef();
|
pnode->AddRef();
|
||||||
pnode->fAllowlisted = allowlisted;
|
pnode->fAllowlisted = allowlisted;
|
||||||
|
pnode->tls_cipher = wolfSSL_get_cipher_name(ssl);
|
||||||
|
|
||||||
LogPrint("net", "connection from %s accepted\n", addr.ToString());
|
LogPrint("net", "connection from %s accepted using cipher %s\n", addr.ToString(), pnode->tls_cipher);
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_vNodes);
|
LOCK(cs_vNodes);
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ public:
|
|||||||
uint64_t nServices;
|
uint64_t nServices;
|
||||||
bool fTLSEstablished;
|
bool fTLSEstablished;
|
||||||
bool fTLSVerified;
|
bool fTLSVerified;
|
||||||
|
std::string tls_cipher;
|
||||||
int64_t nLastSend;
|
int64_t nLastSend;
|
||||||
int64_t nLastRecv;
|
int64_t nLastRecv;
|
||||||
int64_t nTimeConnected;
|
int64_t nTimeConnected;
|
||||||
@@ -279,8 +280,9 @@ public:
|
|||||||
class CNode
|
class CNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// OpenSSL
|
// TLS via WolfSSL
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
|
std::string tls_cipher;
|
||||||
|
|
||||||
// socket
|
// socket
|
||||||
uint64_t nServices;
|
uint64_t nServices;
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
" \"addrlocal\":\"ip:port\", (string) local address\n"
|
" \"addrlocal\":\"ip:port\", (string) local address\n"
|
||||||
" \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
|
" \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
|
||||||
" \"tls_established\": true:false, (boolean) Status of TLS connection\n"
|
" \"tls_established\": true:false, (boolean) Status of TLS connection\n"
|
||||||
|
" \"tls_verified\": true:false, (boolean) Status of TLS verification\n"
|
||||||
|
" \"tls_cipher\": \"XXX\", (string) TLS cipher used for this connection\n"
|
||||||
" \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
|
" \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
|
||||||
" \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
|
" \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
|
||||||
" \"bytessent\": n, (numeric) The total bytes sent\n"
|
" \"bytessent\": n, (numeric) The total bytes sent\n"
|
||||||
@@ -139,6 +141,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
}
|
}
|
||||||
obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
|
obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
|
||||||
obj.push_back(Pair("tls_established", stats.fTLSEstablished));
|
obj.push_back(Pair("tls_established", stats.fTLSEstablished));
|
||||||
|
obj.push_back(Pair("tls_verified", stats.fTLSVerified));
|
||||||
|
obj.push_back(Pair("tls_cipher", stats.tls_cipher));
|
||||||
obj.push_back(Pair("lastsend", stats.nLastSend));
|
obj.push_back(Pair("lastsend", stats.nLastSend));
|
||||||
obj.push_back(Pair("lastrecv", stats.nLastRecv));
|
obj.push_back(Pair("lastrecv", stats.nLastRecv));
|
||||||
obj.push_back(Pair("bytessent", stats.nSendBytes));
|
obj.push_back(Pair("bytessent", stats.nSendBytes));
|
||||||
|
|||||||
Reference in New Issue
Block a user