-
Notifications
You must be signed in to change notification settings - Fork 37.7k
net: allow CSubNet of non-IP networks #20852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
If this is merged, then #20849 will not be needed. That PR is valid with or without this one, but this one fixes the issue more broadly. |
I've given this label "Needs backport (0.21)", as either this or #20849 (or both) should go into rc5. If 20849 is merged and backported, we're good. |
Test is broken, fix: diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index ac4db3a5b6..87d8bf6ef6 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -442,8 +442,7 @@ BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters)
BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0"s, ret));
BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com"s, ret));
BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com\0"s, ret));
- // We only do subnetting for IPv4 and IPv6
- BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion"s, ret));
+ BOOST_CHECK(LookupSubNet("5wyqrzbvrdsumnok.onion"s, ret));
BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0"s, ret));
BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com"s, ret));
BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com\0"s, ret));
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Concept/direction ACK, will review the code later |
06af169...6ab8b2b: minor tweaks, add comments to |
|
I am not familiar with this part of the codebase, but it seems safer to move this to 0.21.1. This claims to fix a bug how outbound onion addresses are handled by rpc and misbehavior-disconnect. However, it changes the code paths for all networks and all net handling. So it seems a bit risky to push out this late in the rc stage. (There haven't been any major issues since rc3 other than the macos code signing, so rc5 might very well be a good -final). It could be documented in the release notes, if needed, and a 0.21.1 can be pushed out once this has settled in the master branch (maybe after ~1-2 months)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach ACK; this works for me manually with disconnectnode
on outbound onion peers (edit: but so does master, the issue isn't hit with it, will look at setban <onion> add
) and the netbase_tests run locally, but seeing CI issues.
It would be good to have a failing test case that this patch fixes.
* @param[in] addr Network start. If not IPv4 or IPv6, then a signle-host subnet is created. | ||
* @param[in] mask Network mask, must be of the same type as `addr` and not contain 0-bits | ||
* followed by 1-bits. Otherwise an invalid subnet is created. Ignored for non-IP `addr`. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
readability suggestion
/**
* Construct from a given network start and number of bits (CIDR mask).
- * @param[in] addr Network start. If not IPv4 or IPv6, then a signle-host subnet is created.
- * @param[in] mask CIDR mask, must be in [0, 32] for IPv4 addresses and in [0, 128] for IPv6
- * addresses. Otherwise an invalid subnet is created. Ignored for non-IP `addr`.
+ * @param[in] addr Network start. If not IPv4 or IPv6, then a single-host subnet is created.
+ * @param[in] mask CIDR mask, must be in [0, 32] for IPv4 addresses and in [0, 128] for IPv6
+ * addresses. Otherwise an invalid subnet is created. Ignored for non-IP `addr`.
*/
CSubNet(const CNetAddr& addr, uint8_t mask);
/**
* Construct from a given network start and mask.
- * @param[in] addr Network start. If not IPv4 or IPv6, then a signle-host subnet is created.
- * @param[in] mask Network mask, must be of the same type as `addr` and not contain 0-bits
- * followed by 1-bits. Otherwise an invalid subnet is created. Ignored for non-IP `addr`.
+ * @param[in] addr Network start. If not IPv4 or IPv6, then a single-host subnet is created.
+ * @param[in] mask Network mask, must be of the same type as `addr` and not contain 0-bits
+ * followed by 1-bits. Otherwise an invalid subnet is created. Ignored for non-IP `addr`.
*/
CSubNet(const CNetAddr& addr, const CNetAddr& mask);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 3-column-layout has a maintainability problem when a parameter with longer name is added or existent one renamed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, though I think it's worth it. Anyway, just a suggestion.
6ab8b2b...826b8d9: fix failing For IPv4, deserialize only sets the first 4 bytes of the netmask, leaving the remaining 12 bytes to the default Yes, Eventually |
826b8d9...293070a: fix typos in comments |
Indeed. |
src/netaddress.cpp
Outdated
case NET_ONION: | ||
case NET_I2P: | ||
case NET_CJDNS: | ||
valid = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't just ignore mask
... Might be best to only change the single-address form?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: #20852 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
293070a...1a54bd7: as per suggestion, reverted the two constructors that take also a "netmask" argument to create an invalid subnet, like in |
break; | ||
case NET_INTERNAL: | ||
case NET_UNROUTABLE: | ||
case NET_MAX: | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think valid
is left uninitialized here. It's not initialized in class CSubNet
declaration nor here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is set to false
in the default constructor which is called by this constructor:
CSubNet::CSubNet(const CNetAddr& addr) : CSubNet()
netmask
is also set there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for illuminating. That's kinda sneaky, would prefer to do initialization in the class declaration itself, but no need to do so in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add valid = false;
here as belt and suspenders.
1a54bd7...5e95ce6: add a functional test that fails without this fix and passes with it |
Co-authored-by: Jon Atack <jon@atack.com>
5e95ce6
to
39b4329
Compare
5e95ce6...39b4329: extend the functional test, #20852 (comment) |
Moved to 0.21.1 milestone according to last weeks meeting. Let me know if this is not applicable. |
code review ACK 39b4329
Agreed. |
Allow creation of valid `CSubNet` objects of non-IP networks and only match the single address they were created from (like /32 for IPv4 or /128 for IPv6). This fixes a deficiency in `CConnman::DisconnectNode(const CNetAddr& addr)` and in `BanMan` which assume that creating a subnet from any address using the `CSubNet(CNetAddr)` constructor would later match that address only. Before this change a non-IP subnet would be invalid and would not match any address. Github-Pull: bitcoin#20852 Rebased-From: 94d335d
Co-authored-by: Jon Atack <jon@atack.com> Github-Pull: bitcoin#20852 Rebased-From: 39b4329
Would be nice to summarize the changes that are expected here. Am I right that this ...
I tried testing the changes and restarting the node will corrupt the
|
Would probably be good to propose some release notes based on the changes. Added a draft here: https://github.com/bitcoin-core/bitcoin-devwiki/wiki/%2320852-Release-notes-snippet |
The serialized format has not been changed. If this version writes a ban entry consisting of the newly allowed tor-one-host-subnet, an old version would deserialize that as an invalid subnet: Line 518 in 5cce607
old code, before this PR: Lines 1121 to 1123 in 616eace
Yes.
Yes.
This looks strange, how to reproduce? |
|
Steps to reproduce:
|
39b4329 test: add test for banning of non-IP addresses (Vasil Dimov) 94d335d net: allow CSubNet of non-IP networks (Vasil Dimov) Pull request description: Allow creation of valid `CSubNet` objects of non-IP networks and only match the single address they were created from (like /32 for IPv4 or /128 for IPv6). This fixes a deficiency in `CConnman::DisconnectNode(const CNetAddr& addr)` and in `BanMan` which assume that creating a subnet from any address using the `CSubNet(CNetAddr)` constructor would later match that address only. Before this change a non-IP subnet would be invalid and would not match any address. ACKs for top commit: jonatack: Code review re-ACK 39b4329 per `git diff 5e95ce6 39b4329`; only change since last review is improvements to the functional test; verified the test fails on master @ 616eace where expected (`assert(self.is_banned(node, tor_addr))` fails and unban unfails) laanwj: code review ACK 39b4329 Tree-SHA512: 3239b26d0f2fa2d1388b4fdbc1d05ce4ac1980be699c6ec46049409baefcb2006b1e72b889871e2210e897f6725c48e873f68457eea7e6e4958ab4f959d20297
This is a followup to bitcoin#20852 which allowed non-IP subnets, but some of them, e.g. torv3, cannot be serialized in 16 bytes (addrv1) and must use addrv2. This commit changes the format of `banlist.dat` in such a way that old versions (before this commit) will not be able to read a file written by new versions (after this commit).
@MarcoFalke the problem you describe above is fixed in #20904, but that requires a Maybe revert this PR and merge it together with #20904 as one PR? |
The problem with bitcoin#20852 is that if a host is banned that cannot be serialized in addrv1 format (e.g. Torv3) it is serialized as a dummy IPv6 (`::`) in `banlist.dat`. So, upon restart, the ban entry is lost (is deserialized as an invalid subnet that matches nothing). This reverts commit 39b4329 from bitcoin#20852.
The problem with bitcoin#20852 is that if a host is banned that cannot be serialized in addrv1 format (e.g. Torv3) it is serialized as a dummy IPv6 (`::`) in `banlist.dat`. So, upon restart, the ban entry is lost (is deserialized as an invalid subnet that matches nothing). This reverts commit 94d335d from bitcoin#20852.
Looks like this was never backported? I guess not worth it at this point. |
39b4329 test: add test for banning of non-IP addresses (Vasil Dimov) 94d335d net: allow CSubNet of non-IP networks (Vasil Dimov) Pull request description: Allow creation of valid `CSubNet` objects of non-IP networks and only match the single address they were created from (like /32 for IPv4 or /128 for IPv6). This fixes a deficiency in `CConnman::DisconnectNode(const CNetAddr& addr)` and in `BanMan` which assume that creating a subnet from any address using the `CSubNet(CNetAddr)` constructor would later match that address only. Before this change a non-IP subnet would be invalid and would not match any address. ACKs for top commit: jonatack: Code review re-ACK 39b4329 per `git diff 5e95ce6 39b4329`; only change since last review is improvements to the functional test; verified the test fails on master @ 616eace where expected (`assert(self.is_banned(node, tor_addr))` fails and unban unfails) laanwj: code review ACK 39b4329 Tree-SHA512: 3239b26d0f2fa2d1388b4fdbc1d05ce4ac1980be699c6ec46049409baefcb2006b1e72b889871e2210e897f6725c48e873f68457eea7e6e4958ab4f959d20297
Allow creation of valid
CSubNet
objects of non-IP networks and onlymatch the single address they were created from (like /32 for IPv4 or
/128 for IPv6).
This fixes a deficiency in
CConnman::DisconnectNode(const CNetAddr& addr)
and in
BanMan
which assume that creating a subnet from any addressusing the
CSubNet(CNetAddr)
constructor would later match that addressonly. Before this change a non-IP subnet would be invalid and would not
match any address.