@@ -275,10 +275,41 @@ async fn run_daemon(config_path: &std::path::Path) -> anyhow::Result<()> { |
| 275 | 275 | let peers: Arc<RwLock<HashMap<Direction, network::FramedConnection>>> = |
| 276 | 276 | Arc::new(RwLock::new(HashMap::new())); |
| 277 | 277 | |
| 278 | + // TLS setup (if enabled) |
| 279 | + let tls_enabled = config.network.tls.enabled; |
| 280 | + if tls_enabled { |
| 281 | + info!("TLS is enabled, ensuring certificates exist..."); |
| 282 | + let cert_path = std::path::Path::new(&config.network.tls.cert_path); |
| 283 | + let key_path = std::path::Path::new(&config.network.tls.key_path); |
| 284 | + |
| 285 | + if let Err(e) = network::ensure_certificate(cert_path, key_path, &config.machines.self_name) { |
| 286 | + anyhow::bail!("Failed to setup TLS certificates: {}", e); |
| 287 | + } |
| 288 | + |
| 289 | + // Print certificate fingerprint for users to share |
| 290 | + match network::get_cert_fingerprint(cert_path) { |
| 291 | + Ok(fp) => { |
| 292 | + info!("Certificate fingerprint: {}", fp); |
| 293 | + info!("Share this fingerprint with peers for secure verification"); |
| 294 | + } |
| 295 | + Err(e) => { |
| 296 | + tracing::warn!("Could not read certificate fingerprint: {}", e); |
| 297 | + } |
| 298 | + } |
| 299 | + } else { |
| 300 | + info!("TLS is disabled (plain TCP mode for backwards compatibility)"); |
| 301 | + } |
| 302 | + |
| 278 | 303 | // Start network server |
| 279 | 304 | let listen_addr: SocketAddr = format!("0.0.0.0:{}", config.network.listen_port).parse()?; |
| 280 | | - let server = network::Server::bind(listen_addr).await?; |
| 281 | | - info!("Listening for connections on {}", server.local_addr()); |
| 305 | + let server = if tls_enabled { |
| 306 | + let cert_path = std::path::Path::new(&config.network.tls.cert_path); |
| 307 | + let key_path = std::path::Path::new(&config.network.tls.key_path); |
| 308 | + network::Server::bind_tls(listen_addr, cert_path, key_path).await? |
| 309 | + } else { |
| 310 | + network::Server::bind(listen_addr).await? |
| 311 | + }; |
| 312 | + info!("Listening for connections on {} (TLS: {})", server.local_addr(), tls_enabled); |
| 282 | 313 | |
| 283 | 314 | // Spawn task to accept incoming connections |
| 284 | 315 | let machine_name = config.machines.self_name.clone(); |
@@ -355,6 +386,13 @@ async fn run_daemon(config_path: &std::path::Path) -> anyhow::Result<()> { |
| 355 | 386 | let direction = neighbor.direction; |
| 356 | 387 | let peers_clone = peers.clone(); |
| 357 | 388 | let machine_name = config.machines.self_name.clone(); |
| 389 | + let neighbor_name = neighbor.name.clone(); |
| 390 | + |
| 391 | + // Determine if TLS should be used for this neighbor |
| 392 | + // Per-neighbor override takes precedence over global setting |
| 393 | + let use_tls = neighbor.tls.unwrap_or(tls_enabled); |
| 394 | + let fingerprint = neighbor.fingerprint.clone(); |
| 395 | + let tofu_enabled = config.network.tls.tofu; |
| 358 | 396 | |
| 359 | 397 | tokio::spawn(async move { |
| 360 | 398 | loop { |
@@ -369,8 +407,21 @@ async fn run_daemon(config_path: &std::path::Path) -> anyhow::Result<()> { |
| 369 | 407 | } |
| 370 | 408 | } |
| 371 | 409 | |
| 372 | | - tracing::debug!("Connecting to {} at {}...", direction, addr); |
| 373 | | - match network::connect(addr).await { |
| 410 | + tracing::debug!("Connecting to {} at {} (TLS: {})...", direction, addr, use_tls); |
| 411 | + |
| 412 | + // Connect with or without TLS |
| 413 | + let conn_result = if use_tls { |
| 414 | + network::connect_tls( |
| 415 | + addr, |
| 416 | + &neighbor_name, |
| 417 | + fingerprint.as_deref(), |
| 418 | + tofu_enabled, |
| 419 | + ).await |
| 420 | + } else { |
| 421 | + network::connect(addr).await |
| 422 | + }; |
| 423 | + |
| 424 | + match conn_result { |
| 374 | 425 | Ok(mut conn) => { |
| 375 | 426 | // Send Hello |
| 376 | 427 | let hello = Message::Hello(HelloPayload { |
@@ -1695,8 +1746,21 @@ async fn run_daemon(config_path: &std::path::Path) -> anyhow::Result<()> { |
| 1695 | 1746 | let peers_clone = peers.clone(); |
| 1696 | 1747 | let machine_name = config.machines.self_name.clone(); |
| 1697 | 1748 | let neighbor_name = n.name.clone(); |
| 1749 | + |
| 1750 | + // Determine TLS settings for this neighbor |
| 1751 | + let use_tls = n.tls.unwrap_or(tls_enabled); |
| 1752 | + let fingerprint = n.fingerprint.clone(); |
| 1753 | + let tofu = config.network.tls.tofu; |
| 1754 | + |
| 1698 | 1755 | tokio::spawn(async move { |
| 1699 | | - match network::connect(addr).await { |
| 1756 | + // Connect with or without TLS |
| 1757 | + let conn_result = if use_tls { |
| 1758 | + network::connect_tls(addr, &neighbor_name, fingerprint.as_deref(), tofu).await |
| 1759 | + } else { |
| 1760 | + network::connect(addr).await |
| 1761 | + }; |
| 1762 | + |
| 1763 | + match conn_result { |
| 1700 | 1764 | Ok(mut conn) => { |
| 1701 | 1765 | // Send Hello |
| 1702 | 1766 | let hello = Message::Hello(HelloPayload { |