shadowsocks/shadowsocks-rust · error
invalid dnsname "{domain}"
Error message
invalid dnsname "{domain}" What it means
tls_connect_inner builds a rustls TlsConnector and must convert the proxy hostname into a rustls ServerName. If the domain fails ServerName::try_from (empty string, contains invalid characters, is not a valid DNS name or IP), the connection is rejected with InvalidInput carrying the offending domain.
Source
Thrown at crates/shadowsocks-service/src/net/outbound/tls.rs:143
for cert in certs {
if let Err(err) = store.add(cert) {
warn!("failed to add cert (native), error: {}", err);
}
}
store
})
.with_no_client_auth();
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
Arc::new(config)
});
let connector = TlsConnector::from(TLS_CONFIG.clone());
let host = ServerName::try_from(domain)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, format!("invalid dnsname \"{domain}\"")))?
.to_owned();
let tls_stream = connector.connect(host, stream).await?;
let (_, session) = tls_stream.get_ref();
let h2 = matches!(session.alpn_protocol(), Some(b"h2"));
Ok(OutboundTlsStream::Rustls(tls_stream, h2))
}
#[cfg(any(feature = "local-http-native-tls", feature = "local-http-rustls"))]
macro_rules! forward_call {
($self:expr, $method:ident $(, $param:expr)*) => {
match $self.as_mut().project() {
#[cfg(all(feature = "local-http-native-tls", not(feature = "local-http-rustls")))]
OutboundTlsStreamProj::NativeTls(s, _) => s.$method($($param),*),
#[cfg(feature = "local-http-rustls")]
OutboundTlsStreamProj::Rustls(s, _) => s.$method($($param),*),
}View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Set the hop host to a bare valid DNS name (e.g. proxy.example.com) or a valid IP, with no scheme or path
- Strip the scheme/port from a pasted URL so only the hostname remains in the host field
- Pre-validate the hostname (non-empty, alphanumerics/hyphens/dots, or a parseable IP) before dialing
Example fix
// before
let hop = OutboundProxyHop { kind: OutboundProxyKind::Https { host: "https://proxy.example.com:8443".into(), .. } };
// after
let hop = OutboundProxyHop { kind: OutboundProxyKind::Https { host: "proxy.example.com".into(), .. } }; Defensive patterns
Strategy: validation
Validate before calling
fn valid_dns_host(host: &str) -> bool {
!host.is_empty()
&& !host.contains("://")
&& host.parse::<std::net::IpAddr>().is_ok()
|| (!host.is_empty() && host.split('.').all(|l| !l.is_empty() && l.chars().all(|c| c.is_ascii_alphanumeric() || c == '-')))
}
if !valid_dns_host(&hop_host) { return Err(anyhow!("invalid https proxy host: {hop_host}")); } Type guard
fn is_servername_ok(host: &str) -> bool {
rustls_pki_types::ServerName::try_from(host.to_string()).is_ok()
} Try / catch
match tls_connect(stream, domain).await {
Err(e) if e.kind() == io::ErrorKind::InvalidInput && e.to_string().starts_with("invalid dnsname") => {
eprintln!("fix proxy host in config: {}", e);
}
other => other?,
} Prevention
- Store only the bare hostname in the host field — no scheme, port, or path
- Reject empty hosts at config parse time
- Test configs with IP literals and hostnames separately
When it happens
Trigger: An https outbound proxy hop is configured with a host string rustls cannot parse as a DNS name — empty host, underscores, scheme prefixes like `https://` left in the host field, IPv6 without brackets, or trailing whitespace/dot issues.
Common situations: Users paste the full proxy URL into the host field; config uses a hostname with illegal characters; empty host field after env-var expansion failed; IP literal formatting mistakes.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid dnsname "{domain}"
- `local_dns_address` invalid
- tun destination must not be an domain name address
- failed to create ServerConfig, error: {}
- missing `addr` in configuration
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/7fe342d62ef5031a.
Report an issue: GitHub.