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

Implement TLS security protocol including early muxer negotiation #283

Merged
merged 38 commits into from
May 31, 2023

Conversation

ianopolous
Copy link
Contributor

@ianopolous ianopolous commented May 24, 2023

Early muxer negotiation is when the security protocol handshake is used to negotiate the muxer to avoid a round trip. In TLS this is done using ALPN. It is not implemented for Noise here.

This also includes a few small changes:

  1. Remove the insecure Secio from builders so it can't be accidentally included
  2. Upgrade to Java 17 which is required for Ed25519 TLS certs
  3. Expose the event loop on Streams which we needed to implement p2p http proxies in Nabu

Part of #272

@ianopolous
Copy link
Contributor Author

ianopolous commented May 24, 2023

I've just noticed the old yamux changes got in there somehow. This was already my second attempt at cherry-picking onto v1.0.0.
Edit I've fixed it.

@Nashatyrev
Copy link
Collaborator

@ianopolous thanks for another contribution 👍

Some questions here:

  • is that PR possible without switching to Java 17? We are potentially considering upgrading the lib to Java 17 at some point, however if possible I would prefer make that transition in a separate PR.
    • Maybe BouncyCastle Ed25519 implementation could be used instead of JDK?
    • Is it possible to make Ed25519 support pluggable?
    • As the last resort: could Ed25519 support be omitted for now?
  • Could you please explain usecases for the eventLoop()? We were trying originally to keep Netty API exposure as minimal as possible. Exposing the Netty EventLoop (which is not quite a basic api) via generic Stream looks slightly painful for me.

I'm planning to revisit early muxer handshake concept and probably make a separate PR for introducing it

@ianopolous
Copy link
Contributor Author

I think I'm most of the way to removing the need for java 17. I've pushed it to a new branch: https://github.com/Peergos/jvm-libp2p/tree/feat/upstream-tls-java-11

However I can't get gradle to find the new bouncy castle jar (which is in maven central like the rest). Any chance you could have a look @Nashatyrev ?

@Nashatyrev
Copy link
Collaborator

However I can't get gradle to find the new bouncy castle jar (which is in maven central like the rest).

Wouldn't that help?

Index: versions.gradle
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/versions.gradle b/versions.gradle
--- a/versions.gradle	(revision d4eb98c8bd4d6ae86eca228c35682b2da9edf9b7)
+++ b/versions.gradle	(date 1685016596704)
@@ -40,6 +40,7 @@
         dependencySet(group: "org.bouncycastle", version: "1.70") {
             entry 'bcprov-jdk15on'
             entry 'bcpkix-jdk15on'
+            entry 'bctls-jdk15on'
         }
     }
 }

@ianopolous
Copy link
Contributor Author

Thank you @Nashatyrev. It's building and running in that java11 branch. But I can't get it to work. It just times out getting the Ping controller. Any chance you could have a look?

I'm testing using HostTestJava and running Kubo locally (You'll need to change the Peerid in the test if you run it)

@Nashatyrev
Copy link
Collaborator

Do you mean it doesn't work with TLS security, but works with others?
Or did it stop working after switching to BC TLS implementation?

@ianopolous
Copy link
Contributor Author

ianopolous commented May 25, 2023

The test is specifically for TLS (If I switch to Noise it is fine). It is working in this branch on java 17, but not in the java 11 branch with BC.

I'm running it locally, along with Kubo.

@ianopolous
Copy link
Contributor Author

ianopolous commented May 26, 2023

I think https://github.com/Peergos/jvm-libp2p/tree/feat/upstream-tls-java-11 is quite close. It works fine Java to Java using Ed25519 certs using BouncyCastle. Talking to Kubo (which uses ECDSA over P-256) the TLS handshake completes, but a subsequent protocol select times out.

@Nashatyrev
Copy link
Collaborator

@ianopolous
You may want to try adding debug wire loggers:

beforeSecureHandler.addHandler(beforeSecureTestHandler1)
afterSecureHandler.addHandler(afterSecureTestHandler1)
streamPreHandler.addHandler(preStreamTestHandler1)
streamHandler.addHandler(streamTestHandler1)
muxFramesHandler.addHandler(muxFrameTestHandler1)

Just use addLogger() instead of addHandler()

@ianopolous
Copy link
Contributor Author

ianopolous commented May 26, 2023

@Nashatyrev Is that possible from the Java Host test?

Don't worry, I'll use the Kotlin one.

@ianopolous
Copy link
Contributor Author

ianopolous commented May 26, 2023

The plot thickens. Running HostTestJava to Kubo works with {Noise + (mplex or yamux)}, but fails with TLS

However, if I disable early muxer negotiation, then TLS works! So it's possible we broke early muxer with some of the upstream changes??

EDIT: Nope. It runs fine on this branch. So that likely means there is something wrong with Bouncy Castle ALPN...

BINGO! I've got it. It was a bug in Netty's interaction with BC for ALPN. Updating Netty fixes it!

@ianopolous
Copy link
Contributor Author

@Nashatyrev Ok. We're now good with Java 11.

The use for the EventLoop is a p2p http proxy. It accepts incoming libp2p connections and proxies it to a fixed http endpoint or http handler. We needed access to the eventloop to add the new http handlers when receiving a new connection: https://github.com/Peergos/nabu/blob/master/src/main/java/org/peergos/protocol/http/HttpProtocol.java#L103

ianopolous added 16 commits May 26, 2023 15:40
Todo:
* muxer negotiation via client hello info
* verify remote certs
Implemented full trust manager

TODO:
* Muxer negotiation in client hello info
* close stream on cipher error
Remove Secio from defaults!!

Kubo still drops us during handshake
Mark certificate extension as critical
Don't remove the SetupHandler before adding the TLS handler.
@ianopolous ianopolous force-pushed the feat/upstream-tls branch from 86c808a to d3ed41e Compare May 26, 2023 14:44
@Nashatyrev
Copy link
Collaborator

@Nashatyrev Ok. We're now good with Java 11.

Great news! Thanks!
Sorry I'm still on the way with the early muxer negotiation integration

The use for the EventLoop is a p2p http proxy. It accepts incoming libp2p connections and proxies it to a fixed http endpoint or http handler. We needed access to the eventloop to add the new http handlers when receiving a new connection: https://github.com/Peergos/nabu/blob/master/src/main/java/org/peergos/protocol/http/HttpProtocol.java#L103

Sorry, I didn't dive deeply into the usage case above.
Anyway I would suggest to discuss that eventLoop question in a separate PR/Issue

@ianopolous
Copy link
Contributor Author

ianopolous commented May 30, 2023

@Nashatyrev I've removed the EventLoop stuff from this PR. Are you planning on PRing your early muxer stuff into this branch?

EDIT somehow those two reverts have lost the work to support java 11. Ugh. FIXED

@ianopolous ianopolous force-pushed the feat/upstream-tls branch from 11f68f4 to 115dbac Compare May 30, 2023 13:35
ApplicationProtocolConfig.Protocol.ALPN,
ApplicationProtocolConfig.SelectorFailureBehavior.FATAL_ALERT,
ApplicationProtocolConfig.SelectedListenerFailureBehavior.FATAL_ALERT,
muxerIds.plus("libp2p") // early muxer negotiation
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need adding "libp2p" here?
Just doing some minor refactoring and curious if it would be the same effect if we don't add this value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is for compatibility with clients that do not support early muxer negotiation (they just send "libp2p"). So definitely necessary.

…puxer protocol, pass a list of StreamMuxers to constructor. SecureChannel.Session contains NegotiatedStreamMuxer instance instead of string protocol representation
Copy link
Collaborator

@Nashatyrev Nashatyrev left a comment

Choose a reason for hiding this comment

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

Basically LGTM. Just please consider some minor refactor here: Peergos#9

I'm still slightly concerned with SecureChannel.Session.earlyMuxer property. It has a transient nature and is not intended to be exposed in the API. But I'm planning to address it later in a separate PR to not block further upstream work

Nashatyrev and others added 2 commits May 31, 2023 16:22
@Nashatyrev Nashatyrev merged commit de42c11 into libp2p:v1.0.0 May 31, 2023
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.

2 participants