fix(server): 动态 DNS 发现的 wss:// 地址正确映射为 Wss 协议

此前动态 DNS TXT 记录中的 wss:// 被错映射为 TlsTcp,导致动态发现
模式下 WSS 连接实际不可用(会对 wss 端口发起裸 TLS over TCP)。

将前缀解析抽为纯函数 parse_dynamic_txt,wss:// -> ProtocolType::Wss,
其余映射保持不变。

测试:test_parse_dynamic_txt 覆盖 wss/quic/udp/tcp/ws/无前缀六种输入。
This commit is contained in:
lbl
2026-08-20 23:10:12 +08:00
parent 2e77801adc
commit 7fbac61e75
@@ -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")
);
}
}