Skip to content
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

Prevent peer flooding inv request queue (redux) (redux) #7079

Merged
merged 2 commits into from Dec 1, 2015
Merged

Prevent peer flooding inv request queue (redux) (redux) #7079

merged 2 commits into from Dec 1, 2015

Conversation

gmaxwell
Copy link
Contributor

@gmaxwell gmaxwell commented Nov 23, 2015

Currently it's possible for peers to send duplicate invs of the same object and push the inv request time far back.

PR #4547 sought to address this, but was closed with the expectation that it would be replaced by the more comprehensive #4831 but the latter hasn't yet reached escape velocity. I agree a comprehensive rework is better, but I think we should not let a simple improvement wait for that.

PR #6306 tried a simpler version, but by reusing the setInventoryKnown it gets the logic somewhat wrong, e.g. not allowing duplicate INVs even for objects we'd mempool retired but now would be accept again.

Here I bring back #4547 and add size limiting and make an important change to the logic (which I believe was originally flawed, though no one seems to have commented on that in the original PR):

The earlier PR would remove the suppression as soon as the getdata was requested, rather than removing it when response was returned. This one removes only when we decide to not getdata (because we already have) or when the getdata returns. This means that a peer can only have one in-flight INV for a particular tx at once; which is what we want.

kazcw and others added 2 commits Nov 23, 2015
mapAlreadyAskedFor does not keep track of which peer has a request queued for a
particular tx. As a result, a peer can blind a node to a tx indefinitely by
sending many invs for the same tx, and then never replying to getdatas for it.
Each inv received will be placed 2 minutes farther back in mapAlreadyAskedFor,
so a short message containing 10 invs would render that tx unavailable for 20
minutes.

This is fixed by disallowing a peer from having more than one entry for a
particular inv in mapAlreadyAskedFor at a time.
…rns.

The setAskFor duplicate elimination was too eager and removed entries
 when we still had no getdata response, allowing the peer to keep
 INVing and not responding.
@laanwj laanwj added the P2P label Nov 24, 2015
@laanwj
Copy link
Member

laanwj commented Nov 24, 2015

concept ACK

@laanwj laanwj added this to the 0.12.0 milestone Nov 24, 2015
@dgenr8
Copy link
Contributor

dgenr8 commented Nov 25, 2015

e.g. not allowing duplicate INVs even for objects we'd mempool retired but now would be accept again.

That's a bug in CTxMemPool::Expire. It should clean the tx out of all setInventoryKnowns anyway, else we won't try to re-inv it to peers when it comes in again.

@gmaxwell
Copy link
Contributor Author

gmaxwell commented Nov 25, 2015

@dgenr8 I don't think it is, or at least it's debatable... we won't reinv to peers we already INVed it to-- they may well still have it-- we should still reinv to anyone we haven't.

@dcousens
Copy link
Contributor

dcousens commented Nov 25, 2015

concept ACK

@dgenr8
Copy link
Contributor

dgenr8 commented Nov 25, 2015

@gmaxwell Ah well, as long as the attack is mitigated. It's also possible to drop the timeout to 20s (from 2m) and only miss a response 1% of the time. .4% at 30s.

@gmaxwell
Copy link
Contributor Author

gmaxwell commented Nov 25, 2015

The timeouts must be set very conservatively or otherwise a congested node (e.g. one under dos attack) can exhaust itself with repeated transmissions. You cannot count on the average case measured on a node with good connectivity.

I'm also not particularly interested if someone-- with a bunch of work-- can delay a transaction by a couple minutes; it's not a very interesting attack compared to self congestion collapse (which can happen absent any attacker at all). 2 minutes is the appropriate scaling from the 20 minute value used elsewhere, with respect to a the maximum size standard transaction being 1/10th the block size.

@sipa
Copy link
Member

sipa commented Nov 26, 2015

Untested ACK

@laanwj
Copy link
Member

laanwj commented Nov 30, 2015

utACK

@laanwj laanwj merged commit ebb25f4 into bitcoin:master Dec 1, 2015
laanwj added a commit that referenced this pull request Dec 1, 2015
ebb25f4 Limit setAskFor and retire requested entries only when a getdata returns. (Gregory Maxwell)
5029698 prevent peer flooding request queue for an inv (kazcw)
luke-jr pushed a commit to luke-jr/bitcoin that referenced this pull request Jan 10, 2016
mapAlreadyAskedFor does not keep track of which peer has a request queued for a
particular tx. As a result, a peer can blind a node to a tx indefinitely by
sending many invs for the same tx, and then never replying to getdatas for it.
Each inv received will be placed 2 minutes farther back in mapAlreadyAskedFor,
so a short message containing 10 invs would render that tx unavailable for 20
minutes.

This is fixed by disallowing a peer from having more than one entry for a
particular inv in mapAlreadyAskedFor at a time.

Github-Pull: bitcoin#7079
Rebased-From: 5029698
luke-jr pushed a commit to luke-jr/bitcoin that referenced this pull request Jan 10, 2016
…rns.

The setAskFor duplicate elimination was too eager and removed entries
 when we still had no getdata response, allowing the peer to keep
 INVing and not responding.

Github-Pull: bitcoin#7079
Rebased-From: ebb25f4
luke-jr pushed a commit to luke-jr/bitcoin that referenced this pull request Jan 10, 2016
mapAlreadyAskedFor does not keep track of which peer has a request queued for a
particular tx. As a result, a peer can blind a node to a tx indefinitely by
sending many invs for the same tx, and then never replying to getdatas for it.
Each inv received will be placed 2 minutes farther back in mapAlreadyAskedFor,
so a short message containing 10 invs would render that tx unavailable for 20
minutes.

This is fixed by disallowing a peer from having more than one entry for a
particular inv in mapAlreadyAskedFor at a time.

Github-Pull: bitcoin#7079
Rebased-From: 5029698
luke-jr pushed a commit to luke-jr/bitcoin that referenced this pull request Jan 10, 2016
…rns.

The setAskFor duplicate elimination was too eager and removed entries
 when we still had no getdata response, allowing the peer to keep
 INVing and not responding.

Github-Pull: bitcoin#7079
Rebased-From: ebb25f4
zkbot pushed a commit to zcash/zcash that referenced this pull request Sep 20, 2016
Upstream patch: Prevent peer flooding inv request queue

bitcoin/bitcoin#7079
5029698
ebb25f4
Fuzzbawls added a commit to Fuzzbawls/Mintcoin-Desktop-Wallet that referenced this pull request Sep 26, 2016
Merge some upstream commits that add
better handling of the header/block
download logic.

Includes:

Reduce download timeouts as blocks arrive
bitcoin/bitcoin#5976

Prevent peer flooding inv request queue
bitcoin/bitcoin#7079
random-zebra added a commit to PIVX-Project/PIVX that referenced this pull request Jun 9, 2021
fcdf87a Populate services in GetLocalAddress (Alex Morcos)
a0a079f Return early in IsBanned. (Gregory Maxwell)
7772138 Remove redundant nullptr checks before deallocation (practicalswift)
5390862 net: remove unimplemented functions. (furszy)
74d0482 Limit setAskFor and retire requested entries only when a getdata returns. (Gregory Maxwell)
3b3bf63 prevent peer flooding request queue for an inv (kazcw)
c814967 Fix subscript[0] potential bugs in key.cpp (Jeremy Rubin)
8e2e79e Remove unnecessary branches in utilstrencodings string constructors. (Jeremy Rubin)
25a16b3 Fix subscript[0] in utilstrencodings.cpp (Jeremy Rubin)
df0584e Fix subscript[0] in streams.h (Jeremy Rubin)
b7e64a5 Fix subscript[0] in validation.cpp (Jeremy Rubin)
2f7b73b Fix subscript[0] in torcontrol (Jeremy Rubin)
3b883eb Fix subscript[0] in netaddress.cpp (Jeremy Rubin)
e5f5401 Fix subscript[0] in base58.cpp (Jeremy Rubin)
7d4ec87 Cleanup (safe, it was checked) subscript[0] in MurmurHash3 (and cleanup MurmurHash3 to be more clear). (Jeremy Rubin)
5e14f54 Fix subscript[0] in compressor.cpp (Jeremy Rubin)
48a622d Fix subscript[0] bug in net.cpp if GetGroup returns a 0-sized vector (Jeremy Rubin)
af4cba3 net: use an internal address for fixed seeds (Cory Fields)
36368c5 net: switch to dummy internal ip for dns seed source (Cory Fields)
8f31295 net: do not allow resolving to an internal address (Cory Fields)
8ba3a40 net: add an internal subnet for representing unresolved hostnames (Cory Fields)
c60b875 fix uninitialized read when stringifying an addrLocal (Kaz Wesley)
3d36540 add test demonstrating addrLocal UB (Kaz Wesley)

Pull request description:

  Grouped some net updates (plus a miscellaneous one) coming from upstream.
  Part of another deep rabbit hole that i'm doing in parallel of the tier two work.

  PRs List:
  * bitcoin#7079.
  * bitcoin#9804.
  * bitcoin#10424
  * bitcoin#10446.
  * bitcoin#10564.
  * bitcoin#14728.

ACKs for top commit:
  random-zebra:
    Code ACK fcdf87a

Tree-SHA512: ee81c834641aa6fdb9ca4396657457358a4b32f7862d60716e914dcfc2d355970937bd0fb4e164faaa0f4ea26d263ca8a2af4d8d5d6615b2db5bf89ec70d15f3
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants