aws / s2n-quic

An implementation of the IETF QUIC protocol
https://crates.io/crates/s2n-quic
Apache License 2.0
1.17k stars 119 forks source link

Allow acessing the UDP socket to enable sidechannel messages for NAT hole punching #1608

Open Frando opened 1 year ago

Frando commented 1 year ago

Problem:

I'd like to use s2n_quic in a peer-to-peer scenario with UDP hole punching. Usually, a rendevouz server is used to tell a peer acting as a Server the addresses of other peers wanting to connect. The "server" peer then sends UDP packets to the peer's address, to open holes through their NAT. After a few packets, the socket is able to accept incoming connections from the peer. I have a demo that first hole-punches a UDP socket and then uses the same socket to construct a Server (through s2n_quic::provider::io::tokio::Builder::default().with_rx_socket(socket)?. This works fine and my server, which is behind a NAT, can accept connections from peers.

However after having punched a hole to the first peer, the UDP socket is passed to s2n_quic and then isn't accessible outside of the QUIC flow anymore. To accept further connections, I'd need to send more hole punching packets to other peers.

Solution:

A way to either access the raw UDP socket passed into s2n_quic, or a way to abstract over the raw socket, to handle hole punching messages there. The hole punching messages themselves can be anything socket.send_to(&[0u8], peer_addr) is fine.

For example, quinn provides a new_with_abstract_socket method that can be used to wrap a raw UDP socket and handle sending holepunching messages from the wrapper.

Requirements / Acceptance Criteria:

Out of scope:

camshaft commented 1 year ago

Are you able to use try_clone before passing the socket to s2n-quic?

Because we've released v1, abstracting the socket interface will lock us into the currently implemented features and make it more difficult to add new features in the future (at least without releasing a new major version, which we would really like to avoid).

dignifiedquire commented 1 year ago

I am working on a hole punching implementation that abstracts the UDPSocket entirely, as it might tunnel over a different protocol or use different sockets, depending on what is available. In quinn there is AsyncUdpSocket which allows me to abstract over the actual socket and inject my logic on how to handle the packets.