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

p2p: Don't use timestamps from inbound peers for Adjusted Time #23631

Merged
merged 1 commit into from
Dec 7, 2021

Conversation

mzumsande
Copy link
Contributor

GetAdjustedTime() (used e.g. in validation and addrman) returns a time with an offset that is influenced by timestamps that our peers have sent us in their version message.

Currently, timestamps from all peers are used for this.
However, I think that it would make sense to ignore the timedata samples from inbound peers, making it much harder for others to influence the Adjusted Time in a targeted way.
With the extra feeler connections (every 2 minutes on average) and extra block-relay-only connections (every 5 minutes on average) there are also now plenty of opportunities to gather a meaningful number of timedata samples from outbound peers.

There are some measures in place to prevent abuse: the -maxtimeadjustment parameter with a default of 70 minutes, warnings in cases of large deviations, only using the first 200 samples (explanation), but I think that only using samples from outbound connections in the first place would be an additional safety measure that would make sense.

See also issue #4521 for further context and links: There have been several discussions in the past about replacing or abolishing the existing timedata system.

This makes it harder for others to tamper with
our adjusted time.
@sipa
Copy link
Member

sipa commented Nov 29, 2021

Concept ACK

@fanquake fanquake added the P2P label Nov 29, 2021
@maflcko
Copy link
Member

maflcko commented Nov 30, 2021

Is this fixing #6071 ?

@mzumsande
Copy link
Contributor Author

Is this fixing #6071 ?

Yes I think so, with SPV clients being inbound peers.

@vasild
Copy link
Contributor

vasild commented Dec 1, 2021

Concept ACK

I have been thinking "what could go wrong with this?" but can't find a realistic adverse scenario. Need to stare a bit more at the surrounding code before full ACK.

What about this - a node fails to create outgoing connections while incoming connections arrive just fine (could happen due to a firewall or some other network mishap (intentional or not) or addrman filled with junk). Many incoming connections arrive from honest nodes with correct times, which are ignored. How realistic is that? Is it worth considering an extension of this patch that starts collecting time samples from incoming connections if none or very few samples have been collected from outgoing connections for a long time after startup?

@mzumsande
Copy link
Contributor Author

mzumsande commented Dec 1, 2021

What about this - a node fails to create outgoing connections while incoming connections arrive just fine (could happen due to a firewall or some other network mishap (intentional or not) or addrman filled with junk). Many incoming connections arrive from honest nodes with correct times, which are ignored. How realistic is that?

I've never heard of someone in this situation this before, maybe others have?
It seems hard to get into this, after all outbound connections must have worked at some point in the past to broadcast our address to the network before others would connect to us. Plus, the lack of timedata samples could only cause potential problems if on top of all this, our system time is seriously off.

Is it worth considering an extension of this patch that starts collecting time samples from incoming connections if none or very few samples have been collected from outgoing connections for a long time after startup?

My first reaction was that this situation is so unlikely that it wouldn't be worth the extra complexity, but I'd love to hear other opinions!

Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tentative Concept ACK. The motivation sounds good to me although i'm not very familiar with this code.

@jnewbery
Copy link
Contributor

jnewbery commented Dec 2, 2021

Concept and code review ACK 0c85dc3

Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 0c85dc3

Is it worth considering an extension of this patch...

Probably not.

@@ -2683,7 +2683,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,

int64_t nTimeOffset = nTime - GetTime();
pfrom.nTimeOffset = nTimeOffset;
AddTimeData(pfrom.addr, nTimeOffset);
if (!pfrom.IsInboundConn()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, feel free to ignore: there is already if (!pfrom.IsInboundConn()) { just a few lines above and the nTimeOffset local variable seems unnecessary.

dont click here
--- i/src/net_processing.cpp
+++ w/src/net_processing.cpp
@@ -2657,47 +2657,48 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
         if (!pfrom.IsInboundConn()) {
             // For non-inbound connections, we update the addrman to record
             // connection success so that addrman will have an up-to-date
             // notion of which peers are online and available.
             //
             // While we strive to not leak information about block-relay-only
             // connections via the addrman, not moving an address to the tried
             // table is also potentially detrimental because new-table entries
             // are subject to eviction in the event of addrman collisions.  We
             // mitigate the information-leak by never calling
             // AddrMan::Connected() on block-relay-only peers; see
             // FinalizeNode().
             //
             // This moves an address from New to Tried table in Addrman,
             // resolves tried-table collisions, etc.
             m_addrman.Good(pfrom.addr);
+
+            // Don't use timedata samples from inbound peers to make it
+            // harder for others to tamper with our adjusted time.
+            pfrom.nTimeOffset = nTime - GetTime();
+            AddTimeData(pfrom.addr, pfrom.nTimeOffset);
         }

         std::string remoteAddr;
         if (fLogIPs)
             remoteAddr = ", peeraddr=" + pfrom.addr.ToString();

         LogPrint(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s\n",
                   cleanSubVer, pfrom.nVersion,
                   peer->m_starting_height, addrMe.ToString(), fRelay, pfrom.GetId(),
                   remoteAddr);

-        int64_t nTimeOffset = nTime - GetTime();
-        pfrom.nTimeOffset = nTimeOffset;
-        AddTimeData(pfrom.addr, nTimeOffset);
-
         // If the peer is old enough to have the old alert system, send it the final alert.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That suggested patch would leave pfrom.nTimeOffset unset for inbound peers, which in turn would mean that timeoffset is unset in the node stats.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right!

@naumenkogs
Copy link
Member

I think the justification makes sense and the code is good. This is an improvement.
ACK 0c85dc3

What about this - a node fails to create outgoing connections while incoming connections arrive just fine (could happen due to a firewall or some other network mishap (intentional or not) or addrman filled with junk). Many incoming connections arrive from honest nodes with correct times, which are ignored. How realistic is that? Is it worth considering an extension of this patch that starts collecting time samples from incoming connections if none or very few samples have been collected from outgoing connections for a long time after startup?

Yeah, it's hard for me to imagine this, I can only see this happen if Addrman is attacked in a very severe way sometime during node uptime. And even in that case i don't think this current approach can help much.

@fanquake fanquake merged commit e457513 into bitcoin:master Dec 7, 2021
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Dec 7, 2021
… Adjusted Time

0c85dc3 p2p: Don't use timestamps from inbound peers (Martin Zumsande)

Pull request description:

  `GetAdjustedTime()` (used e.g. in validation and addrman) returns a time with an offset that is influenced by timestamps that our peers have sent us in their version message.

  Currently, timestamps from all peers are used for this.
  However, I think that it would make sense to ignore the timedata samples from inbound peers, making it much harder for others to influence the Adjusted Time in a targeted way.
  With the extra feeler connections (every 2 minutes on average) and extra block-relay-only connections (every 5 minutes on average) there are also now plenty of opportunities to gather a meaningful number of timedata samples from outbound peers.

  There are some measures in place to prevent abuse: the `-maxtimeadjustment` parameter with a default of 70 minutes, warnings in cases of large deviations, only using the first 200 samples ([explanation](https://github.com/bitcoin/bitcoin/blob/383d350bd5107bfe00e3b90a00cab9a3c1397c72/src/timedata.cpp#L57-L72)), but I think that only using samples from outbound connections in the first place would be an additional safety measure that would make sense.

  See also issue bitcoin#4521 for further context and links: There have been several discussions in the past about replacing or abolishing the existing timedata system.

ACKs for top commit:
  jnewbery:
    Concept and code review ACK 0c85dc3
  naumenkogs:
    ACK 0c85dc3
  vasild:
    ACK 0c85dc3

Tree-SHA512: 2d6375305bcae034d68b58b7a07777b40ac430dfed554c88e681a048c527536691e1b7d08c0ef995247d356f8e81aa0a4b983bf2674faf6a416264e5f1af0a96
@mzumsande mzumsande deleted the 202111_timedata_inbound branch December 8, 2021 15:53
RandyMcMillan pushed a commit to RandyMcMillan/mempool-tab that referenced this pull request Dec 23, 2021
…eers for Adjusted Time

04f4770 p2p: Don't use timestamps from inbound peers (Martin Zumsande)

Pull request description:

  `GetAdjustedTime()` (used e.g. in validation and addrman) returns a time with an offset that is influenced by timestamps that our peers have sent us in their version message.

  Currently, timestamps from all peers are used for this.
  However, I think that it would make sense to ignore the timedata samples from inbound peers, making it much harder for others to influence the Adjusted Time in a targeted way.
  With the extra feeler connections (every 2 minutes on average) and extra block-relay-only connections (every 5 minutes on average) there are also now plenty of opportunities to gather a meaningful number of timedata samples from outbound peers.

  There are some measures in place to prevent abuse: the `-maxtimeadjustment` parameter with a default of 70 minutes, warnings in cases of large deviations, only using the first 200 samples ([explanation](https://github.com/bitcoin/bitcoin/blob/b63551cc4a6cda8f7af3ad5560b97cdb14ce5b67/src/timedata.cpp#L57-L72)), but I think that only using samples from outbound connections in the first place would be an additional safety measure that would make sense.

  See also issue #4521 for further context and links: There have been several discussions in the past about replacing or abolishing the existing timedata system.

ACKs for top commit:
  jnewbery:
    Concept and code review ACK 04f4770
  naumenkogs:
    ACK 04f4770
  vasild:
    ACK 04f4770

Tree-SHA512: 2d6375305bcae034d68b58b7a07777b40ac430dfed554c88e681a048c527536691e1b7d08c0ef995247d356f8e81aa0a4b983bf2674faf6a416264e5f1af0a96
Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posthumous ACK 0c85dc3

-maxtimeadjustment should be updated with this change; done in #24609.

maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request Mar 18, 2022
…ers influence timedata

1bba72d Clarify in -maxtimeadjustment that only outbound peers influence time data (Jon Atack)

Pull request description:

  bitcoin#23631 changed our adjusted time to only take into account time from outbound peers.

  Update `-maxtimeadjustment` to clarify this for users.

ACKs for top commit:
  MarcoFalke:
    cr ACK 1bba72d
  mzumsande:
    code Review ACK 1bba72d
  brunoerg:
    crACK 1bba72d

Tree-SHA512: ad610ab3038fb83134e21d31cca952ef9ac926e88992ff93023b7010f2499f9a4d952e8e98a0ec56f8949872d966e5ffdd01a81e6b6115768f1992bd81be7a56
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Mar 18, 2022
…ers influence timedata

1bba72d Clarify in -maxtimeadjustment that only outbound peers influence time data (Jon Atack)

Pull request description:

  bitcoin#23631 changed our adjusted time to only take into account time from outbound peers.

  Update `-maxtimeadjustment` to clarify this for users.

ACKs for top commit:
  MarcoFalke:
    cr ACK 1bba72d
  mzumsande:
    code Review ACK 1bba72d
  brunoerg:
    crACK 1bba72d

Tree-SHA512: ad610ab3038fb83134e21d31cca952ef9ac926e88992ff93023b7010f2499f9a4d952e8e98a0ec56f8949872d966e5ffdd01a81e6b6115768f1992bd81be7a56
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Mar 17, 2023
Summary:
> This makes it harder for others to tamper with our adjusted time.

Rationale from the PR description:
> With the extra feeler connections (every 2 minutes on average) and extra block-relay-only connections (every 5 minutes on average) there are also now plenty of opportunities to gather a meaningful number of timedata samples from outbound peers.
>
> There are some measures in place to prevent abuse: the -maxtimeadjustment parameter with a default of 70 minutes, warnings in cases of large deviations, only using the first 200 samples (explanation), but I think that only using samples from outbound connections in the first place would be an additional safety measure that would make sense.
>
> See also issue [[bitcoin/bitcoin#4521 | core#4521]] for further context and links: There have been several discussions in the past about replacing or abolishing the existing timedata system.

The difference with the source material is caused by D6024. This changes previous behavior slightly: now the computed time offset is assigned to the node even if we are not going to use it to compute our adjusted time. This `pfrom.nTimeOffset` is only used for display purposes (RPC results, GUI).

This is a backport of [[bitcoin/bitcoin#23631 | core#23631]]

Depends on D13357

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D13357
@bitcoin bitcoin locked and limited conversation to collaborators Mar 18, 2023
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.

9 participants