shadowsocks/shadowsocks-rust · error
redir destination must not be an domain name address
Error message
redir destination must not be an domain name address
What it means
The UDP relay for redir (transparent proxy) must send the datagram to the packet's real destination, which pf/nftables/iptables rewriting can only express as an IP address. When the resolved destination is Address::DomainNameAddress, there is no IP to send to in a redir socket, so send_to returns InvalidInput.
Source
Thrown at crates/shadowsocks-service/src/local/redir/udprelay/mod.rs:125
} else {
sa
}
}
SocketAddr::V6(ref v6) => {
// If IPv6 is not supported. Try to map it back to IPv4.
if !ip_stack_caps.support_ipv6 || !ip_stack_caps.support_ipv4_mapped_ipv6 {
match v6.ip().to_ipv4_mapped() {
Some(v4) => SocketAddr::new(v4.into(), v6.port()),
None => sa,
}
} else {
sa
}
}
}
}
Address::DomainNameAddress(..) => {
let err = io::Error::new(
ErrorKind::InvalidInput,
"redir destination must not be an domain name address",
);
return Err(err);
}
};
let inbound = {
let mut cache = self.inbound_cache.cache.lock().await;
match cache.get(&addr) {
Some(socket) => socket.clone(),
_ => {
// Create a socket binds to destination addr
// This only works for systems that supports binding to non-local addresses
//
// This socket has to set SO_REUSEADDR and SO_REUSEPORT.
// Outbound addresses could be connected from different source addresses.
let inbound = UdpRedirSocket::bind_nonlocal(self.redir_ty, addr, &self.socket_opts)?;View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Resolve the domain to a SocketAddr (via a resolver/lookup) before calling send_to.
- Use the non-redir UDP relay/UdpSocket path when targets may be domain names.
- Check that the transparent-proxy rules preserve IP-form original destinations (no NAT64/DNS64 rewriting).
- Reject or log domain destinations early in your caller instead of reaching send_to.
Example fix
// before
let target = Address::DomainNameAddress("example.com".to_owned(), 53);
socket.send_to(payload, &target).await?;
// after
let ip = lookup_host(("example.com", 53)).await?;
socket.send_to(payload, &Address::from(ip)).await?; Defensive patterns
Strategy: validation
Validate before calling
// resolve before send_to; reject domain targets early
if matches!(addr, Address::DomainNameAddress(..)) {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "resolve domain before redir send_to"));
} Type guard
fn as_ip(addr: &Address) -> Option<SocketAddr> {
match addr {
Address::SocketAddress(sa) => Some(*sa),
_ => None,
}
} Try / catch
match socket.send_to(payload, &addr).await {
Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => {
// resolve domain destination then retry once
let ip = resolve(&addr).await?;
socket.send_to(payload, &Address::from(ip)).await?;
}
r => r?,
} Prevention
- Always pass IP-form destinations to redir UDP sockets
- Resolve domains with the same resolver the proxy would use to avoid asymmetric routing
- Disable NAT64/DNS64 on transparent-proxy hosts so lookups stay IP-form
When it happens
Trigger: Calling UdpRedirSocket::send_to whose target Address is a domain name — e.g. original-destination lookup returned a hostname, or application code passed a domain-based Address into the redir UDP relay instead of an IP SocketAddr.
Common situations: Custom integrations feeding domain Addresses into the redir path, DNS configurations where the pf lookup yields non-IP forms, or mixing the ordinary (non-redir) UDP relay API with redir sockets.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- unexpected response from 8.8.8.8:53
- missing destination address in msghdr
- not supported udp transparent proxy type
- missing destination address in msghdr
- not supported udp transparent proxy type
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/5185bcf78b95f2ec.
Report an issue: GitHub.