{"record":{"id":"790f55fce128ef60","repo":"shadowsocks/shadowsocks-rust","slug":"tun-destination-must-not-be-an-domain-name-address","errorCode":null,"errorMessage":"tun destination must not be an domain name address","messagePattern":"tun destination must not be an domain name address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/shadowsocks-service/src/local/tun/udp.rs","lineNumber":121,"sourceCode":"                        // If peer is IPv4, then remote_addr can only be IPv4-mapped-IPv6\n                        match to_ipv4_mapped(v6.ip()) {\n                            Some(v4) => SocketAddr::new(IpAddr::from(v4), v6.port()),\n                            None => {\n                                return Err(io::Error::new(\n                                    ErrorKind::InvalidData,\n                                    \"source and destination type unmatch\",\n                                ));\n                            }\n                        }\n                    }\n                    (SocketAddr::V6(..), SocketAddr::V4(v4)) => {\n                        // Convert remote_addr to IPv4-mapped-IPv6\n                        SocketAddr::new(IpAddr::from(v4.ip().to_ipv6_mapped()), v4.port())\n                    }\n                }\n            }\n            Address::DomainNameAddress(..) => {\n                let err = io::Error::new(\n                    ErrorKind::InvalidInput,\n                    \"tun destination must not be an domain name address\",\n                );\n                return Err(err);\n            }\n        };\n\n        let packet = match (peer_addr, addr) {\n            (SocketAddr::V4(peer), SocketAddr::V4(remote)) => {\n                let builder =\n                    PacketBuilder::ipv4(remote.ip().octets(), peer.ip().octets(), 20).udp(remote.port(), peer.port());\n\n                let packet = BytesMut::with_capacity(builder.size(data.len()));\n                let mut packet_writer = packet.writer();\n                builder.write(&mut packet_writer, data).expect(\"PacketBuilder::write\");\n\n                packet_writer.into_inner()\n            }","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/local/tun/udp.rs#L103-L139","documentation":"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'.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Resolve the domain to an IP address before calling send_to (use a DNS resolver and pass SocketAddr/Address::Ip)","Enable local address resolution so destinations are IPs by the time they reach the tun relay","If the remote returns a domain in the UDP reply, map it back through your DNS cache to the queried IP","Reject such packets upstream with a clear log instead of reaching send_to"],"exampleFix":"// before\nlet dest = Address::DomainNameAddress(\"example.com\".into(), 53);\nrelay.send_to(dest, ...).await?;\n// after\nlet ip = resolver.resolve(\"example.com\").await?;\nlet dest = Address::SocketAddr(SocketAddr::new(ip, 53));\nrelay.send_to(dest, ...).await?;","handlingStrategy":"validation","validationCode":"if let Address::DomainNameAddress(..) = dest {\n    return Err(\"resolve domain before tun UDP send_to\");\n}","typeGuard":"fn is_ip_address(addr: &Address) -> bool { !matches!(addr, Address::DomainNameAddress(..)) }","tryCatchPattern":"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? }","preventionTips":["Resolve all destinations to IPs before the tun relay","Enable DNS resolution in the local pipeline when using tun mode","Cache domain->IP mappings from upstream queries","Validate Address kind at relay entry points"],"tags":["network","udp","tun","dns","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}