Merge pull request #5161

845c86d Do not use third party services for IP detection. (Gregory Maxwell)
This commit is contained in:
Wladimir J. van der Laan 2014-11-12 18:12:33 +01:00
commit 0c7862e968
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
4 changed files with 61 additions and 148 deletions

View File

@ -574,6 +574,9 @@ bool AppInit2(boost::thread_group& threadGroup)
// to protect privacy, do not listen by default if a default proxy server is specified // to protect privacy, do not listen by default if a default proxy server is specified
if (SoftSetBoolArg("-listen", false)) if (SoftSetBoolArg("-listen", false))
LogPrintf("AppInit2 : parameter interaction: -proxy set -> setting -listen=0\n"); LogPrintf("AppInit2 : parameter interaction: -proxy set -> setting -listen=0\n");
// to protect privacy, do not discover addresses by default
if (SoftSetBoolArg("-discover", false))
LogPrintf("AppInit2 : parameter interaction: -proxy set -> setting -discover=0\n");
} }
if (!GetBoolArg("-listen", true)) { if (!GetBoolArg("-listen", true)) {

View File

@ -3478,12 +3478,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else else
pfrom->fRelayTxes = true; pfrom->fRelayTxes = true;
if (pfrom->fInbound && addrMe.IsRoutable())
{
pfrom->addrLocal = addrMe;
SeenLocal(addrMe);
}
// Disconnect if we connected to ourself // Disconnect if we connected to ourself
if (nNonce == nLocalHostNonce && nNonce > 1) if (nNonce == nLocalHostNonce && nNonce > 1)
{ {
@ -3492,6 +3486,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true; return true;
} }
pfrom->addrLocal = addrMe;
if (pfrom->fInbound && addrMe.IsRoutable())
{
SeenLocal(addrMe);
}
// Be shy and don't send version until we hear // Be shy and don't send version until we hear
if (pfrom->fInbound) if (pfrom->fInbound)
pfrom->PushVersion(); pfrom->PushVersion();
@ -3512,7 +3512,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{ {
CAddress addr = GetLocalAddress(&pfrom->addr); CAddress addr = GetLocalAddress(&pfrom->addr);
if (addr.IsRoutable()) if (addr.IsRoutable())
{
pfrom->PushAddress(addr); pfrom->PushAddress(addr);
} else if (IsPeerAddrLocalGood(pfrom)) {
addr.SetIP(pfrom->addrLocal);
pfrom->PushAddress(addr);
}
} }
// Get recent addresses // Get recent addresses
@ -4375,24 +4380,18 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
static int64_t nLastRebroadcast; static int64_t nLastRebroadcast;
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
{ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{ {
LOCK(cs_vNodes); // Periodically clear setAddrKnown to allow refresh broadcasts
BOOST_FOREACH(CNode* pnode, vNodes) if (nLastRebroadcast)
{ pnode->setAddrKnown.clear();
// Periodically clear setAddrKnown to allow refresh broadcasts
if (nLastRebroadcast)
pnode->setAddrKnown.clear();
// Rebroadcast our address // Rebroadcast our address
if (fListen) AdvertizeLocal(pnode);
{
CAddress addr = GetLocalAddress(&pnode->addr);
if (addr.IsRoutable())
pnode->PushAddress(addr);
}
}
} }
nLastRebroadcast = GetTime(); if (!vNodes.empty())
nLastRebroadcast = GetTime();
} }
// //

View File

@ -142,16 +142,19 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
} }
// get best local address for a particular peer as a CAddress // get best local address for a particular peer as a CAddress
// Otherwise, return the unroutable 0.0.0.0 but filled in with
// the normal parameters, since the IP may be changed to a useful
// one by discovery.
CAddress GetLocalAddress(const CNetAddr *paddrPeer) CAddress GetLocalAddress(const CNetAddr *paddrPeer)
{ {
CAddress ret(CService("0.0.0.0",0),0); CAddress ret(CService("0.0.0.0",GetListenPort()),0);
CService addr; CService addr;
if (GetLocal(addr, paddrPeer)) if (GetLocal(addr, paddrPeer))
{ {
ret = CAddress(addr); ret = CAddress(addr);
ret.nServices = nLocalServices;
ret.nTime = GetAdjustedTime();
} }
ret.nServices = nLocalServices;
ret.nTime = GetAdjustedTime();
return ret; return ret;
} }
@ -205,21 +208,38 @@ bool RecvLine(SOCKET hSocket, string& strLine)
} }
} }
// used when scores of local addresses may have changed int GetnScore(const CService& addr)
// pushes better local address to peers
void static AdvertizeLocal()
{ {
LOCK(cs_vNodes); LOCK(cs_mapLocalHost);
BOOST_FOREACH(CNode* pnode, vNodes) if (mapLocalHost.count(addr) == LOCAL_NONE)
return 0;
return mapLocalHost[addr].nScore;
}
// Is our peer's addrLocal potentially useful as an external IP source?
bool IsPeerAddrLocalGood(CNode *pnode)
{
return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
!IsLimited(pnode->addrLocal.GetNetwork());
}
// pushes our own address to a peer
void AdvertizeLocal(CNode *pnode)
{
if (fListen && pnode->fSuccessfullyConnected)
{ {
if (pnode->fSuccessfullyConnected) CAddress addrLocal = GetLocalAddress(&pnode->addr);
// If discovery is enabled, sometimes give our peer the address it
// tells us that it sees us as in case it has a better idea of our
// address than we do.
if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
{ {
CAddress addrLocal = GetLocalAddress(&pnode->addr); addrLocal.SetIP(pnode->addrLocal);
if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal) }
{ if (addrLocal.IsRoutable())
pnode->PushAddress(addrLocal); {
pnode->addrLocal = addrLocal; pnode->PushAddress(addrLocal);
}
} }
} }
} }
@ -257,8 +277,6 @@ bool AddLocal(const CService& addr, int nScore)
SetReachable(addr.GetNetwork()); SetReachable(addr.GetNetwork());
} }
AdvertizeLocal();
return true; return true;
} }
@ -296,12 +314,10 @@ bool SeenLocal(const CService& addr)
return false; return false;
mapLocalHost[addr].nScore++; mapLocalHost[addr].nScore++;
} }
AdvertizeLocal();
return true; return true;
} }
/** check whether a given address is potentially local */ /** check whether a given address is potentially local */
bool IsLocal(const CService& addr) bool IsLocal(const CService& addr)
{ {
@ -323,114 +339,12 @@ bool IsReachable(const CNetAddr& addr)
return IsReachable(net); return IsReachable(net);
} }
bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
{
SOCKET hSocket;
if (!ConnectSocket(addrConnect, hSocket))
return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString());
send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
string strLine;
while (RecvLine(hSocket, strLine))
{
if (strLine.empty()) // HTTP response is separated from headers by blank line
{
while (true)
{
if (!RecvLine(hSocket, strLine))
{
CloseSocket(hSocket);
return false;
}
if (pszKeyword == NULL)
break;
if (strLine.find(pszKeyword) != string::npos)
{
strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
break;
}
}
CloseSocket(hSocket);
if (strLine.find("<") != string::npos)
strLine = strLine.substr(0, strLine.find("<"));
strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
strLine.resize(strLine.size()-1);
CService addr(strLine,0,true);
LogPrintf("GetMyExternalIP() received [%s] %s\n", strLine, addr.ToString());
if (!addr.IsValid() || !addr.IsRoutable())
return false;
ipRet.SetIP(addr);
return true;
}
}
CloseSocket(hSocket);
return error("GetMyExternalIP() : connection closed");
}
bool GetMyExternalIP(CNetAddr& ipRet)
{
CService addrConnect;
const char* pszGet;
const char* pszKeyword;
for (int nLookup = 0; nLookup <= 1; nLookup++)
for (int nHost = 1; nHost <= 1; nHost++)
{
// We should be phasing out our use of sites like these. If we need
// replacements, we should ask for volunteers to put this simple
// php file on their web server that prints the client IP:
// <?php echo $_SERVER["REMOTE_ADDR"]; ?>
if (nHost == 1)
{
addrConnect = CService("91.198.22.70", 80); // checkip.dyndns.org
if (nLookup == 1)
{
CService addrIP("checkip.dyndns.org", 80, true);
if (addrIP.IsValid())
addrConnect = addrIP;
}
pszGet = "GET / HTTP/1.1\r\n"
"Host: checkip.dyndns.org\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
"Connection: close\r\n"
"\r\n";
pszKeyword = "Address:";
}
if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
return true;
}
return false;
}
void ThreadGetMyExternalIP()
{
CNetAddr addrLocalHost;
if (GetMyExternalIP(addrLocalHost))
{
LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP());
AddLocal(addrLocalHost, LOCAL_HTTP);
}
}
void AddressCurrentlyConnected(const CService& addr) void AddressCurrentlyConnected(const CService& addr)
{ {
addrman.Connected(addr); addrman.Connected(addr);
} }
uint64_t CNode::nTotalBytesRecv = 0; uint64_t CNode::nTotalBytesRecv = 0;
uint64_t CNode::nTotalBytesSent = 0; uint64_t CNode::nTotalBytesSent = 0;
CCriticalSection CNode::cs_totalBytesRecv; CCriticalSection CNode::cs_totalBytesRecv;
@ -1687,9 +1601,6 @@ void static Discover(boost::thread_group& threadGroup)
} }
#endif #endif
// Don't use external IPv4 discovery, when -onlynet="IPv6"
if (!IsLimited(NET_IPV4))
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
} }
void StartNode(boost::thread_group& threadGroup) void StartNode(boost::thread_group& threadGroup)

View File

@ -60,7 +60,6 @@ unsigned int SendBufferSize();
void AddOneShot(std::string strDest); void AddOneShot(std::string strDest);
bool RecvLine(SOCKET hSocket, std::string& strLine); bool RecvLine(SOCKET hSocket, std::string& strLine);
bool GetMyExternalIP(CNetAddr& ipRet);
void AddressCurrentlyConnected(const CService& addr); void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const std::string& addrName); CNode* FindNode(const std::string& addrName);
@ -96,12 +95,13 @@ enum
LOCAL_IF, // address a local interface listens on LOCAL_IF, // address a local interface listens on
LOCAL_BIND, // address explicit bound to LOCAL_BIND, // address explicit bound to
LOCAL_UPNP, // address reported by UPnP LOCAL_UPNP, // address reported by UPnP
LOCAL_HTTP, // address reported by whatismyip.com and similar
LOCAL_MANUAL, // address explicitly specified (-externalip=) LOCAL_MANUAL, // address explicitly specified (-externalip=)
LOCAL_MAX LOCAL_MAX
}; };
bool IsPeerAddrLocalGood(CNode *pnode);
void AdvertizeLocal(CNode *pnode);
void SetLimited(enum Network net, bool fLimited = true); void SetLimited(enum Network net, bool fLimited = true);
bool IsLimited(enum Network net); bool IsLimited(enum Network net);
bool IsLimited(const CNetAddr& addr); bool IsLimited(const CNetAddr& addr);