shadowsocks/shadowsocks-rust · error

tun destination must not be an domain name address

Error message

tun destination must not be an domain name address

What it means

The tun device routes raw IP packets, so a UDP destination must be a concrete IP address. If the destination Address is a domain name that was never resolved, send_to returns InvalidInput 'tun destination must not be an domain name address'.

Source

Thrown at crates/shadowsocks-service/src/local/tun/udp.rs:121

                        // If peer is IPv4, then remote_addr can only be IPv4-mapped-IPv6
                        match to_ipv4_mapped(v6.ip()) {
                            Some(v4) => SocketAddr::new(IpAddr::from(v4), v6.port()),
                            None => {
                                return Err(io::Error::new(
                                    ErrorKind::InvalidData,
                                    "source and destination type unmatch",
                                ));
                            }
                        }
                    }
                    (SocketAddr::V6(..), SocketAddr::V4(v4)) => {
                        // Convert remote_addr to IPv4-mapped-IPv6
                        SocketAddr::new(IpAddr::from(v4.ip().to_ipv6_mapped()), v4.port())
                    }
                }
            }
            Address::DomainNameAddress(..) => {
                let err = io::Error::new(
                    ErrorKind::InvalidInput,
                    "tun destination must not be an domain name address",
                );
                return Err(err);
            }
        };

        let packet = match (peer_addr, addr) {
            (SocketAddr::V4(peer), SocketAddr::V4(remote)) => {
                let builder =
                    PacketBuilder::ipv4(remote.ip().octets(), peer.ip().octets(), 20).udp(remote.port(), peer.port());

                let packet = BytesMut::with_capacity(builder.size(data.len()));
                let mut packet_writer = packet.writer();
                builder.write(&mut packet_writer, data).expect("PacketBuilder::write");

                packet_writer.into_inner()
            }

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Resolve the domain to an IP address before calling send_to (use a DNS resolver and pass SocketAddr/Address::Ip)
  2. Enable local address resolution so destinations are IPs by the time they reach the tun relay
  3. If the remote returns a domain in the UDP reply, map it back through your DNS cache to the queried IP
  4. Reject such packets upstream with a clear log instead of reaching send_to

Example fix

// before
let dest = Address::DomainNameAddress("example.com".into(), 53);
relay.send_to(dest, ...).await?;
// after
let ip = resolver.resolve("example.com").await?;
let dest = Address::SocketAddr(SocketAddr::new(ip, 53));
relay.send_to(dest, ...).await?;
Defensive patterns

Strategy: validation

Validate before calling

if let Address::DomainNameAddress(..) = dest {
    return Err("resolve domain before tun UDP send_to");
}

Type guard

fn is_ip_address(addr: &Address) -> bool { !matches!(addr, Address::DomainNameAddress(..)) }

Try / catch

match relay.send_to(dest, src, &data).await { Err(e) if e.kind()==InvalidInput => { let ip = resolve(dest).await?; retry_with(ip).await? }, r => r? }

Prevention

When it happens

Trigger: Calling send_to on the tun UDP relay with a destination Address::DomainNameAddress — i.e. DNS resolution was skipped or the address came from a path that did not resolve hostnames (e.g. remote returned a domain in its reply header).

Common situations: Remote shadowsocks server replies with a domain-name address for UDP associate replies; local resolution disabled (remote DNS) while using tun mode, which cannot send un-resolved names.

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


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/790f55fce128ef60. Report an issue: GitHub.