Skip to content

Commit 17f30b1

Browse files
refactor!(iroh-net): remove relay secret key (#2847)
The `secret_key` configuration of the relay server was actually dead code at this point, this removes it from the config and all associated dead code. This also removes the need to write to the config file of the `iroh-relay`, making deployments easier to secure. ## Breaking Changes - removed - the `secret_key` property of the `iroh-relay` config - `iroh_net::relay::server::ServerActorTask::secret_key` - `iroh_net::relay::server::ServerActorTask::public_key` - `iroh_net::relay::server::ServerActorTask::meta_cert` - field `secret_key` in `iroh_net::relay::server::RelayConfig` - changed - `iroh_net::relay::server::ServerActorTask::new` now takes no arguments Closes #2845
1 parent 8f75005 commit 17f30b1

File tree

7 files changed

+40
-222
lines changed

7 files changed

+40
-222
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

iroh-net/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ axum = { version = "0.7.4", optional = true }
8181
clap = { version = "4", features = ["derive"], optional = true }
8282
regex = { version = "1.7.1", optional = true }
8383
rustls-pemfile = { version = "2.1", optional = true }
84-
serde_with = { version = "3.3", optional = true }
8584
toml = { version = "0.8", optional = true }
8685
tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true }
8786
tokio-rustls-acme = { version = "0.4", optional = true }
@@ -140,7 +139,6 @@ iroh-relay = [
140139
"dep:toml",
141140
"dep:rustls-pemfile",
142141
"dep:regex",
143-
"dep:serde_with",
144142
"dep:tracing-subscriber"
145143
]
146144
metrics = ["iroh-metrics/metrics"]

iroh-net/src/bin/iroh-relay.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ use anyhow::{anyhow, bail, Context as _, Result};
1212
use clap::Parser;
1313
use iroh_net::{
1414
defaults::{DEFAULT_HTTPS_PORT, DEFAULT_HTTP_PORT, DEFAULT_METRICS_PORT, DEFAULT_STUN_PORT},
15-
key::SecretKey,
1615
relay::server as iroh_relay,
1716
};
1817
use serde::{Deserialize, Serialize};
19-
use serde_with::{serde_as, DisplayFromStr};
2018
use tokio_rustls_acme::{caches::DirCache, AcmeConfig};
21-
use tracing::{debug, info};
19+
use tracing::debug;
2220
use tracing_subscriber::{prelude::*, EnvFilter};
2321

2422
/// The default `http_bind_port` when using `--dev`.
@@ -94,16 +92,8 @@ fn load_secret_key(
9492
/// Configuration for the relay-server.
9593
///
9694
/// This is (de)serialised to/from a TOML config file.
97-
#[serde_as]
9895
#[derive(Debug, Clone, Serialize, Deserialize)]
9996
struct Config {
100-
/// The iroh [`SecretKey`] for this relay server.
101-
///
102-
/// If not specified a new key will be generated and the config file will be re-written
103-
/// using it.
104-
#[serde_as(as = "DisplayFromStr")]
105-
#[serde(default = "SecretKey::generate")]
106-
secret_key: SecretKey,
10797
/// Whether to enable the Relay server.
10898
///
10999
/// Defaults to `true`.
@@ -178,7 +168,6 @@ impl Config {
178168
impl Default for Config {
179169
fn default() -> Self {
180170
Self {
181-
secret_key: SecretKey::generate(),
182171
enable_relay: true,
183172
http_bind_addr: None,
184173
tls: None,
@@ -321,10 +310,6 @@ impl Config {
321310
.await
322311
.context("unable to read config")?;
323312
let config: Self = toml::from_str(&config_ser).context("config file must be valid toml")?;
324-
if !config_ser.contains("secret_key") {
325-
info!("generating new secret key and updating config file");
326-
config.write_to_file(path).await?;
327-
}
328313

329314
Ok(config)
330315
}
@@ -430,7 +415,6 @@ async fn build_relay_config(cfg: Config) -> Result<iroh_relay::ServerConfig<std:
430415
.unwrap_or_default(),
431416
};
432417
let relay_config = iroh_relay::RelayConfig {
433-
secret_key: cfg.secret_key.clone(),
434418
http_bind_addr: cfg.http_bind_addr(),
435419
tls,
436420
limits,

iroh-net/src/relay/server.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ use tokio_util::task::AbortOnDropHandle;
2828
use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument};
2929

3030
use crate::{
31-
key::SecretKey,
3231
relay::http::{LEGACY_RELAY_PROBE_PATH, RELAY_PROBE_PATH},
3332
stun,
3433
};
@@ -50,7 +49,6 @@ pub use self::{
5049
const NO_CONTENT_CHALLENGE_HEADER: &str = "X-Tailscale-Challenge";
5150
const NO_CONTENT_RESPONSE_HEADER: &str = "X-Tailscale-Response";
5251
const NOTFOUND: &[u8] = b"Not Found";
53-
const RELAY_DISABLED: &[u8] = b"relay server disabled";
5452
const ROBOTS_TXT: &[u8] = b"User-agent: *\nDisallow: /\n";
5553
const INDEX: &[u8] = br#"<html><body>
5654
<h1>Iroh Relay</h1>
@@ -94,8 +92,6 @@ pub struct ServerConfig<EC: fmt::Debug, EA: fmt::Debug = EC> {
9492
/// endpoint is only one of the services served.
9593
#[derive(Debug)]
9694
pub struct RelayConfig<EC: fmt::Debug, EA: fmt::Debug = EC> {
97-
/// The iroh secret key of the Relay server.
98-
pub secret_key: SecretKey,
9995
/// The socket address on which the Relay HTTP server should bind.
10096
///
10197
/// Normally you'd choose port `80`. The bind address for the HTTPS server is
@@ -244,9 +240,7 @@ impl Server {
244240
None => relay_config.http_bind_addr,
245241
};
246242
let mut builder = http_server::ServerBuilder::new(relay_bind_addr)
247-
.secret_key(Some(relay_config.secret_key))
248243
.headers(headers)
249-
.relay_override(Box::new(relay_disabled_handler))
250244
.request_handler(Method::GET, "/", Box::new(root_handler))
251245
.request_handler(Method::GET, "/index.html", Box::new(root_handler))
252246
.request_handler(
@@ -518,16 +512,6 @@ async fn handle_stun_request(src_addr: SocketAddr, pkt: Vec<u8>, sock: Arc<UdpSo
518512
}
519513
}
520514

521-
fn relay_disabled_handler(
522-
_r: Request<Incoming>,
523-
response: ResponseBuilder,
524-
) -> HyperResult<Response<BytesBody>> {
525-
response
526-
.status(StatusCode::NOT_FOUND)
527-
.body(RELAY_DISABLED.into())
528-
.map_err(|err| Box::new(err) as HyperError)
529-
}
530-
531515
fn root_handler(
532516
_r: Request<Incoming>,
533517
response: ResponseBuilder,
@@ -712,7 +696,7 @@ mod tests {
712696

713697
use bytes::Bytes;
714698
use http::header::UPGRADE;
715-
use iroh_base::node_addr::RelayUrl;
699+
use iroh_base::{key::SecretKey, node_addr::RelayUrl};
716700

717701
use super::*;
718702
use crate::relay::{
@@ -723,7 +707,6 @@ mod tests {
723707
async fn spawn_local_relay() -> Result<Server> {
724708
Server::spawn(ServerConfig::<(), ()> {
725709
relay: Some(RelayConfig {
726-
secret_key: SecretKey::generate(),
727710
http_bind_addr: (Ipv4Addr::LOCALHOST, 0).into(),
728711
tls: None,
729712
limits: Default::default(),
@@ -752,7 +735,6 @@ mod tests {
752735
let _guard = iroh_test::logging::setup();
753736
let mut server = Server::spawn(ServerConfig::<(), ()> {
754737
relay: Some(RelayConfig {
755-
secret_key: SecretKey::generate(),
756738
http_bind_addr: (Ipv4Addr::LOCALHOST, 1234).into(),
757739
tls: None,
758740
limits: Default::default(),

iroh-net/src/relay/server/actor.rs

Lines changed: 17 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use tungstenite::protocol::Role;
2323

2424
use crate::{
2525
defaults::timeouts::relay::SERVER_WRITE_TIMEOUT as WRITE_TIMEOUT,
26-
key::{PublicKey, SecretKey},
26+
key::PublicKey,
2727
relay::{
2828
codec::{
2929
recv_client_key, DerpCodec, PER_CLIENT_SEND_QUEUE_DEPTH, PROTOCOL_VERSION,
@@ -58,10 +58,6 @@ pub struct ServerActorTask {
5858
/// Optionally specifies how long to wait before failing when writing
5959
/// to a client
6060
write_timeout: Option<Duration>,
61-
/// secret_key of the client
62-
secret_key: SecretKey,
63-
/// The DER encoded x509 cert to send after `LetsEncrypt` cert+intermediate.
64-
meta_cert: Vec<u8>,
6561
/// Channel on which to communicate to the [`ServerActor`]
6662
server_channel: mpsc::Sender<ServerMessage>,
6763
/// When true, the server has been shutdown.
@@ -73,37 +69,30 @@ pub struct ServerActorTask {
7369
// TODO: stats collection
7470
}
7571

76-
impl ServerActorTask {
77-
/// TODO: replace with builder
78-
pub fn new(key: SecretKey) -> Self {
72+
impl Default for ServerActorTask {
73+
fn default() -> Self {
7974
let (server_channel_s, server_channel_r) = mpsc::channel(SERVER_CHANNEL_SIZE);
80-
let server_actor = ServerActor::new(key.public(), server_channel_r);
75+
let server_actor = ServerActor::new(server_channel_r);
8176
let cancel_token = CancellationToken::new();
8277
let done = cancel_token.clone();
8378
let server_task = AbortOnDropHandle::new(tokio::spawn(
84-
async move { server_actor.run(done).await }
85-
.instrument(info_span!("relay.server", me = %key.public().fmt_short())),
79+
async move { server_actor.run(done).await }.instrument(info_span!("relay.server")),
8680
));
87-
let meta_cert = init_meta_cert(&key.public());
81+
8882
Self {
8983
write_timeout: Some(WRITE_TIMEOUT),
90-
secret_key: key,
91-
meta_cert,
9284
server_channel: server_channel_s,
9385
closed: false,
9486
loop_handler: server_task,
9587
cancel: cancel_token,
9688
}
9789
}
90+
}
9891

99-
/// Returns the server's secret key.
100-
pub fn secret_key(&self) -> &SecretKey {
101-
&self.secret_key
102-
}
103-
104-
/// Returns the server's public key.
105-
pub fn public_key(&self) -> PublicKey {
106-
self.secret_key.public()
92+
impl ServerActorTask {
93+
/// Creates a new default `ServerActorTask`.
94+
pub fn new() -> Self {
95+
Self::default()
10796
}
10897

10998
/// Closes the server and waits for the connections to disconnect.
@@ -142,17 +131,10 @@ impl ServerActorTask {
142131
pub fn client_conn_handler(&self, default_headers: HeaderMap) -> ClientConnHandler {
143132
ClientConnHandler {
144133
server_channel: self.server_channel.clone(),
145-
secret_key: self.secret_key.clone(),
146134
write_timeout: self.write_timeout,
147135
default_headers: Arc::new(default_headers),
148136
}
149137
}
150-
151-
/// Returns the server metadata cert that can be sent by the TLS server to
152-
/// let the client skip a round trip during start-up.
153-
pub fn meta_cert(&self) -> &[u8] {
154-
&self.meta_cert
155-
}
156138
}
157139

158140
/// Handle incoming connections to the Server.
@@ -163,7 +145,6 @@ impl ServerActorTask {
163145
#[derive(Debug)]
164146
pub struct ClientConnHandler {
165147
server_channel: mpsc::Sender<ServerMessage>,
166-
secret_key: SecretKey,
167148
write_timeout: Option<Duration>,
168149
pub(crate) default_headers: Arc<HeaderMap>,
169150
}
@@ -172,7 +153,6 @@ impl Clone for ClientConnHandler {
172153
fn clone(&self) -> Self {
173154
Self {
174155
server_channel: self.server_channel.clone(),
175-
secret_key: self.secret_key.clone(),
176156
write_timeout: self.write_timeout,
177157
default_headers: Arc::clone(&self.default_headers),
178158
}
@@ -236,17 +216,15 @@ impl ClientConnHandler {
236216
}
237217

238218
struct ServerActor {
239-
key: PublicKey,
240219
receiver: mpsc::Receiver<ServerMessage>,
241220
/// All clients connected to this server
242221
clients: Clients,
243222
client_counter: ClientCounter,
244223
}
245224

246225
impl ServerActor {
247-
fn new(key: PublicKey, receiver: mpsc::Receiver<ServerMessage>) -> Self {
226+
fn new(receiver: mpsc::Receiver<ServerMessage>) -> Self {
248227
Self {
249-
key,
250228
receiver,
251229
clients: Clients::new(),
252230
client_counter: ClientCounter::default(),
@@ -310,7 +288,7 @@ impl ServerActor {
310288

311289
report_usage_stats(&UsageStatsReport::new(
312290
"relay_accepts".to_string(),
313-
self.key.to_string(),
291+
"relay_server".to_string(), // TODO: other id?
314292
1,
315293
None, // TODO(arqu): attribute to user id; possibly with the re-introduction of request tokens or other auth
316294
Some(key.to_string()),
@@ -346,36 +324,6 @@ impl ServerActor {
346324
}
347325
}
348326

349-
/// Initializes the [`ServerActor`] with a self-signed x509 cert
350-
/// encoding this server's public key and protocol version. "cmd/relay_server
351-
/// then sends this after the Let's Encrypt leaf + intermediate certs after
352-
/// the ServerHello (encrypted in TLS 1.3, not that is matters much).
353-
///
354-
/// Then the client can save a round trime getting that and can start speaking
355-
/// relay right away. (we don't use ALPN because that's sent in the clear and
356-
/// we're being paranoid to not look too weird to any middleboxes, given that
357-
/// relay is an ultimate fallback path). But since the post-ServerHello certs
358-
/// are encrypted we can have the client also use them as a signal to be able
359-
/// to start speaking relay right away, starting with its identity proof,
360-
/// encrypted to the server's public key.
361-
///
362-
/// This RTT optimization fails where there's a corp-mandated TLS proxy with
363-
/// corp-mandated root certs on employee machines and TLS proxy cleans up
364-
/// unnecessary certs. In that case we just fall back to the extra RTT.
365-
fn init_meta_cert(server_key: &PublicKey) -> Vec<u8> {
366-
let mut params =
367-
rcgen::CertificateParams::new([format!("derpkey{}", hex::encode(server_key.as_bytes()))]);
368-
params.serial_number = Some((PROTOCOL_VERSION as u64).into());
369-
// Windows requires not_after and not_before set:
370-
params.not_after = time::OffsetDateTime::now_utc().saturating_add(30 * time::Duration::DAY);
371-
params.not_before = time::OffsetDateTime::now_utc().saturating_sub(30 * time::Duration::DAY);
372-
373-
rcgen::Certificate::from_params(params)
374-
.expect("fixed inputs")
375-
.serialize_der()
376-
.expect("fixed allocations")
377-
}
378-
379327
struct ClientCounter {
380328
clients: HashMap<PublicKey, usize>,
381329
last_clear_date: Date,
@@ -412,6 +360,7 @@ impl ClientCounter {
412360
#[cfg(test)]
413361
mod tests {
414362
use bytes::Bytes;
363+
use iroh_base::key::SecretKey;
415364
use tokio::io::DuplexStream;
416365
use tokio_util::codec::{FramedRead, FramedWrite};
417366
use tracing_subscriber::{prelude::*, EnvFilter};
@@ -446,11 +395,9 @@ mod tests {
446395

447396
#[tokio::test]
448397
async fn test_server_actor() -> Result<()> {
449-
let server_key = SecretKey::generate().public();
450-
451398
// make server actor
452399
let (server_channel, server_channel_r) = mpsc::channel(20);
453-
let server_actor: ServerActor = ServerActor::new(server_key, server_channel_r);
400+
let server_actor: ServerActor = ServerActor::new(server_channel_r);
454401
let done = CancellationToken::new();
455402
let server_done = done.clone();
456403

@@ -518,7 +465,6 @@ mod tests {
518465
let (server_channel_s, mut server_channel_r) = mpsc::channel(10);
519466
let client_key = SecretKey::generate();
520467
let handler = ClientConnHandler {
521-
secret_key: client_key.clone(),
522468
write_timeout: None,
523469
server_channel: server_channel_s,
524470
default_headers: Default::default(),
@@ -580,8 +526,7 @@ mod tests {
580526
let _guard = iroh_test::logging::setup();
581527

582528
// create the server!
583-
let server_key = SecretKey::generate();
584-
let server: ServerActorTask = ServerActorTask::new(server_key);
529+
let server: ServerActorTask = ServerActorTask::new();
585530

586531
// create client a and connect it to the server
587532
let key_a = SecretKey::generate();
@@ -656,8 +601,7 @@ mod tests {
656601
.ok();
657602

658603
// create the server!
659-
let server_key = SecretKey::generate();
660-
let server: ServerActorTask = ServerActorTask::new(server_key);
604+
let server: ServerActorTask = ServerActorTask::new();
661605

662606
// create client a and connect it to the server
663607
let key_a = SecretKey::generate();

0 commit comments

Comments
 (0)