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

feat: verify expected PeerId as part of security handshake #4864

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

denis2glez
Copy link

@denis2glez denis2glez commented Nov 14, 2023

Description

During a handshake, certificates should be verified in order to allow the connection attempt to be aborted during the security handshake (by security protocols such as TLS or Noise). This requires being able to verify the peer ID after the handshake. Otherwise, we will have abnormal behaviors, such as aborting after completing the handshake and leaving the peer not knowing what went wrong.

Fixes: #2946.
Related: #4307.
Related: #4726.
Related: #882.

Tasks

  • Introduce the InboundSecurityUpgrade/OutboundSecurityUpgrade traits that should be implemented by transports such as Noise or TLS.
  • Create the Builder::authenticate2 function to accept an upgrade that implements this traits.
  • Implement a state machine inupgrade::secure that calls the InboundSecurityUpgrade/OutboundSecurityUpgrade traits instead of InboundConnectionUpgrade / OutboundConnectionUpgrade.
  • Implement the InboundSecurityUpgrade/OutboundSecurityUpgrade traits for Noise and TLS transports, repectively.
  • Complete the missing parts.
  • Include unit tests.
  • Make appropriate changes to the docs.

Notes & open questions

@denis2glez denis2glez changed the title feat: Verification of the expected PeerId as part of a protocol handshake. feat: Verification of expected PeerId during protocol handshake. Nov 15, 2023
Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

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

Great start!

We'll need to implement the new trait for libp2p-tls and libp2p-noise.

core/src/upgrade.rs Outdated Show resolved Hide resolved
core/src/upgrade/secure.rs Outdated Show resolved Hide resolved
core/src/upgrade/secure.rs Outdated Show resolved Hide resolved
core/src/transport/upgrade.rs Outdated Show resolved Hide resolved
core/src/transport/upgrade.rs Show resolved Hide resolved
@denis2glez
Copy link
Author

Thanks for the suggestions!

Introduce `Builder::authenticate2` as an alternative code path given
the supplied upgrade implements `SecurityUpgrade` instead of
`InboundConnectionUpgrade`/`OutboundConnectionUpgrade`.

Inline `secure_inbound` and `secure_outound` functions into `secure`.

Fix `PeerId` in the output of `SecurityUpgrade::upgrade_security`.

Remove the unnecessary call to `panic`.

Co-authored-by: Thomas Eizinger
core/src/upgrade.rs Outdated Show resolved Hide resolved
Use an owned dynamically typed `Future` that is `Send`
(i.e. `BoxFuture`).
Introduce `InboundSecurityUpgrade`/`OutboundSecurityUpgrade` instead.
Implement the `InboundSecurityUpgrade`/`OutboundSecurityUpgrade` traits
for the TLS transport verifying the expected peer ID on outgoing upgrades.
Implement the `InboundSecurityUpgrade`/`OutboundSecurityUpgrade` traits
for the Noise transport verifying the expected peer ID on outgoing upgrades.
Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

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

That looks great!

I've left some more comments. Can you also please use authenticate2 within the SwarmBuilder in the libp2p crate?

core/src/upgrade.rs Outdated Show resolved Hide resolved
transports/noise/src/lib.rs Outdated Show resolved Hide resolved
transports/tls/src/upgrade.rs Outdated Show resolved Hide resolved
The optional `PeerId` parameter in a security upgrade is never known
at this point for an inbound connection.
Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

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

Good progress! I've left a few more comments :)

core/src/transport/upgrade.rs Outdated Show resolved Hide resolved
core/src/transport/upgrade.rs Outdated Show resolved Hide resolved
core/src/upgrade.rs Outdated Show resolved Hide resolved
core/src/upgrade/secure.rs Outdated Show resolved Hide resolved
transports/noise/src/lib.rs Outdated Show resolved Hide resolved
transports/noise/src/lib.rs Outdated Show resolved Hide resolved
transports/noise/src/lib.rs Outdated Show resolved Hide resolved
core/src/upgrade.rs Outdated Show resolved Hide resolved
@thomaseizinger thomaseizinger changed the title feat: Verification of expected PeerId during protocol handshake. feat: verify expected PeerId as part of security handshake Nov 19, 2023
Delegate the implementations of `InboundConnectionUpgrade`/`OutboundConnectionUpgrade`
traits to `InboundSecurityUpgrade`/`OutboundSecurityUpgrade` for Noise and TLS.
The `PeerId` coming from the address is the remote `PeerId` and the one from the handshake is the actual `PeerId`.
Introduce the `with_remote_peer_id` constructor in `Config`.
@thomaseizinger
Copy link
Contributor

thomaseizinger commented Nov 27, 2023

Can you also please use authenticate2 within the SwarmBuilder in the libp2p crate?

In addition to the above comments, this is also still an open item. So far, we are not using those APIs anywhere, meaning we don't actually get to benefit from the new handshake. You'll have to find the usage sites of the current authenticate function within the SwarmBuilder and use authenticate2 instead. Your IDE should be of great assistance here or alternatively, you can mark the old as deprecated and run the compiler once.

Here is one of the usages sites:

.authenticate(
security_upgrade.into_security_upgrade(&self.keypair)?,
)

The `PeerId` coming from the address is the expected `PeerId`
and the one from the handshake is the actual `PeerId`.
@denis2glez
Copy link
Author

Can you also please use authenticate2 within the SwarmBuilder in the libp2p crate?

In addition to the above comments, this is also still an open item. So far, we are not using those APIs anywhere, meaning we don't actually get to benefit from the new handshake. You'll have to find the usage sites of the current authenticate function within the SwarmBuilder and use authenticate2 instead. Your IDE should be of great assistance here or alternatively, you can mark the old as deprecated and run the compiler once.

Here is one of the usages sites:

.authenticate(
security_upgrade.into_security_upgrade(&self.keypair)?,
)

Thanks, I was already working on this.

Explicitly call `make_server_config` and `make_client_config` as part of the upgrade.
@thomaseizinger
Copy link
Contributor

Thanks, I was already working on this.

Awesome! Let me know when you want another review! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider verifying expected PeerId as part of auth upgrades
2 participants