Allow configurable tunnel IP address for server

This commit introduces a new option to specify the IP address where tunnels
will listen, which may be different from the control server's IP address.

A new flag `--tunnels-addr` can specify the IP addr to bind to. Default is set
to `0.0.0.0` which is the previous behavior.
This commit is contained in:
confor
2025-04-14 01:18:03 -04:00
parent aa0d6e0ae5
commit 2a2541e866
2 changed files with 13 additions and 4 deletions

View File

@@ -51,6 +51,10 @@ enum Command {
/// IP address for the control server. Bore clients must reach this address. /// IP address for the control server. Bore clients must reach this address.
#[clap(long, default_value = "0.0.0.0")] #[clap(long, default_value = "0.0.0.0")]
control_addr: String, control_addr: String,
/// IP address where tunnels will listen on.
#[clap(long, default_value = "0.0.0.0")]
tunnels_addr: String,
}, },
} }
@@ -72,6 +76,7 @@ async fn run(command: Command) -> Result<()> {
max_port, max_port,
secret, secret,
control_addr, control_addr,
tunnels_addr,
} => { } => {
let port_range = min_port..=max_port; let port_range = min_port..=max_port;
if port_range.is_empty() { if port_range.is_empty() {
@@ -79,7 +84,7 @@ async fn run(command: Command) -> Result<()> {
.error(ErrorKind::InvalidValue, "port range is empty") .error(ErrorKind::InvalidValue, "port range is empty")
.exit(); .exit();
} }
Server::new(port_range, secret.as_deref(), control_addr).listen().await?; Server::new(port_range, secret.as_deref(), control_addr, tunnels_addr).listen().await?;
} }
} }

View File

@@ -26,17 +26,21 @@ pub struct Server {
/// IP address for the control server. Bore clients must reach this address. /// IP address for the control server. Bore clients must reach this address.
control_addr: String, control_addr: String,
/// IP address where tunnels will listen on.
tunnels_addr: String,
} }
impl Server { impl Server {
/// Create a new server with a specified minimum port number. /// Create a new server with a specified minimum port number.
pub fn new(port_range: RangeInclusive<u16>, secret: Option<&str>, control_addr: String) -> Self { pub fn new(port_range: RangeInclusive<u16>, secret: Option<&str>, control_addr: String, tunnels_addr: String) -> Self {
assert!(!port_range.is_empty(), "must provide at least one port"); assert!(!port_range.is_empty(), "must provide at least one port");
Server { Server {
port_range, port_range,
conns: Arc::new(DashMap::new()), conns: Arc::new(DashMap::new()),
auth: secret.map(Authenticator::new), auth: secret.map(Authenticator::new),
control_addr: control_addr, control_addr,
tunnels_addr,
} }
} }
@@ -65,7 +69,7 @@ impl Server {
async fn create_listener(&self, port: u16) -> Result<TcpListener, &'static str> { async fn create_listener(&self, port: u16) -> Result<TcpListener, &'static str> {
let try_bind = |port: u16| async move { let try_bind = |port: u16| async move {
TcpListener::bind(("0.0.0.0", port)) TcpListener::bind((self.tunnels_addr.as_ref(), port))
.await .await
.map_err(|err| match err.kind() { .map_err(|err| match err.kind() {
io::ErrorKind::AddrInUse => "port already in use", io::ErrorKind::AddrInUse => "port already in use",