From aa0d6e0ae5508f127acfa255cd11e31fc4d7ffa1 Mon Sep 17 00:00:00 2001 From: confor Date: Mon, 14 Apr 2025 00:59:38 -0400 Subject: [PATCH] Allow configurable control server bind address This commit adds the ability to bind the control server to a specific network interface via an additional flag `--control-addr`. By default it listens on `0.0.0.0` which is the previous behaviour. --- src/main.rs | 7 ++++++- src/server.rs | 13 ++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3432c08..9d7b81f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,6 +47,10 @@ enum Command { /// Optional secret for authentication. #[clap(short, long, env = "BORE_SECRET", hide_env_values = true)] secret: Option, + + /// IP address for the control server. Bore clients must reach this address. + #[clap(long, default_value = "0.0.0.0")] + control_addr: String, }, } @@ -67,6 +71,7 @@ async fn run(command: Command) -> Result<()> { min_port, max_port, secret, + control_addr, } => { let port_range = min_port..=max_port; if port_range.is_empty() { @@ -74,7 +79,7 @@ async fn run(command: Command) -> Result<()> { .error(ErrorKind::InvalidValue, "port range is empty") .exit(); } - Server::new(port_range, secret.as_deref()).listen().await?; + Server::new(port_range, secret.as_deref(), control_addr).listen().await?; } } diff --git a/src/server.rs b/src/server.rs index de3158c..6240323 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,6 +1,6 @@ //! Server implementation for the `bore` service. -use std::{io, net::SocketAddr, ops::RangeInclusive, sync::Arc, time::Duration}; +use std::{io, ops::RangeInclusive, sync::Arc, time::Duration}; use anyhow::Result; use dashmap::DashMap; @@ -23,25 +23,28 @@ pub struct Server { /// Concurrent map of IDs to incoming connections. conns: Arc>, + + /// IP address for the control server. Bore clients must reach this address. + control_addr: String, } impl Server { /// Create a new server with a specified minimum port number. - pub fn new(port_range: RangeInclusive, secret: Option<&str>) -> Self { + pub fn new(port_range: RangeInclusive, secret: Option<&str>, control_addr: String) -> Self { assert!(!port_range.is_empty(), "must provide at least one port"); Server { port_range, conns: Arc::new(DashMap::new()), auth: secret.map(Authenticator::new), + control_addr: control_addr, } } /// Start the server, listening for new connections. pub async fn listen(self) -> Result<()> { let this = Arc::new(self); - let addr = SocketAddr::from(([0, 0, 0, 0], CONTROL_PORT)); - let listener = TcpListener::bind(&addr).await?; - info!(?addr, "server listening"); + let listener = TcpListener::bind((this.control_addr.as_ref(), CONTROL_PORT)).await?; + info!(?this.control_addr, "server listening"); loop { let (stream, addr) = listener.accept().await?;