diff --git a/client/src/plugin/tls_term.rs b/client/src/plugin/tls_term.rs index a5c9660..1eee4fc 100644 --- a/client/src/plugin/tls_term.rs +++ b/client/src/plugin/tls_term.rs @@ -11,7 +11,6 @@ use tokio_rustls::TlsAcceptor; pub struct TlsTermPlugin { local_addr: String, host_header_rewrite: String, - request_headers: Vec<(String, String)>, acceptor: TlsAcceptor, } @@ -30,13 +29,6 @@ impl TlsTermPlugin { let tls_cfg = load_or_generate_https_server_config(&cfg.cert_file, &cfg.key_file, &cn)?; let acceptor = TlsAcceptor::from(tls_cfg); - let request_headers: Vec<(String, String)> = cfg - .request_headers - .set - .iter() - .map(|(k, v)| (k.clone(), v.clone())) - .collect(); - tracing::info!( tunnel = %ctx.name, %local_addr, @@ -47,7 +39,6 @@ impl TlsTermPlugin { Ok(Self { local_addr, host_header_rewrite: cfg.host_header_rewrite.clone(), - request_headers, acceptor, }) } @@ -73,7 +64,7 @@ impl Plugin for TlsTermPlugin { let (mut tls_r, mut tls_w) = tokio::io::split(tls); let mut head = read_http_request_head(&mut tls_r).await?; - apply_request_rewrites(&mut head, &self.host_header_rewrite, &self.request_headers)?; + apply_host_rewrite(&mut head, &self.host_header_rewrite)?; orbien_core::net::apply_x_forwarded_for(&mut head, &conn.src_addr, "https")?; local.write_all(&head).await?; @@ -114,11 +105,11 @@ async fn read_http_request_head(stream: &mut R) -> Resu } } -fn apply_request_rewrites( - buf: &mut Vec, - host_rewrite: &str, - extra_headers: &[(String, String)], -) -> Result<()> { +fn apply_host_rewrite(buf: &mut Vec, host_rewrite: &str) -> Result<()> { + if host_rewrite.is_empty() { + return Ok(()); + } + let text = String::from_utf8_lossy(buf); let mut lines: Vec = text.split_inclusive('\n').map(|s| s.to_string()).collect(); if lines.is_empty() { @@ -131,27 +122,17 @@ fn apply_request_rewrites( "\n" }; - if !host_rewrite.is_empty() { - let mut replaced = false; - for line in lines.iter_mut().skip(1) { - let trimmed = line.trim_start_matches([' ', '\t']); - if trimmed.len() >= 5 && trimmed.as_bytes()[..5].eq_ignore_ascii_case(b"host:") { - *line = format!("Host: {host_rewrite}{ending}"); - replaced = true; - break; - } - } - if !replaced { - lines.insert(1, format!("Host: {host_rewrite}{ending}")); + let mut replaced = false; + for line in lines.iter_mut().skip(1) { + let trimmed = line.trim_start_matches([' ', '\t']); + if trimmed.len() >= 5 && trimmed.as_bytes()[..5].eq_ignore_ascii_case(b"host:") { + *line = format!("Host: {host_rewrite}{ending}"); + replaced = true; + break; } } - - for (k, v) in extra_headers { - let blank_idx = lines - .iter() - .position(|l| l == "\r\n" || l == "\n") - .unwrap_or(lines.len()); - lines.insert(blank_idx, format!("{k}: {v}{ending}")); + if !replaced { + lines.insert(1, format!("Host: {host_rewrite}{ending}")); } *buf = lines.join("").into_bytes(); diff --git a/conf/orbien-full.toml b/conf/orbien-full.toml index 0fb4d9a..d1dcab1 100644 --- a/conf/orbien-full.toml +++ b/conf/orbien-full.toml @@ -90,10 +90,6 @@ certFile = "./certs/portal.crt" keyFile = "./certs/portal.key" hostHeaderRewrite = "127.0.0.1" -[tunnels.plugin.requestHeaders.set] -X-Forwarded-Proto = "https" -X-Orbien-Tunnel = "portal" - [[tunnels]] name = "socks5" protocol = "tcp" diff --git a/core/src/config/client.rs b/core/src/config/client.rs index e451eb4..647bc1c 100644 --- a/core/src/config/client.rs +++ b/core/src/config/client.rs @@ -170,21 +170,12 @@ pub struct PluginConfig { #[serde(default, rename = "hostHeaderRewrite", alias = "host_header_rewrite")] pub host_header_rewrite: String, - #[serde(default, rename = "requestHeaders", alias = "request_headers")] - pub request_headers: PluginRequestHeaders, - #[serde(default)] pub username: String, #[serde(default)] pub password: String, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] -pub struct PluginRequestHeaders { - #[serde(default)] - pub set: std::collections::HashMap, -} - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] pub struct TunnelTransportConfig { #[serde(default)] diff --git a/core/src/config/mod.rs b/core/src/config/mod.rs index 626c372..a7ea8f2 100644 --- a/core/src/config/mod.rs +++ b/core/src/config/mod.rs @@ -3,7 +3,7 @@ mod env; mod server; pub use client::{ - ClientConfig, ClientTlsConfig, PluginConfig, PluginRequestHeaders, TransportConfig, + ClientConfig, ClientTlsConfig, PluginConfig, TransportConfig, TunnelConfig, TunnelTransportConfig, }; pub use env::{contains_env_placeholders, expand_env_placeholders}; diff --git a/desktop/i18n/en_US.properties b/desktop/i18n/en_US.properties index 48cbfc0..f1ee198 100644 --- a/desktop/i18n/en_US.properties +++ b/desktop/i18n/en_US.properties @@ -57,8 +57,6 @@ tunnel-tls-term=TLS terminate tunnel-plugin-local-addr=Local address tunnel-plugin-cert=Certificate path tunnel-plugin-key=Key path -tunnel-plugin-request-headers=Extra request headers -tunnel-plugin-request-headers-hint=e.g. X-From: orbien, comma-separated tunnel-plugin-username=Username tunnel-plugin-password=Password tunnel-copied=Copied to clipboard diff --git a/desktop/i18n/zh_CN.properties b/desktop/i18n/zh_CN.properties index 58398ee..d4d1f18 100644 --- a/desktop/i18n/zh_CN.properties +++ b/desktop/i18n/zh_CN.properties @@ -55,8 +55,6 @@ tunnel-tls-term=TLS 终止 tunnel-plugin-local-addr=本地地址 tunnel-plugin-cert=证书路径 tunnel-plugin-key=私钥路径 -tunnel-plugin-request-headers=追加请求头 -tunnel-plugin-request-headers-hint=如 X-From: orbien,多项逗号分隔 tunnel-plugin-username=用户名 tunnel-plugin-password=密码 tunnel-copied=已复制到剪贴板 diff --git a/desktop/src/config_bridge.rs b/desktop/src/config_bridge.rs index abb8763..4ba68bc 100644 --- a/desktop/src/config_bridge.rs +++ b/desktop/src/config_bridge.rs @@ -1,10 +1,9 @@ use anyhow::{anyhow, Context, Result}; use orbien_client::ClientConfig; use orbien_core::config::{ - parse_host_port, ClientTlsConfig, PluginConfig, PluginRequestHeaders, TransportConfig, - TunnelConfig, TunnelTransportConfig, + parse_host_port, ClientTlsConfig, PluginConfig, TransportConfig, TunnelConfig, + TunnelTransportConfig, }; -use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; @@ -298,35 +297,6 @@ fn split_csv(raw: &str) -> Vec { .collect() } -fn parse_request_headers(raw: &str) -> PluginRequestHeaders { - let mut set = HashMap::new(); - for part in raw.split(',') { - let part = part.trim(); - if part.is_empty() { - continue; - } - let Some((name, value)) = part.split_once(':') else { - continue; - }; - let name = name.trim(); - if name.is_empty() { - continue; - } - set.insert(name.to_string(), value.trim().to_string()); - } - PluginRequestHeaders { set } -} - -fn format_request_headers(headers: &PluginRequestHeaders) -> String { - let mut names: Vec<&String> = headers.set.keys().collect(); - names.sort(); - names - .into_iter() - .map(|name| format!("{name}: {}", headers.set[name])) - .collect::>() - .join(", ") -} - fn is_tls_term_plugin(plugin_type: &str) -> bool { matches!(plugin_type.trim().to_ascii_lowercase().as_str(), "tls-term") } @@ -354,7 +324,6 @@ pub fn tunnel_from_parts( plugin_cert_file: &str, plugin_key_file: &str, plugin_host_rewrite: &str, - plugin_request_headers: &str, plugin_username: &str, plugin_password: &str, ) -> Result { @@ -373,7 +342,6 @@ pub fn tunnel_from_parts( cert_file: plugin_cert_file.trim().into(), key_file: plugin_key_file.trim().into(), host_header_rewrite: plugin_host_rewrite.trim().into(), - request_headers: parse_request_headers(plugin_request_headers), username: String::new(), password: String::new(), }) @@ -466,9 +434,6 @@ pub fn tunnel_to_parts(p: &TunnelConfig) -> TunnelParts { plugin_host_rewrite: tls_term .map(|pl| pl.host_header_rewrite.clone()) .unwrap_or_default(), - plugin_request_headers: tls_term - .map(|pl| format_request_headers(&pl.request_headers)) - .unwrap_or_default(), plugin_username: socks5.map(|pl| pl.username.clone()).unwrap_or_default(), plugin_password: socks5.map(|pl| pl.password.clone()).unwrap_or_default(), } @@ -494,7 +459,6 @@ pub struct TunnelParts { pub plugin_cert_file: String, pub plugin_key_file: String, pub plugin_host_rewrite: String, - pub plugin_request_headers: String, pub plugin_username: String, pub plugin_password: String, } diff --git a/desktop/src/main.rs b/desktop/src/main.rs index cd8197c..f61bf27 100644 --- a/desktop/src/main.rs +++ b/desktop/src/main.rs @@ -102,7 +102,6 @@ fn row_to_tunnel(row: &TunnelRow) -> anyhow::Result TunnelRow { plugin_cert_file: parts.plugin_cert_file.into(), plugin_key_file: parts.plugin_key_file.into(), plugin_host_rewrite: parts.plugin_host_rewrite.into(), - plugin_request_headers: parts.plugin_request_headers.into(), plugin_username: parts.plugin_username.into(), plugin_password: parts.plugin_password.into(), } @@ -359,7 +357,6 @@ fn reset_tunnel_form(ui: &AppWindow) { ui.set_tunnel_edit_plugin_cert_file("".into()); ui.set_tunnel_edit_plugin_key_file("".into()); ui.set_tunnel_edit_plugin_host_rewrite("".into()); - ui.set_tunnel_edit_plugin_request_headers("".into()); ui.set_tunnel_edit_plugin_username("".into()); ui.set_tunnel_edit_plugin_password("".into()); ui.set_tunnel_edit_type_index(0); @@ -389,7 +386,6 @@ fn fill_tunnel_form(ui: &AppWindow, row: &TunnelRow) { ui.set_tunnel_edit_plugin_cert_file(row.plugin_cert_file.clone()); ui.set_tunnel_edit_plugin_key_file(row.plugin_key_file.clone()); ui.set_tunnel_edit_plugin_host_rewrite(row.plugin_host_rewrite.clone()); - ui.set_tunnel_edit_plugin_request_headers(row.plugin_request_headers.clone()); ui.set_tunnel_edit_plugin_username(row.plugin_username.clone()); ui.set_tunnel_edit_plugin_password(row.plugin_password.clone()); ui.set_tunnel_show_advanced(false); @@ -473,11 +469,6 @@ fn collect_tunnel_form(ui: &AppWindow) -> TunnelRow { } else { "".into() }, - plugin_request_headers: if plugin { - ui.get_tunnel_edit_plugin_request_headers() - } else { - "".into() - }, plugin_username: if is_socks5 { ui.get_tunnel_edit_plugin_username() } else { diff --git a/desktop/ui/app.slint b/desktop/ui/app.slint index 1c1901e..dab9690 100644 --- a/desktop/ui/app.slint +++ b/desktop/ui/app.slint @@ -122,7 +122,6 @@ export component AppWindow inherits Window { in-out property tunnel-edit-plugin-cert-file: ""; in-out property tunnel-edit-plugin-key-file: ""; in-out property tunnel-edit-plugin-host-rewrite: ""; - in-out property tunnel-edit-plugin-request-headers: ""; in-out property tunnel-edit-plugin-username: ""; in-out property tunnel-edit-plugin-password: ""; in-out property tunnel-edit-type-index: 0; @@ -261,7 +260,6 @@ export component AppWindow inherits Window { edit-plugin-cert-file <=> root.tunnel-edit-plugin-cert-file; edit-plugin-key-file <=> root.tunnel-edit-plugin-key-file; edit-plugin-host-rewrite <=> root.tunnel-edit-plugin-host-rewrite; - edit-plugin-request-headers <=> root.tunnel-edit-plugin-request-headers; edit-plugin-username <=> root.tunnel-edit-plugin-username; edit-plugin-password <=> root.tunnel-edit-plugin-password; edit-type-index <=> root.tunnel-edit-type-index; diff --git a/desktop/ui/pages/tunnel.slint b/desktop/ui/pages/tunnel.slint index 8d75335..51ef4e0 100644 --- a/desktop/ui/pages/tunnel.slint +++ b/desktop/ui/pages/tunnel.slint @@ -28,7 +28,6 @@ export component TunnelPage inherits Rectangle { in-out property edit-plugin-cert-file: ""; in-out property edit-plugin-key-file: ""; in-out property edit-plugin-host-rewrite: ""; - in-out property edit-plugin-request-headers: ""; in-out property edit-plugin-username: ""; in-out property edit-plugin-password: ""; in-out property edit-type-index: 0; @@ -174,7 +173,6 @@ export component TunnelPage inherits Rectangle { edit-plugin-cert-file <=> root.edit-plugin-cert-file; edit-plugin-key-file <=> root.edit-plugin-key-file; edit-plugin-host-rewrite <=> root.edit-plugin-host-rewrite; - edit-plugin-request-headers <=> root.edit-plugin-request-headers; edit-plugin-username <=> root.edit-plugin-username; edit-plugin-password <=> root.edit-plugin-password; edit-type-index <=> root.edit-type-index; diff --git a/desktop/ui/pages/tunnel/editor.slint b/desktop/ui/pages/tunnel/editor.slint index c0dbb2b..9a01fd5 100644 --- a/desktop/ui/pages/tunnel/editor.slint +++ b/desktop/ui/pages/tunnel/editor.slint @@ -22,7 +22,6 @@ export component TunnelEditor inherits Rectangle { in-out property edit-plugin-cert-file: ""; in-out property edit-plugin-key-file: ""; in-out property edit-plugin-host-rewrite: ""; - in-out property edit-plugin-request-headers: ""; in-out property edit-plugin-username: ""; in-out property edit-plugin-password: ""; in-out property edit-type-index: 0; @@ -335,12 +334,6 @@ export component TunnelEditor inherits Rectangle { model: [Tr.proxy-protocol-off, "v1", "v2"]; current-index <=> root.edit-proxy-protocol-index; } - - if root.is-https && root.use-plugin: FormField { - label: Tr.tunnel-plugin-request-headers; - value <=> root.edit-plugin-request-headers; - placeholder: Tr.tunnel-plugin-request-headers-hint; - } } } } diff --git a/desktop/ui/pages/tunnel/types.slint b/desktop/ui/pages/tunnel/types.slint index 998ec4a..b90ddea 100644 --- a/desktop/ui/pages/tunnel/types.slint +++ b/desktop/ui/pages/tunnel/types.slint @@ -18,7 +18,6 @@ export struct TunnelRow { plugin-cert-file: string, plugin-key-file: string, plugin-host-rewrite: string, - plugin-request-headers: string, plugin-username: string, plugin-password: string, } diff --git a/docs/docs/tunnels/https.md b/docs/docs/tunnels/https.md index e50f592..28375c0 100644 --- a/docs/docs/tunnels/https.md +++ b/docs/docs/tunnels/https.md @@ -85,26 +85,6 @@ keyFile = "/path/to/key.pem" hostHeaderRewrite = "127.0.0.1" ``` -## 示例:TLS 终止时追加请求头 - -在 `tls-term` 下,向本地 HTTP 追加自定义请求头: - -```toml -[[tunnels]] -name = "https-term" -protocol = "https" -domains = ["web.example.com"] - -[tunnels.plugin] -type = "tls-term" -service = "127.0.0.1:80" -certFile = "/path/to/cert.pem" -keyFile = "/path/to/key.pem" - -[tunnels.plugin.requestHeaders.set] -X-From = "orbien" -``` - ## 参数 | 参数 | 必填 | 默认值 | 说明 | @@ -118,7 +98,6 @@ X-From = "orbien" | `plugin.certFile` | 否 | | 证书路径;空则临时自签 | | `plugin.keyFile` | 否 | | 私钥路径;空则临时自签 | | `plugin.hostHeaderRewrite` | 否 | | 改写转发到本地服务的 Host;空表示不改 | -| `plugin.requestHeaders.set` | 否 | | 向后端追加请求头,键值对 | | `transport.bandwidth` | 否 | `0` | 带宽上限(Mbps);`0` 表示不限制 | | `transport.bandwidthLimitSide` | 否 | `client` | 限速端:`client` / `server` | | `transport.proxyProtocolVersion` | 否 | | PROXY Protocol:`v1` / `v2`(`tls-term` 不可用) | diff --git a/docs/i18n/en/docusaurus-plugin-content-docs/current/tunnels/https.md b/docs/i18n/en/docusaurus-plugin-content-docs/current/tunnels/https.md index 6a461d2..b87a47d 100644 --- a/docs/i18n/en/docusaurus-plugin-content-docs/current/tunnels/https.md +++ b/docs/i18n/en/docusaurus-plugin-content-docs/current/tunnels/https.md @@ -88,26 +88,6 @@ keyFile = "/path/to/key.pem" hostHeaderRewrite = "127.0.0.1" ``` -## Example: Add request headers with TLS termination - -Under `tls-term`, append custom request headers to local HTTP: - -```toml -[[tunnels]] -name = "https-term" -protocol = "https" -domains = ["web.example.com"] - -[tunnels.plugin] -type = "tls-term" -service = "127.0.0.1:80" -certFile = "/path/to/cert.pem" -keyFile = "/path/to/key.pem" - -[tunnels.plugin.requestHeaders.set] -X-From = "orbien" -``` - ## Parameters | Parameter | Required | Default | Description | @@ -121,7 +101,6 @@ X-From = "orbien" | `plugin.certFile` | No | | Certificate path; empty uses a temporary self-signed cert | | `plugin.keyFile` | No | | Private key path; empty uses a temporary self-signed cert | | `plugin.hostHeaderRewrite` | No | | Rewrite Host when forwarding to the local service; empty means no rewrite | -| `plugin.requestHeaders.set` | No | | Extra request headers to send to the backend; key-value pairs | | `transport.bandwidth` | No | `0` | Bandwidth cap (Mbps); `0` means unlimited | | `transport.bandwidthLimitSide` | No | `client` | Limit side: `client` / `server` | | `transport.proxyProtocolVersion` | No | | PROXY Protocol: `v1` / `v2` (not available with `tls-term`) |