diff --git a/libethereum/PeerNetwork.cpp b/libethereum/PeerNetwork.cpp index 51a345d0a..7a43bcc69 100644 --- a/libethereum/PeerNetwork.cpp +++ b/libethereum/PeerNetwork.cpp @@ -60,14 +60,36 @@ static const vector c_rejectAddresses = { {bi::address_v6::from_string("::")} }; -PeerSession::PeerSession(PeerServer* _s, bi::tcp::socket _socket, uint _rNId): +// Helper function to determine if an address falls within one of the reserved ranges +// For V4: +// Class A "10.*", Class B "172.[16->31].*", Class C "192.168.*" +// Not implemented yet for V6 +bool eth::isPrivateAddress(bi::address _addressToCheck) +{ + if (_addressToCheck.is_v4()) + { + bi::address_v4 v4Address = _addressToCheck.to_v4(); + bi::address_v4::bytes_type bytesToCheck = v4Address.to_bytes(); + if (bytesToCheck[0] == 10) + return true; + if (bytesToCheck[0] == 172 && (bytesToCheck[1] >= 16 && bytesToCheck[1] <=31)) + return true; + if (bytesToCheck[0] == 192 && bytesToCheck[1] == 168) + return true; + } + return false; +} + +PeerSession::PeerSession(PeerServer* _s, bi::tcp::socket _socket, uint _rNId, bi::address _peerAddress, short _peerPort): m_server(_s), m_socket(std::move(_socket)), m_reqNetworkId(_rNId), + m_listenPort(_peerPort), m_rating(0) { m_disconnect = std::chrono::steady_clock::time_point::max(); m_connect = std::chrono::steady_clock::now(); + m_info = PeerInfo({"?", _peerAddress.to_string(), m_listenPort, std::chrono::steady_clock::duration(0)}); } PeerSession::~PeerSession() @@ -116,7 +138,7 @@ bool PeerSession::interpret(RLP const& _r) return false; } try - { m_info = PeerInfo({clientVersion, m_socket.remote_endpoint().address().to_string(), (short)m_socket.remote_endpoint().port(), std::chrono::steady_clock::duration()}); } + { m_info = PeerInfo({clientVersion, m_socket.remote_endpoint().address().to_string(), m_listenPort, std::chrono::steady_clock::duration()}); } catch (...) { disconnect(BadProtocol); @@ -196,8 +218,11 @@ bool PeerSession::interpret(RLP const& _r) clogS(NetMessageSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)"; for (unsigned i = 1; i < _r.itemCount(); ++i) { - auto ep = bi::tcp::endpoint(bi::address_v4(_r[i][0].toArray()), _r[i][1].toInt()); + bi::address_v4 peerAddress(_r[i][0].toArray()); + auto ep = bi::tcp::endpoint(peerAddress, _r[i][1].toInt()); Public id = _r[i][2].toHash(); + if (isPrivateAddress(peerAddress)) + goto CONTINUE; clogS(NetAllDetail) << "Checking: " << ep << "(" << asHex(id.ref().cropped(0, 4)) << ")"; @@ -707,7 +732,9 @@ std::map PeerServer::potentialPeers() if (auto j = i.second.lock()) { auto ep = j->endpoint(); - if (ep.port() && j->m_id) + // Skip peers with a listen port of zero or are on a private network + bool peerOnNet = (j->m_listenPort != 0 && !isPrivateAddress(ep.address())); + if (peerOnNet && ep.port() && j->m_id) ret.insert(make_pair(i.first, ep)); } return ret; @@ -727,7 +754,9 @@ void PeerServer::ensureAccepting() try { clog(NetNote) << "Accepted connection from " << m_socket.remote_endpoint(); } catch (...){} - auto p = std::make_shared(this, std::move(m_socket), m_requiredNetworkId); + bi::address remoteAddress = m_socket.remote_endpoint().address(); + // Port defaults to 0 - we let the hello tell us which port the peer listens to + auto p = std::make_shared(this, std::move(m_socket), m_requiredNetworkId, remoteAddress); p->start(); } catch (std::exception const& _e) @@ -754,7 +783,7 @@ void PeerServer::connect(bi::tcp::endpoint const& _ep) } else { - auto p = make_shared(this, std::move(*s), m_requiredNetworkId); + auto p = make_shared(this, std::move(*s), m_requiredNetworkId, _ep.address(), _ep.port()); clog(NetNote) << "Connected to " << p->endpoint(); p->start(); } diff --git a/libethereum/PeerNetwork.h b/libethereum/PeerNetwork.h index 6bdc239ca..9553120fa 100644 --- a/libethereum/PeerNetwork.h +++ b/libethereum/PeerNetwork.h @@ -35,6 +35,8 @@ namespace bi = boost::asio::ip; namespace eth { +bool isPrivateAddress(bi::address _addressToCheck); + class BlockChain; class TransactionQueue; @@ -89,7 +91,7 @@ class PeerSession: public std::enable_shared_from_this friend class PeerServer; public: - PeerSession(PeerServer* _server, bi::tcp::socket _socket, uint _rNId); + PeerSession(PeerServer* _server, bi::tcp::socket _socket, uint _rNId, bi::address _peerAddress, short _peerPort = 0); ~PeerSession(); void start();