From 7fbac61e75435d4951e3c97ac35d930f06c63d02 Mon Sep 17 00:00:00 2001 From: lbl <1791778603@qq.com> Date: Thu, 20 Aug 2026 23:10:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(server):=20=E5=8A=A8=E6=80=81=20DNS=20?= =?UTF-8?q?=E5=8F=91=E7=8E=B0=E7=9A=84=20wss://=20=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E6=98=A0=E5=B0=84=E4=B8=BA=20Wss=20=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 此前动态 DNS TXT 记录中的 wss:// 被错映射为 TlsTcp,导致动态发现 模式下 WSS 连接实际不可用(会对 wss 端口发起裸 TLS over TCP)。 将前缀解析抽为纯函数 parse_dynamic_txt,wss:// -> ProtocolType::Wss, 其余映射保持不变。 测试:test_parse_dynamic_txt 覆盖 wss/quic/udp/tcp/ws/无前缀六种输入。 --- .../tunnel_core/server/transport/config.rs | 69 +++++++++++++++---- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/vnt-core/src/tunnel_core/server/transport/config.rs b/vnt-core/src/tunnel_core/server/transport/config.rs index 918db06..f567c31 100644 --- a/vnt-core/src/tunnel_core/server/transport/config.rs +++ b/vnt-core/src/tunnel_core/server/transport/config.rs @@ -116,19 +116,7 @@ impl ConnectRegConfig { txt.shuffle(&mut rand::rng()); let x = txt.first().context("DNS query failed")?; let x = x.to_lowercase(); - let (protocol_type, domain) = if let Some(v) = x.strip_prefix("udp://") { - (ProtocolType::Quic, v) - } else if let Some(v) = x.strip_prefix("quic://") { - (ProtocolType::Quic, v) - } else if let Some(v) = x.strip_prefix("tcp://") { - (ProtocolType::TlsTcp, v) - } else if let Some(v) = x.strip_prefix("ws://") { - (ProtocolType::TlsTcp, v) - } else if let Some(v) = x.strip_prefix("wss://") { - (ProtocolType::TlsTcp, v) - } else { - (ProtocolType::TlsTcp, x.as_str()) - }; + let (protocol_type, domain) = parse_dynamic_txt(&x); (protocol_type, domain.to_owned()) } v => (v, self.server_addr.address.to_string()), @@ -144,6 +132,25 @@ impl ConnectRegConfig { }) } } +/// 解析动态 DNS TXT 记录中的协议前缀。 +/// 注意 wss:// 必须映射到 Wss(此前错映射为 TlsTcp,导致动态发现模式下 +/// WSS 实际不可用)。 +fn parse_dynamic_txt(txt: &str) -> (ProtocolType, &str) { + if let Some(v) = txt.strip_prefix("udp://") { + (ProtocolType::Quic, v) + } else if let Some(v) = txt.strip_prefix("quic://") { + (ProtocolType::Quic, v) + } else if let Some(v) = txt.strip_prefix("tcp://") { + (ProtocolType::TlsTcp, v) + } else if let Some(v) = txt.strip_prefix("ws://") { + (ProtocolType::TlsTcp, v) + } else if let Some(v) = txt.strip_prefix("wss://") { + (ProtocolType::Wss, v) + } else { + (ProtocolType::TlsTcp, txt) + } +} + fn strip_port(addr: &str) -> &str { if let Some(stripped) = addr.strip_prefix('[') && let Some(pos) = stripped.find(']') @@ -171,3 +178,39 @@ impl ConnectConfig { &self.server_domain } } + + +#[cfg(test)] +mod tests { + use super::*; + + /// 动态 DNS TXT 记录中的 wss:// 必须映射为 Wss, + /// 其余前缀维持原有映射不变 + #[test] + fn test_parse_dynamic_txt() { + assert_eq!( + parse_dynamic_txt("wss://example.com:443"), + (ProtocolType::Wss, "example.com:443") + ); + assert_eq!( + parse_dynamic_txt("quic://example.com:29872"), + (ProtocolType::Quic, "example.com:29872") + ); + assert_eq!( + parse_dynamic_txt("udp://example.com:29872"), + (ProtocolType::Quic, "example.com:29872") + ); + assert_eq!( + parse_dynamic_txt("tcp://example.com:29872"), + (ProtocolType::TlsTcp, "example.com:29872") + ); + assert_eq!( + parse_dynamic_txt("ws://example.com:80"), + (ProtocolType::TlsTcp, "example.com:80") + ); + assert_eq!( + parse_dynamic_txt("example.com:29872"), + (ProtocolType::TlsTcp, "example.com:29872") + ); + } +}