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

quic: private network support #1432

Open
Stebalien opened this issue Aug 13, 2019 · 12 comments
Open

quic: private network support #1432

Stebalien opened this issue Aug 13, 2019 · 12 comments
Labels
exp/expert Having worked on the specific codebase is important kind/enhancement A net-new feature or improvement to an existing feature

Comments

@Stebalien
Copy link
Member

Currently, the QUIC transport is incompatible with private networks as it doesn't use the pre-shared key in any way.

We have a couple of options:

  1. Implement the proposed TLS1.3 PSK extension: https://tools.ietf.org/html/draft-ietf-tls-tls13-cert-with-extern-psk-00. This allows mixing the pre-shared key with the result from the handshake.
  2. Add the ability to layer on some kind of trivial packet-based encryption protocol. We can use the same crypto as the current private network library as long as we use a new nonce per packet.
@marten-seemann
Copy link
Contributor

Implement the proposed TLS1.3 PSK extension: https://tools.ietf.org/html/draft-ietf-tls-tls13-cert-with-extern-psk-00. This allows mixing the pre-shared key with the result from the handshake.

We're in the unfortunate situation where the Go team effectively froze crypto/tls (with the exception of security-related bugfixes). It doesn't seem like they are planning to implement any new features.
quic-go already uses a fork of crypto/tls, however, I'd feel more confident in the security properties if we don't mess too much with the key schedule.

Add the ability to layer on some kind of trivial packet-based encryption protocol. We can use the same crypto as the current private network library as long as we use a new nonce per packet.

This is something we could do outside of quic-go. Effectively, we'd encrypt every QUIC packet that's being sent out. We'd either have to define a header that specifies the nonce of the packet, or use part of the QUIC packet payload as a nonce (for example the last 16 bytes of the packet, and leave those unencrypted). Aside from the obvious downside of double encryption, this would run against our efforts to make our traffic resemble commonly used internet protocols though.

@Stebalien
Copy link
Member Author

I'm leaning towards just encrypting each packet with a format: <nonce><enc-message><hmac>. That's what we do in go-libp2p-pnet (well, minus the MAC; we're relying on the actual transport for authentication in that case...).

@Stebalien
Copy link
Member Author

Having some form of private network (symmetric key) support in QUIC is needed before we can switch over to it by default. What's the status here? Can we mix in a symmetric key or are we going to have to introduce a packet-based pnet implementation?

@marten-seemann
Copy link
Contributor

There's not been any progress in Go's standard library TLS implementation, which we'd need to mix in symmetric keys.

Is there a third option here? Can we do the encryption on a stream level?

@Stebalien
Copy link
Member Author

Is there a third option here? Can we do the encryption on a stream level?

Not really. We'd leak the peer IDs at that point. We can probably find some kind of dead-simple symmetric-key encrypted packet transport. I'll ask on #libp2p to see if someone knows of a good one.

@marten-seemann
Copy link
Contributor

This might be a crazy idea. What about only encrypting the certificate (or the libp2p extension in the certificate)?

@Stebalien
Copy link
Member Author

That would definitely hide the peers. However:

  • That won't hide libp2p as the extension is well known.
  • That won't protect against, e.g., crypto breaks in the asymmetric crypto. I know that's kind of paranoid but I believe that's part of the point of this feature.

Thoughts @Kubuxu? You implemented the original version.

@marten-seemann
Copy link
Contributor

marten-seemann commented Jan 31, 2020

Another option would be to only encrypt Handshake packets. Let me explain:
QUIC uses different packet types during the Handshake:

  • Initial packets carry the ClientHello and ServerHello. They're obfuscated, but due to the lack of shared key material not encrypted.
  • Handshake packets carry the second flight of the TLS handshake.
  • 1-RTT packets carry all data exchanged after the handshake.

All packet types are identifiable from the wire image, i.e. no knowledge of the keys is necessary. Every packet type starts with a header, which, depending on the packet type, includes information like connection ID(s), QUIC version etc.

If we encrypt the payload (i.e. everything that comes after the QUIC header) of Handshake packets, we get the following properties:

  • We retain the wire image of QUIC, which might be useful in assisting middleboxes to let QUIC traffic through and to maintain NAT mappings.
  • A passive attacker cannot distinguish between a normal QUIC handshake and a private network QUIC handshake.

However, an active attacker would notice that something's going on when trying to dial such a peer, since it would receive undecryptable Handshake packets. That might allow him to conclude that the node might be using a private network. This applies to most of the other solutions as well though.

I'm not sure if I prefer this solution. Encrypting the libp2p extension still seems a bit cleaner to me than modifying already encrypted packets, if we can live with exposing the fact that a node is (probably) running in private network mode.

@marten-seemann
Copy link
Contributor

@Stebalien, @Kubuxu How can we move forward with this issue? Looks like we have a few different options, each with its pros and cons, and we need to make a decide which one we'll go with.

@marten-seemann
Copy link
Contributor

Copying from Slack. @raulk raised the following point:

The problem with encrypting only the certificate is that if I happen to get access to a node’s private TLS key (single-use or not, as per libp2p-tls spec), and I record the certificate sent in a handshake, I could replay the encrypted certificate as-is on a new connection, and I would’ve bypassed the PSK security entirely, and I’d be able to interact with any node in the pnet using only the private key I obtained.

(without ever knowing the PSK)

@Stebalien Stebalien added the kind/enhancement A net-new feature or improvement to an existing feature label Mar 27, 2021
@marten-seemann marten-seemann transferred this issue from libp2p/go-libp2p-quic-transport Apr 22, 2022
@marten-seemann marten-seemann added the exp/expert Having worked on the specific codebase is important label Apr 22, 2022
@marten-seemann marten-seemann changed the title Private network support quic: private network support Apr 22, 2022
@Kubuxu
Copy link
Member

Kubuxu commented Apr 25, 2022

Hey, I missed this. I will review in next few days.

@marten-seemann
Copy link
Contributor

@Kubuxu Nothing new here. I just moved the issue to go-libp2p because we've moved go-libp2p-quic-transport into go-libp2p. No idea why GitHub is sending out notifications for that :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
exp/expert Having worked on the specific codebase is important kind/enhancement A net-new feature or improvement to an existing feature
Projects
None yet
Development

No branches or pull requests

3 participants