From 0eb87dc80df0f2db47539ef8938fc6b77a2b5013 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Thu, 18 Nov 2021 09:19:09 +0100 Subject: [PATCH] net: open p2p connections to nodes that listen on non-default ports By default, for mainnet, the p2p listening port is 8333. Bitcoin Core has a strong preference for only connecting to nodes that listen on that port. Remove that preference because connections over clearnet that involve port 8333 make it easy to detect, analyze, block or divert Bitcoin p2p traffic before the connection is even established (at TCP SYN time). For further justification see the OP of: https://github.com/bitcoin/bitcoin/pull/23306 --- doc/README.md | 1 + doc/p2p-bad-ports.md | 114 +++++++++++++++++++++++++++++++++++++ src/init.cpp | 7 +++ src/net.cpp | 8 +-- src/netbase.cpp | 90 +++++++++++++++++++++++++++++ src/netbase.h | 9 +++ src/test/netbase_tests.cpp | 20 +++++++ 7 files changed, 243 insertions(+), 6 deletions(-) create mode 100644 doc/p2p-bad-ports.md diff --git a/doc/README.md b/doc/README.md index 2800937d30669b..c200ac3753727d 100644 --- a/doc/README.md +++ b/doc/README.md @@ -79,6 +79,7 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th - [Init Scripts (systemd/upstart/openrc)](init.md) - [Managing Wallets](managing-wallets.md) - [Multisig Tutorial](multisig-tutorial.md) +- [P2P bad ports definition and list](p2p-bad-ports.md) - [PSBT support](psbt.md) - [Reduce Memory](reduce-memory.md) - [Reduce Traffic](reduce-traffic.md) diff --git a/doc/p2p-bad-ports.md b/doc/p2p-bad-ports.md new file mode 100644 index 00000000000000..54d40f86d16e2c --- /dev/null +++ b/doc/p2p-bad-ports.md @@ -0,0 +1,114 @@ +When Bitcoin Core automatically opens outgoing P2P connections it chooses +a peer (address and port) from its list of potential peers. This list is +populated with unchecked data, gossiped over the P2P network by other peers. + +It may happen that a malicious actor gossips an address:port where no Bitcoin +node is listening. Or even where another service is listening which is not +related to the Bitcoin network. As a result, this service may occasionally +get connection attempts from Bitcoin nodes. + +"Bad" ports are ones that are used by services which usually are not opened to +the public and usually require authentication. A connection attempt (by Bitcoin +Core, trying to connect because it thinks there is a Bitcoin node on that +address:port) to such service may be considered a malicious action by an +ultra-paranoid administrator. An example for such a port is 22 (ssh). On the +other hand, connection attempts to public services that usually do not require +authentication are unlikely to be considered a malicious action, +e.g. port 80 (http). + +Following is a list of "bad" ports which Bitcoin Core avoids when choosing a +peer to connect to. If a node is listening on such a port, it will likely get +less incoming connections. + + 1: tcpmux + 7: echo + 9: discard + 11: systat + 13: daytime + 15: netstat + 17: qotd + 19: chargen + 20: ftp data + 21: ftp access + 22: ssh + 23: telnet + 25: smtp + 37: time + 42: name + 43: nicname + 53: domain + 69: tftp + 77: priv-rjs + 79: finger + 87: ttylink + 95: supdup + 101: hostname + 102: iso-tsap + 103: gppitnp + 104: acr-nema + 109: pop2 + 110: pop3 + 111: sunrpc + 113: auth + 115: sftp + 117: uucp-path + 119: nntp + 123: NTP + 135: loc-srv /epmap + 137: netbios + 139: netbios + 143: imap2 + 161: snmp + 179: BGP + 389: ldap + 427: SLP (Also used by Apple Filing Protocol) + 465: smtp+ssl + 512: print / exec + 513: login + 514: shell + 515: printer + 526: tempo + 530: courier + 531: chat + 532: netnews + 540: uucp + 548: AFP (Apple Filing Protocol) + 554: rtsp + 556: remotefs + 563: nntp+ssl + 587: smtp (rfc6409) + 601: syslog-conn (rfc3195) + 636: ldap+ssl + 989: ftps-data + 990: ftps + 993: ldap+ssl + 995: pop3+ssl + 1719: h323gatestat + 1720: h323hostcall + 1723: pptp + 2049: nfs + 3659: apple-sasl / PasswordServer + 4045: lockd + 5060: sip + 5061: sips + 6000: X11 + 6566: sane-port + 6665: Alternate IRC + 6666: Alternate IRC + 6667: Standard IRC + 6668: Alternate IRC + 6669: Alternate IRC + 6697: IRC + TLS + 10080: Amanda + +For further information see: + +[pull/23306](https://github.com/bitcoin/bitcoin/pull/23306#issuecomment-947516736) + +[pull/23542](https://github.com/bitcoin/bitcoin/pull/23542) + +[fetch.spec.whatwg.org](https://fetch.spec.whatwg.org/#port-blocking) + +[chromium.googlesource.com](https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc) + +[hg.mozilla.org](https://hg.mozilla.org/mozilla-central/file/tip/netwerk/base/nsIOService.cpp) diff --git a/src/init.cpp b/src/init.cpp index 015e17596c3829..3248035103173d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1701,6 +1701,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) if (index == std::string::npos) { if (Lookup(bind_arg, bind_addr, GetListenPort(), false)) { connOptions.vBinds.push_back(bind_addr); + if (IsBadPort(bind_addr.GetPort())) { + InitWarning(strprintf( + _("-bind request to listen on port %u. This port is considered \"bad\" and " + "thus it is unlikely that any Bitcoin Core peers connect to it. See " + "doc/p2p-bad-ports.md for details and a full list."), + bind_addr.GetPort())); + } continue; } } else { diff --git a/src/net.cpp b/src/net.cpp index be56d1e2d2572d..345dcfe75c68a2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2098,12 +2098,8 @@ void CConnman::ThreadOpenConnections(const std::vector connect) continue; } - // Do not allow non-default ports, unless after 50 invalid - // addresses selected already. This is to prevent malicious peers - // from advertising themselves as a service on another host and - // port, causing a DoS attack as nodes around the network attempt - // to connect to it fruitlessly. - if (addr.GetPort() != Params().GetDefaultPort(addr.GetNetwork()) && nTries < 50) { + // Do not connect to bad ports, unless 50 invalid addresses have been selected already. + if (nTries < 50 && (addr.IsIPv4() || addr.IsIPv6()) && IsBadPort(addr.GetPort())) { continue; } diff --git a/src/netbase.cpp b/src/netbase.cpp index 87014a06444820..fd3016d9d77ebc 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -749,3 +749,93 @@ void InterruptSocks5(bool interrupt) { interruptSocks5Recv = interrupt; } + +bool IsBadPort(uint16_t port) +{ + /* Don't forget to update doc/p2p-bad-ports.md if you change this list. */ + + switch (port) { + case 1: // tcpmux + case 7: // echo + case 9: // discard + case 11: // systat + case 13: // daytime + case 15: // netstat + case 17: // qotd + case 19: // chargen + case 20: // ftp data + case 21: // ftp access + case 22: // ssh + case 23: // telnet + case 25: // smtp + case 37: // time + case 42: // name + case 43: // nicname + case 53: // domain + case 69: // tftp + case 77: // priv-rjs + case 79: // finger + case 87: // ttylink + case 95: // supdup + case 101: // hostname + case 102: // iso-tsap + case 103: // gppitnp + case 104: // acr-nema + case 109: // pop2 + case 110: // pop3 + case 111: // sunrpc + case 113: // auth + case 115: // sftp + case 117: // uucp-path + case 119: // nntp + case 123: // NTP + case 135: // loc-srv /epmap + case 137: // netbios + case 139: // netbios + case 143: // imap2 + case 161: // snmp + case 179: // BGP + case 389: // ldap + case 427: // SLP (Also used by Apple Filing Protocol) + case 465: // smtp+ssl + case 512: // print / exec + case 513: // login + case 514: // shell + case 515: // printer + case 526: // tempo + case 530: // courier + case 531: // chat + case 532: // netnews + case 540: // uucp + case 548: // AFP (Apple Filing Protocol) + case 554: // rtsp + case 556: // remotefs + case 563: // nntp+ssl + case 587: // smtp (rfc6409) + case 601: // syslog-conn (rfc3195) + case 636: // ldap+ssl + case 989: // ftps-data + case 990: // ftps + case 993: // ldap+ssl + case 995: // pop3+ssl + case 1719: // h323gatestat + case 1720: // h323hostcall + case 1723: // pptp + case 2049: // nfs + case 3659: // apple-sasl / PasswordServer + case 4045: // lockd + case 5060: // sip + case 5061: // sips + case 6000: // X11 + case 6566: // sane-port + case 6665: // Alternate IRC + case 6666: // Alternate IRC + case 6667: // Standard IRC + case 6668: // Alternate IRC + case 6669: // Alternate IRC + case 6697: // IRC + TLS + case 10080: // Amanda + return true; + } + return false; +} diff --git a/src/netbase.h b/src/netbase.h index 980aa47d66c3fa..90107c8bbb0b51 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -247,4 +247,13 @@ void InterruptSocks5(bool interrupt); */ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* auth, const Sock& socket); +/** + * Determine if a port is "bad" from the perspective of attempting to connect + * to a node on that port. + * @see doc/p2p-bad-ports.md + * @param[in] port Port to check. + * @return true if the port is bad + */ +bool IsBadPort(uint16_t port); + #endif // BITCOIN_NETBASE_H diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 6410ac565ab05a..8e6e911ec2c0a4 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -576,4 +576,24 @@ BOOST_AUTO_TEST_CASE(caddress_unserialize_v2) BOOST_CHECK(fixture_addresses == addresses_unserialized); } +BOOST_AUTO_TEST_CASE(isbadport) +{ + BOOST_CHECK(IsBadPort(1)); + BOOST_CHECK(IsBadPort(22)); + BOOST_CHECK(IsBadPort(6000)); + + BOOST_CHECK(!IsBadPort(80)); + BOOST_CHECK(!IsBadPort(443)); + BOOST_CHECK(!IsBadPort(8333)); + + // Check all ports, there must be 80 bad ports in total. + size_t total_bad_ports{0}; + for (uint16_t port = std::numeric_limits::max(); port > 0; --port) { + if (IsBadPort(port)) { + ++total_bad_ports; + } + } + BOOST_CHECK_EQUAL(total_bad_ports, 80); +} + BOOST_AUTO_TEST_SUITE_END()