shadowsocks/shadowsocks-rust · error
unexpected response from 8.8.8.8:53
Error message
unexpected response from 8.8.8.8:53
What it means
check_request_udp probes a proxy with a UDP DNS query to 8.8.8.8:53 and validates that the answer is at least 12 bytes (DNS header size) and that its transaction ID matches the sent 0x1234. If the packet is too short or the ID differs, the reply is not a valid DNS response for our query, so InvalidData is thrown.
Source
Thrown at crates/shadowsocks-service/src/local/loadbalancing/ping_balancer.rs:962
.await?;
let mut control = UdpSocketControlData::default();
control.client_session_id = rand::random::<u64>();
control.packet_id = 1;
client.send_with_ctrl(&addr, &control, DNS_QUERY).await?;
let mut buffer = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE];
let (n, ..) = client.recv(&mut buffer).await?;
let dns_answer = &buffer[..n];
// DNS packet must have at least 6 * 2 bytes
if dns_answer.len() < 12 || &dns_answer[0..2] != b"\x12\x34" {
use std::io::{Error, ErrorKind};
debug!("unexpected response from 8.8.8.8:53, {:?}", ByteStr::new(dns_answer));
let err = Error::new(ErrorKind::InvalidData, "unexpected response from 8.8.8.8:53");
return Err(err);
}
Ok(())
}
async fn check_request(&self) -> io::Result<()> {
match self.server_type {
ServerType::Tcp => self.check_request_tcp_firefox().await,
ServerType::Udp => self.check_request_udp().await,
}
}
async fn check_delay(&self) -> io::Result<u32> {
let start = Instant::now();
// Send HTTP GET and read the first byte
let res = time::timeout(self.max_server_rtt, self.check_request()).await;View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Confirm the server supports UDP relay (udp_assist / udp_enabled) before using it for UDP traffic.
- Test plain UDP DNS to 8.8.8.8 from the server host; open port 53 egress if blocked.
- Check for DNS hijacking on the path (compare response with dig @8.8.8.8 directly).
- Exclude the node from UDP-eligible servers in the balancer.
Defensive patterns
Strategy: fallback
Validate before calling
// before probing UDP, confirm server advertises UDP relay support
if !server.udp_assist() { /* exclude from UDP balancer */ } Try / catch
match udp_check(&server).await {
Ok(()) => udp_balancer.add_server(server, estimate),
Err(_) => {
// fall back to TCP relay for DNS or exclude node from UDP pool
exclude_from_udp_pool(server);
}
} Prevention
- Only enable UDP relay on servers that support it (shadowsocks-2022 / udp_assist)
- Detect DNS hijacking by comparing transaction IDs of independent queries
- Open UDP port 53 egress on the server firewall
- Prefer tcping-based balancer if UDP relay is not essential
When it happens
Trigger: check_request (UDP path) receiving a UDP reply that is <12 bytes, empty, or whose first two bytes are not \x12\x34 — e.g. ICMP port-unreachable payloads, hijacked answers, or a different server's response.
Common situations: Proxy nodes that don't support UDP relay (ASSOCIATE), firewalls dropping UDP, ISP DNS hijacking injecting spoofed responses, or servers where port 53 egress is blocked.
Related errors
- redir destination must not be an domain name address
- tun destination must not be an domain name address
- resolve empty
- resolve empty
- failed to encode DNS response
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/223356fd77b48743.
Report an issue: GitHub.