mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
Fix secure tunnel session handling
This commit is contained in:
@@ -26,7 +26,6 @@ pub(crate) fn mount_public_support_routes(router: Router<AppState>) -> Router<Ap
|
||||
.route("/api/capabilities/model/{*model_path}", get(proxy_request))
|
||||
.route("/install/{*install_path}", get(proxy_request))
|
||||
.route("/install-tunnel/{*install_path}", get(proxy_request))
|
||||
.route("/install-proxy/{*install_path}", get(proxy_request))
|
||||
.route("/i/{*install_path}", get(proxy_request))
|
||||
.route("/", get(proxy_request))
|
||||
}
|
||||
|
||||
@@ -797,7 +797,6 @@ pub(super) fn classify_public_support_route(
|
||||
} else if method == http::Method::GET
|
||||
&& (has_single_segment_after_prefix(normalized_path, "/install/")
|
||||
|| has_single_segment_after_prefix(normalized_path, "/install-tunnel/")
|
||||
|| has_single_segment_after_prefix(normalized_path, "/install-proxy/")
|
||||
|| has_single_segment_after_prefix(normalized_path, "/i/"))
|
||||
{
|
||||
Some(classified(
|
||||
|
||||
@@ -16,7 +16,7 @@ const INSTALL_SESSION_TTL_SECS: u64 = 15 * 60;
|
||||
const INSTALL_SESSION_KEY_PREFIX: &str = "install:session:";
|
||||
const TUNNEL_INSTALL_SESSION_KEY_PREFIX: &str = "tunnel-install:session:";
|
||||
const TUNNEL_INSTALL_UNIX_SCRIPT_URL: &str =
|
||||
"https://raw.githubusercontent.com/fawney19/Aether/main/apps/aether-tunnel/install.sh";
|
||||
"https://raw.githubusercontent.com/fawney19/Aether/refs/heads/main/apps/aether-tunnel/install.sh";
|
||||
const TUNNEL_INSTALL_POWERSHELL_SCRIPT_URL: &str =
|
||||
"https://raw.githubusercontent.com/fawney19/Aether/main/apps/aether-tunnel/install.ps1";
|
||||
|
||||
@@ -95,8 +95,7 @@ fn install_code_from_path(request_path: &str) -> Option<(String, bool)> {
|
||||
|
||||
fn tunnel_install_code_from_path(request_path: &str) -> Option<(String, bool)> {
|
||||
let raw = request_path
|
||||
.strip_prefix("/install-tunnel/")
|
||||
.or_else(|| request_path.strip_prefix("/install-proxy/"))?
|
||||
.strip_prefix("/install-tunnel/")?
|
||||
.trim()
|
||||
.trim_matches('/');
|
||||
if raw.is_empty() || raw.contains('/') {
|
||||
@@ -735,9 +734,7 @@ pub(super) async fn maybe_build_local_install_response(
|
||||
if decision.route_family.as_deref() != Some("install") {
|
||||
return None;
|
||||
}
|
||||
if request_context.request_path.starts_with("/install-tunnel/")
|
||||
|| request_context.request_path.starts_with("/install-proxy/")
|
||||
{
|
||||
if request_context.request_path.starts_with("/install-tunnel/") {
|
||||
return Some(maybe_build_local_tunnel_install_response(state, request_context).await);
|
||||
}
|
||||
let Some((code, wants_powershell)) = install_code_from_path(&request_context.request_path)
|
||||
@@ -932,10 +929,6 @@ mod tests {
|
||||
tunnel_install_code_from_path("/install-tunnel/abc123.ps1"),
|
||||
Some(("abc123".to_string(), true))
|
||||
);
|
||||
assert_eq!(
|
||||
tunnel_install_code_from_path("/install-proxy/abc123"),
|
||||
Some(("abc123".to_string(), false))
|
||||
);
|
||||
assert_eq!(tunnel_install_code_from_path("/install-tunnel/a/b"), None);
|
||||
}
|
||||
|
||||
@@ -949,7 +942,7 @@ mod tests {
|
||||
assert!(script.contains("export AETHER_TUNNEL_SECURITY='non_tls_required'"));
|
||||
assert!(script.contains("export AETHER_TUNNEL_ENCRYPTION_KEY='base64-32-bytes'"));
|
||||
assert!(script.contains(
|
||||
"https://raw.githubusercontent.com/fawney19/Aether/main/apps/aether-tunnel/install.sh"
|
||||
"https://raw.githubusercontent.com/fawney19/Aether/refs/heads/main/apps/aether-tunnel/install.sh"
|
||||
));
|
||||
assert!(!script.contains("aether-rust-pioneer"));
|
||||
assert!(!script.contains("[[servers]]"));
|
||||
|
||||
@@ -90,7 +90,6 @@ fn frontend_path_bypasses_static(path: &str) -> bool {
|
||||
|| path.starts_with("/.well-known/")
|
||||
|| path.starts_with("/install/")
|
||||
|| path.starts_with("/install-tunnel/")
|
||||
|| path.starts_with("/install-proxy/")
|
||||
|| path.starts_with("/i/")
|
||||
}
|
||||
|
||||
|
||||
@@ -264,18 +264,23 @@ pub async fn ws_proxy(
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.unwrap_or(node_id.as_str())
|
||||
.to_string();
|
||||
.map(str::to_string);
|
||||
|
||||
if node_id.is_empty() {
|
||||
warn!("proxy connection rejected: missing X-Node-ID header");
|
||||
return axum::http::StatusCode::BAD_REQUEST.into_response();
|
||||
}
|
||||
let stored_security_key = state.secure_tunnel_key_for_node(&node_id).await;
|
||||
let security_key = match tunnel_security.as_deref() {
|
||||
let (security_key, security_session) = match tunnel_security.as_deref() {
|
||||
Some(aether_contracts::tunnel_security::TUNNEL_SECURITY_NON_TLS_REQUIRED) => {
|
||||
match stored_security_key {
|
||||
Some(key) => Some(key),
|
||||
Some(key) => {
|
||||
let Some(session) = security_session else {
|
||||
warn!(node_id = %node_id, "secure tunnel requested without a security session");
|
||||
return axum::http::StatusCode::BAD_REQUEST.into_response();
|
||||
};
|
||||
(Some(key), session)
|
||||
}
|
||||
None => {
|
||||
warn!(node_id = %node_id, "secure tunnel requested but no PSK is registered");
|
||||
return axum::http::StatusCode::UNAUTHORIZED.into_response();
|
||||
@@ -287,7 +292,7 @@ pub async fn ws_proxy(
|
||||
warn!(node_id = %node_id, "proxy connection rejected: stored secure tunnel key requires encrypted frames");
|
||||
return axum::http::StatusCode::UNAUTHORIZED.into_response();
|
||||
}
|
||||
None => None,
|
||||
None => (None, String::new()),
|
||||
};
|
||||
|
||||
let request_permit = match state.try_acquire_request_permit().await {
|
||||
|
||||
Reference in New Issue
Block a user