Gate non-loopback remote binds
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled

This commit is contained in:
DuProcess
2026-06-14 09:10:09 -04:00
parent fb5c25ea0b
commit 6c14d669b8
3 changed files with 28 additions and 4 deletions
+1
View File
@@ -506,6 +506,7 @@ native_auth_rate_limit_per_minute = 30
attach_ticket_ttl_secs = 86400
allow_tcp_forwarding = true
allow_remote_forwarding = false
allow_remote_non_loopback_bind = false
allow_agent_forwarding = false
accept_env = ["LANG", "LC_*", "TERM", "COLORTERM"]
```
+24 -4
View File
@@ -1443,10 +1443,7 @@ async fn start_remote_forwards(
.bind_host
.clone()
.unwrap_or_else(|| "127.0.0.1".to_string());
anyhow::ensure!(
is_loopback_bind(&bind_host),
"remote forwarding may only bind loopback in this server build"
);
remote_bind_allowed(&config, &bind_host)?;
let listen_port = forward.listen_port;
let target_host = forward
.target_host
@@ -1547,6 +1544,16 @@ fn is_loopback_bind(host: &str) -> bool {
matches!(host, "127.0.0.1" | "localhost" | "::1")
}
fn remote_bind_allowed(config: &ServerConfig, host: &str) -> Result<()> {
if !is_loopback_bind(host) {
anyhow::ensure!(
config.allow_remote_non_loopback_bind,
"remote forwarding non-loopback bind disabled"
);
}
Ok(())
}
fn stream_open_allowed(
config: &ServerConfig,
client: &ClientState,
@@ -2151,4 +2158,17 @@ mod tests {
assert_eq!(data.stream_id, 42);
assert_eq!(data.bytes, b"hello");
}
#[test]
fn remote_non_loopback_bind_requires_explicit_config() {
let config = ServerConfig::default();
remote_bind_allowed(&config, "127.0.0.1").unwrap();
assert!(remote_bind_allowed(&config, "0.0.0.0").is_err());
let config = ServerConfig {
allow_remote_non_loopback_bind: true,
..ServerConfig::default()
};
remote_bind_allowed(&config, "0.0.0.0").unwrap();
}
}
+3
View File
@@ -33,6 +33,8 @@ pub struct ServerConfig {
#[serde(default)]
pub allow_remote_forwarding: bool,
#[serde(default)]
pub allow_remote_non_loopback_bind: bool,
#[serde(default)]
pub allow_agent_forwarding: bool,
#[serde(default = "default_accept_env")]
pub accept_env: Vec<String>,
@@ -61,6 +63,7 @@ impl Default for ServerConfig {
native_auth_rate_limit_per_minute: default_native_auth_rate_limit_per_minute(),
allow_tcp_forwarding: true,
allow_remote_forwarding: false,
allow_remote_non_loopback_bind: false,
allow_agent_forwarding: false,
accept_env: default_accept_env(),
}