The WebRTC-based network protocol used in newer versions of Minecraft. It provides LAN discovery and secure peer-to-peer (P2P) connectivity.
nethernet- a pure sans-io implementation. It owns the wire formats, the identity assertions, the signaling state machines, and the WebRTC session itself (ICE, DTLS, SCTP, data channels, driven directly rather than through a generic peer connection), and performs no IO of its own, so it can be driven by any runtime.nethernet-tokio- an async tokio wrapper over the sans-io crate, exposingNetherServerandNetherClient.bevy-nethernet- a Bevy plugin wrapping the sans-io crate directly, for games that want to drive it from their own tick rather than through tokio.
- Secure communication over WebRTC (DTLS/SCTP)
- LAN server discovery, with retransmission of unanswered signals
- Signaling over LAN discovery or over the HTTP endpoint of a dedicated server, as a client and as a server
- Identity assertions: offers are validated against the fingerprints they carry, and answers are signed with the identity of the server
- Candidate inference for peers that gathered nothing a host on another network can reach
- Connection limits and trusted proxies on the HTTP endpoint
To build the project:
cargo build --releaseTo run the examples:
# NetherNet server
cargo run --example server -p nethernet-tokio
# NetherNet client
cargo run --example client -p nethernet-tokio
# List the servers advertising themselves on the local network
cargo run --example scanner -p nethernet-tokiolet signaling = HttpSignalingServer::bind(
"0.0.0.0:19132".parse()?,
HttpServerConfig {
network_id: "1234".to_string(),
tls: Some(nethernet_tokio::util::tls::from_pem("fullchain.pem", "key.pem").await?),
..Default::default()
},
)
.await?;
// Required for HTTP by default: NetherServer::bind_with fails with NetherError::IdentityRequired
// without it, unless ConnectionConfig::allow_unsigned_answers is set.
let identity = nethernet_tokio::util::identity::from_pem_or_create("identity.pem", "example.com").await?;
let config = ConnectionConfig {
identity: Some(Arc::new(identity)),
..Default::default()
};
let mut listener = NetherServer::bind_with(signaling, config).await?;
let AcceptedSession { session, .. } = listener.accept().await?;Answers are signed with the identity in ConnectionConfig::identity, which
nethernet_tokio::util::identity::from_pem_or_create loads from a PEM and creates on first
use. Clients pin that key, so it should be kept between restarts, and every answer must
carry one (guide section 5.2) - a vanilla client refuses the connection otherwise, whether
signaling ran over HTTPS or plaintext HTTP, so an HTTP server refuses to start without one by
default. A server that only serves non-vanilla clients, which do not verify answers, can opt out
with ConnectionConfig::allow_unsigned_answers; an identity that is set still signs. It stays
optional over LAN discovery. In bevy-nethernet, NetherHttpServer::set_identity is required
the same way and joins are answered with 503 until it is called, unless
NetherHttpServer::allow_unsigned_answers(true) opts out. Offers over
HTTP are validated against HttpSignalerConfig::token_trust alone, and ConnectionConfig::token_trust applies only to offers over LAN discovery. It
defaults to accepting any self-signed token while still binding it to the certificate the
peer presents. nethernet_tokio::util::jwks::Jwks::minecraft fetches the keys needed to
require a token issued by the Minecraft authorization service instead.
This project is licensed under the Apache License 2.0. See the LICENSE file for details.