Exclusively TLS connections at p2p layer; dump peers more often
This commit is contained in:
275
src/net.cpp
275
src/net.cpp
@@ -3,7 +3,6 @@
|
||||
// Copyright (c) 2016-2020 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
@@ -18,7 +17,6 @@
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
@@ -45,8 +43,9 @@
|
||||
#include <hush/tlsmanager.cpp>
|
||||
using namespace hush;
|
||||
|
||||
// Dump addresses to peers.dat every 15 minutes (900s)
|
||||
#define DUMP_ADDRESSES_INTERVAL 900
|
||||
// Dump addresses to peers.dat every 5 minutes (300s)
|
||||
// Satoshi originally used 10 seconds(!), did he know something Peter Wuille didn't?
|
||||
#define DUMP_ADDRESSES_INTERVAL 300
|
||||
|
||||
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
|
||||
#define MSG_NOSIGNAL 0
|
||||
@@ -63,20 +62,20 @@ using namespace hush;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USE_TLS
|
||||
#define USE_TLS "encrypted as fuck"
|
||||
|
||||
#if defined(USE_TLS) && !defined(TLS1_3_VERSION)
|
||||
// minimum secure protocol is 1.3
|
||||
// TLS1_3_VERSION is defined in openssl/tls1.h
|
||||
#error "ERROR: Your WolfSSL version does not support TLS v1.3"
|
||||
#error "ERROR: Your WolfSSL version does not support TLS v1.3!!!"
|
||||
#endif
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
//TODO: Make these CLI args
|
||||
const int MAX_OUTBOUND_CONNECTIONS = 64;
|
||||
const int MAX_INBOUND_FROMIP = 3;
|
||||
const int MAX_INBOUND_FROMIP = 3;
|
||||
|
||||
struct ListenSocket {
|
||||
SOCKET socket;
|
||||
@@ -86,9 +85,7 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Global state variables
|
||||
//
|
||||
extern uint16_t ASSETCHAINS_P2PPORT;
|
||||
extern char SMART_CHAIN_SYMBOL[65];
|
||||
|
||||
@@ -141,12 +138,6 @@ static bool operator==(_NODE_ADDR a, _NODE_ADDR b)
|
||||
return (a.ipAddr == b.ipAddr);
|
||||
}
|
||||
|
||||
static std::vector<NODE_ADDR> vNonTLSNodesInbound;
|
||||
static CCriticalSection cs_vNonTLSNodesInbound;
|
||||
|
||||
static std::vector<NODE_ADDR> vNonTLSNodesOutbound;
|
||||
static CCriticalSection cs_vNonTLSNodesOutbound;
|
||||
|
||||
void AddOneShot(const std::string& strDest)
|
||||
{
|
||||
LOCK(cs_vOneShots);
|
||||
@@ -359,7 +350,7 @@ void AddressCurrentlyConnected(const CService& addr)
|
||||
}
|
||||
|
||||
|
||||
CNode::eTlsOption CNode::tlsFallbackNonTls = CNode::eTlsOption::FALLBACK_UNSET;
|
||||
CNode::eTlsOption CNode::tlsFallbackNonTls = CNode::eTlsOption::FALLBACK_FALSE;
|
||||
CNode::eTlsOption CNode::tlsValidate = CNode::eTlsOption::FALLBACK_UNSET;
|
||||
|
||||
uint64_t CNode::nTotalBytesRecv = 0;
|
||||
@@ -418,7 +409,6 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
||||
}
|
||||
}
|
||||
|
||||
/// debug print
|
||||
LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
|
||||
pszDest ? pszDest : addrConnect.ToString(),
|
||||
pszDest ? 0.0 : (double)(GetTime() - addrConnect.nTime)/3600.0);
|
||||
@@ -441,67 +431,12 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* TCP connection is ready. Do client side SSL. */
|
||||
if (CNode::GetTlsFallbackNonTls())
|
||||
{
|
||||
{
|
||||
LOCK(cs_vNonTLSNodesOutbound);
|
||||
|
||||
LogPrint("tls", "%s():%d - handling connection to %s\n", __func__, __LINE__, addrConnect.ToString());
|
||||
|
||||
NODE_ADDR nodeAddr(addrConnect.ToStringIP());
|
||||
|
||||
bool bUseTLS = ((GetBoolArg("-tls", true) || GetArg("-tls", "") == "only")
|
||||
&& find(vNonTLSNodesOutbound.begin(),
|
||||
vNonTLSNodesOutbound.end(),
|
||||
nodeAddr) == vNonTLSNodesOutbound.end());
|
||||
unsigned long err_code = 0;
|
||||
if (bUseTLS)
|
||||
{
|
||||
ssl = tlsmanager.connect(hSocket, addrConnect, err_code);
|
||||
if (!ssl)
|
||||
{
|
||||
if (err_code == TLSManager::SELECT_TIMEDOUT)
|
||||
{
|
||||
// can fail for timeout in select on fd, that is not a ssl error and we should not
|
||||
// consider this node as non TLS
|
||||
LogPrint("tls", "%s():%d - Connection to %s timedout\n",
|
||||
__func__, __LINE__, addrConnect.ToStringIP());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Further reconnection will be made in non-TLS (unencrypted) mode
|
||||
vNonTLSNodesOutbound.push_back(NODE_ADDR(addrConnect.ToStringIP(), GetTimeMillis()));
|
||||
LogPrint("tls", "%s():%d - err_code %x, adding connection to %s vNonTLSNodesOutbound list (sz=%d)\n",
|
||||
__func__, __LINE__, err_code, addrConnect.ToStringIP(), vNonTLSNodesOutbound.size());
|
||||
}
|
||||
CloseSocket(hSocket);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrintf ("Connection to %s will be unencrypted\n", addrConnect.ToString());
|
||||
|
||||
vNonTLSNodesOutbound.erase(
|
||||
remove(
|
||||
vNonTLSNodesOutbound.begin(),
|
||||
vNonTLSNodesOutbound.end(),
|
||||
nodeAddr),
|
||||
vNonTLSNodesOutbound.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long err_code = 0;
|
||||
ssl = tlsmanager.connect(hSocket, addrConnect, err_code);
|
||||
if(!ssl)
|
||||
{
|
||||
LogPrint("tls", "%s():%d - err_code %x, connection to %s failed)\n",
|
||||
__func__, __LINE__, err_code, addrConnect.ToStringIP());
|
||||
CloseSocket(hSocket);
|
||||
return NULL;
|
||||
}
|
||||
unsigned long err_code = 0;
|
||||
ssl = tlsmanager.connect(hSocket, addrConnect, err_code);
|
||||
if(!ssl) {
|
||||
LogPrint("tls", "%s():%d - err_code %x, connection to %s failed)\n", __func__, __LINE__, err_code, addrConnect.ToStringIP());
|
||||
CloseSocket(hSocket);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // USE_TLS
|
||||
@@ -547,8 +482,7 @@ void CNode::CloseSocketDisconnect()
|
||||
LogPrintf("(node is probably shutting down) disconnecting peer=%d\n", id);
|
||||
}
|
||||
|
||||
if (ssl)
|
||||
{
|
||||
if (ssl) {
|
||||
unsigned long err_code = 0;
|
||||
tlsmanager.waitFor(SSL_SHUTDOWN, hSocket, ssl, (DEFAULT_CONNECT_TIMEOUT / 1000), err_code);
|
||||
wolfSSL_free(ssl);
|
||||
@@ -590,10 +524,6 @@ void CNode::PushVersion()
|
||||
//fprintf(stderr,"HUSH_NSPV.%d PUSH services.%llx\n",HUSH_NSPV,(long long)nLocalServices);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::map<CSubNet, int64_t> CNode::setBanned;
|
||||
CCriticalSection CNode::cs_setBanned;
|
||||
|
||||
@@ -718,7 +648,7 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
|
||||
nPingUsecWait = GetTimeMicros() - nPingUsecStart;
|
||||
}
|
||||
|
||||
// Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
|
||||
// Raw ping time is in microseconds, but show it to user as whole seconds (Hush users should be well used to small numbers with many decimal places by now :)
|
||||
stats.dPingTime = (((double)nPingUsecTime) / 1e6);
|
||||
stats.dPingWait = (((double)nPingUsecWait) / 1e6);
|
||||
|
||||
@@ -1174,66 +1104,14 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
|
||||
SetSocketNonBlocking(hSocket, true);
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* TCP connection is ready. Do server side SSL. */
|
||||
if (CNode::GetTlsFallbackNonTls())
|
||||
/* TCP connection is ready. Do server side TLS */
|
||||
unsigned long err_code = 0;
|
||||
ssl = tlsmanager.accept( hSocket, addr, err_code);
|
||||
if(!ssl)
|
||||
{
|
||||
LOCK(cs_vNonTLSNodesInbound);
|
||||
|
||||
LogPrint("tls", "%s():%d - handling connection from %s\n", __func__, __LINE__, addr.ToString());
|
||||
|
||||
NODE_ADDR nodeAddr(addr.ToStringIP());
|
||||
|
||||
bool bUseTLS = ((GetBoolArg("-tls", true) || GetArg("-tls", "") == "only")
|
||||
&& find(vNonTLSNodesInbound.begin(),
|
||||
vNonTLSNodesInbound.end(),
|
||||
nodeAddr) == vNonTLSNodesInbound.end());
|
||||
unsigned long err_code = 0;
|
||||
if (bUseTLS)
|
||||
{
|
||||
ssl = tlsmanager.accept( hSocket, addr, err_code);
|
||||
if(!ssl)
|
||||
{
|
||||
if (err_code == TLSManager::SELECT_TIMEDOUT)
|
||||
{
|
||||
// can fail also for timeout in select on fd, that is not a ssl error and we should not
|
||||
// consider this node as non TLS
|
||||
LogPrint("tls", "%s():%d - Connection from %s timedout\n", __func__, __LINE__, addr.ToStringIP());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Further reconnection will be made in non-TLS (unencrypted) mode
|
||||
vNonTLSNodesInbound.push_back(NODE_ADDR(addr.ToStringIP(), GetTimeMillis()));
|
||||
LogPrint("tls", "%s():%d - err_code %x, adding connection from %s vNonTLSNodesInbound list (sz=%d)\n",
|
||||
__func__, __LINE__, err_code, addr.ToStringIP(), vNonTLSNodesInbound.size());
|
||||
}
|
||||
CloseSocket(hSocket);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrintf ("TLS: Connection from %s will be unencrypted\n", addr.ToStringIP());
|
||||
|
||||
vNonTLSNodesInbound.erase(
|
||||
remove(
|
||||
vNonTLSNodesInbound.begin(),
|
||||
vNonTLSNodesInbound.end(),
|
||||
nodeAddr
|
||||
),
|
||||
vNonTLSNodesInbound.end());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long err_code = 0;
|
||||
ssl = tlsmanager.accept( hSocket, addr, err_code);
|
||||
if(!ssl)
|
||||
{
|
||||
LogPrint("tls", "%s():%d - err_code %x, failure accepting connection from %s\n",
|
||||
__func__, __LINE__, err_code, addr.ToStringIP());
|
||||
CloseSocket(hSocket);
|
||||
return;
|
||||
}
|
||||
LogPrint("tls", "%s():%d - err_code %x, failure accepting connection from %s\n", __func__, __LINE__, err_code, addr.ToStringIP());
|
||||
CloseSocket(hSocket);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // USE_TLS
|
||||
@@ -1250,28 +1128,12 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_TLS)
|
||||
void ThreadNonTLSPoolsCleaner()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
tlsmanager.cleanNonTLSPool(vNonTLSNodesInbound, cs_vNonTLSNodesInbound);
|
||||
tlsmanager.cleanNonTLSPool(vNonTLSNodesOutbound, cs_vNonTLSNodesOutbound);
|
||||
MilliSleep(DEFAULT_CONNECT_TIMEOUT); // sleep and sleep_for are interruption points, which will throw boost::thread_interrupted
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_TLS
|
||||
|
||||
|
||||
void ThreadSocketHandler()
|
||||
{
|
||||
unsigned int nPrevNodeCount = 0;
|
||||
while (true)
|
||||
{
|
||||
//
|
||||
// Disconnect nodes
|
||||
//
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
// Disconnect unused nodes
|
||||
@@ -1332,9 +1194,7 @@ void ThreadSocketHandler()
|
||||
uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
|
||||
}
|
||||
|
||||
//
|
||||
// Find which sockets have data to receive
|
||||
//
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 50000; // frequency to poll pnode->vSend
|
||||
@@ -1418,9 +1278,7 @@ void ThreadSocketHandler()
|
||||
MilliSleep(timeout.tv_usec/1000);
|
||||
}
|
||||
|
||||
//
|
||||
// Accept new connections
|
||||
//
|
||||
BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket)
|
||||
{
|
||||
if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
|
||||
@@ -1429,9 +1287,7 @@ void ThreadSocketHandler()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Service each socket
|
||||
//
|
||||
vector<CNode*> vNodesCopy;
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
@@ -1447,9 +1303,7 @@ void ThreadSocketHandler()
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Inactivity checking
|
||||
//
|
||||
int64_t nTime = GetTime();
|
||||
if (nTime - pnode->nTimeConnected > 60)
|
||||
{
|
||||
@@ -1541,8 +1395,7 @@ void DumpAddresses()
|
||||
CAddrDB adb;
|
||||
adb.Write(addrman);
|
||||
|
||||
LogPrint("net", "Flushed %d addresses to peers.dat %dms\n",
|
||||
addrman.size(), GetTimeMillis() - nStart);
|
||||
LogPrint("net", "Flushed %d addresses to peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart);
|
||||
}
|
||||
|
||||
void static ProcessOneShot()
|
||||
@@ -1609,12 +1462,11 @@ void ThreadOpenConnections()
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Choose an address to connect to based on most recently seen
|
||||
//
|
||||
CAddress addrConnect;
|
||||
|
||||
// Only connect out to one peer per network group (/16 for IPv4).
|
||||
// Use -asmap for ASN bucketing
|
||||
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
|
||||
int nOutbound = 0;
|
||||
set<vector<unsigned char> > setConnected;
|
||||
@@ -1738,16 +1590,14 @@ void ThreadOpenAddedConnections()
|
||||
OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
|
||||
MilliSleep(500);
|
||||
}
|
||||
MilliSleep(120000); // Retry every 2 minutes
|
||||
MilliSleep(120000);
|
||||
}
|
||||
}
|
||||
|
||||
// if successful, this moves the passed grant to the constructed node
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot)
|
||||
{
|
||||
//
|
||||
// Initiate outbound network connection
|
||||
//
|
||||
boost::this_thread::interruption_point();
|
||||
if (!pszDest) {
|
||||
if (IsLocal(addrConnect) ||
|
||||
@@ -1760,30 +1610,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
|
||||
CNode* pnode = ConnectNode(addrConnect, pszDest);
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
#if defined(USE_TLS)
|
||||
if (CNode::GetTlsFallbackNonTls())
|
||||
{
|
||||
if (!pnode)
|
||||
{
|
||||
string strDest;
|
||||
int port;
|
||||
|
||||
if (!pszDest)
|
||||
strDest = addrConnect.ToStringIP();
|
||||
else
|
||||
SplitHostPort(string(pszDest), port, strDest);
|
||||
|
||||
if (tlsmanager.isNonTLSAddr(strDest, vNonTLSNodesOutbound, cs_vNonTLSNodesOutbound))
|
||||
{
|
||||
// Attempt to reconnect in non-TLS mode
|
||||
pnode = ConnectNode(addrConnect, pszDest);
|
||||
boost::this_thread::interruption_point();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!pnode)
|
||||
return false;
|
||||
if (grantOutbound)
|
||||
@@ -2028,7 +1854,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
{
|
||||
CAddrDB adb;
|
||||
if (!adb.Read(addrman))
|
||||
LogPrintf("Invalid or missing peers.dat; recreating\n");
|
||||
LogPrintf("Invalid or missing peers.dat! This can happen when upgrading. Whatevz, recreating\n");
|
||||
}
|
||||
LogPrintf("Loaded %i addresses from peers.dat %dms\n",
|
||||
addrman.size(), GetTimeMillis() - nStart);
|
||||
@@ -2046,7 +1872,6 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
Discover(threadGroup);
|
||||
|
||||
#ifdef USE_TLS
|
||||
|
||||
if (!tlsmanager.prepareCredentials()) {
|
||||
LogPrintf("TLS: ERROR: %s: %s: Credentials weren't generated. Node can't be started.\n", __FILE__, __func__);
|
||||
return;
|
||||
@@ -2057,7 +1882,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
return;
|
||||
}
|
||||
#else
|
||||
LogPrintf("TLS is not used!\n");
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Start threads
|
||||
@@ -2078,14 +1903,6 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
// Process messages
|
||||
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));
|
||||
|
||||
#if defined(USE_TLS)
|
||||
if (CNode::GetTlsFallbackNonTls())
|
||||
{
|
||||
// Clean pools of addresses for non-TLS connections
|
||||
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "poolscleaner", &ThreadNonTLSPoolsCleaner));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Dump network addresses
|
||||
scheduler.scheduleEvery(&DumpAddresses, DUMP_ADDRESSES_INTERVAL);
|
||||
}
|
||||
@@ -2396,40 +2213,22 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
|
||||
|
||||
bool CNode::GetTlsFallbackNonTls()
|
||||
{
|
||||
if (tlsFallbackNonTls == eTlsOption::FALLBACK_UNSET)
|
||||
{
|
||||
// one time only setting of static class attribute
|
||||
if ( GetArg("-tls", "") != "only" )
|
||||
{
|
||||
LogPrint("tls", "%s():%d - Non-TLS connections will be used in case of failure of TLS\n",
|
||||
__func__, __LINE__);
|
||||
tlsFallbackNonTls = eTlsOption::FALLBACK_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint("tls", "%s():%d - Non-TLS connections will NOT be used in case of failure of TLS\n",
|
||||
__func__, __LINE__);
|
||||
tlsFallbackNonTls = eTlsOption::FALLBACK_FALSE;
|
||||
}
|
||||
}
|
||||
return (tlsFallbackNonTls == eTlsOption::FALLBACK_TRUE);
|
||||
LogPrint("tls", "%s():%d - Non-TLS connections no longer supported\n", __func__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNode::GetTlsValidate()
|
||||
{
|
||||
if (tlsValidate == eTlsOption::FALLBACK_UNSET)
|
||||
{
|
||||
// one time only setting of static class attribute
|
||||
if ( GetBoolArg("-tlsvalidate", false))
|
||||
{
|
||||
LogPrint("tls", "%s():%d - TLS certificates will be validated\n",
|
||||
__func__, __LINE__);
|
||||
// This is useful for private Hush Smart Chains, that want to exist
|
||||
// on a closed VPN with an internal CA or trusted cert system, or
|
||||
// various other use cases
|
||||
if ( GetBoolArg("-tlsvalidate", false)) {
|
||||
LogPrint("tls", "%s():%d - TLS certificates will be validated\n", __func__, __LINE__);
|
||||
tlsValidate = eTlsOption::FALLBACK_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint("tls", "%s():%d - TLS certificates will NOT be validated\n",
|
||||
__func__, __LINE__);
|
||||
} else {
|
||||
LogPrint("tls", "%s():%d - TLS certificates will NOT be validated\n", __func__, __LINE__);
|
||||
tlsValidate = eTlsOption::FALLBACK_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user