feat: optional TLS for P2P connections (#1420) - #3907
Conversation
| max_peer_attempts / 2 - new_peers.len() + max_peer_attempts / 4, | ||
| max_peer_attempts / 4, | ||
| ); | ||
| // When TLS is required, skip unknown peers — we only know TLS support after a successful handshake. |
There was a problem hiding this comment.
Unknown state is valid for all new peers that are coming from peer list request
There was a problem hiding this comment.
Agreed — fixed in the rebase. Unknown peers from peer-list responses are dialed again so handshake can discover TLS (and other) capabilities. tls_required only filters peers that already have stored capabilities (healthy/defunct) via accepts_outbound_peer_capabilities.
wiesche89
left a comment
There was a problem hiding this comment.
please fix merge conflicts
Encrypt peer traffic with rustls for privacy against passive observers. TLS is opt-in via p2p_config.tls_enabled (default false) so the existing plaintext network remains compatible. When enabled, peers use self-signed certificates (auto-generated under the node data dir if paths are not set) and clients intentionally skip certificate authentication — encryption for privacy only, matching the issue intent. Wire a plain/TLS Stream abstraction through handshake, codec, and conn I/O, and add an integration test for TLS peer handshake + ping/pong.
Advertise Capabilities::TLS when tls_enabled so peers can discover encrypted endpoints. Add tls_required to filter outbound attempts and peer-list requests to TLS-capable peers (seeds/preferred/allow still used for bootstrap).
iho
left a comment
There was a problem hiding this comment.
Rebased onto current staging and resolved conflicts in servers/src/grin/seed.rs and servers/src/grin/server.rs.
Also addressed @ardocrat's note: State::Unknown peers from peer-list requests are dialed again under tls_required (capabilities are only known after handshake). Preferred-peer handling from staging is preserved.
cargo test -p grin_p2p and cargo check -p grin_config -p grin_servers pass.
P2P TLS introduced Stream; seedcheck still passed TcpStream and broke the bin test build (Linux src / macOS CI).
Summary
Implements optional TLS for peer-to-peer connections (#1420).
p2p_config.tls_enabled(defaultfalse) so the existing plaintext network stays compatible{data_dir}/p2p_tls/when paths are not configuredtls_certificate_file/tls_certificate_keygrin-server.tomltemplatePeer discovery:
Capabilities::TLS+tls_requiredCapabilities::TLS(0b1_0000_0000), advertised whentls_enabled = truep2p_config.tls_required(defaultfalse): when set withtls_enabled, only attempt outbound connections to peers known to advertise TLS, and requestPEER_LIST | TLSin peer-list queriestls_requiredis onDesign notes
Streamabstraction wraps plainTcpStreamor a mutex-shared rustls session (needed because reader/writer threads cannottry_clonea TLS session the way they do TCP)How to enable
Testing
cargo test -p grin_p2p(includespeer_handshake_tls, capability /tls_requiredhelpers)cargo check -p grin_config -p grin_serverstls_enabled = trueconnecting on testnet/localConsensus / compatibility
tls_required = true, automatic outbound selection prefers the TLS peer mesh once capabilities are knownCloses #1420