{"record":{"id":"a961b897d0bdcfb9","repo":"XTLS/Xray-core","slug":"failed-to-read-domain-for-socks-4a","errorCode":null,"errorMessage":"failed to read domain for socks 4a","messagePattern":"failed to read domain for socks 4a","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/socks/protocol.go","lineNumber":78,"sourceCode":"\n\t{\n\t\tbuffer := buf.StackNew()\n\t\tif _, err := buffer.ReadFullFrom(reader, 6); err != nil {\n\t\t\tbuffer.Release()\n\t\t\treturn nil, errors.New(\"insufficient header\").Base(err)\n\t\t}\n\t\tport = net.PortFromBytes(buffer.BytesRange(0, 2))\n\t\taddress = net.IPAddress(buffer.BytesRange(2, 6))\n\t\tbuffer.Release()\n\t}\n\n\tif _, err := ReadUntilNull(reader); /* user id */ err != nil {\n\t\treturn nil, err\n\t}\n\tif address.IP()[0] == 0x00 {\n\t\tdomain, err := ReadUntilNull(reader)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"failed to read domain for socks 4a\").Base(err)\n\t\t}\n\t\taddress = net.ParseAddress(domain)\n\t}\n\n\tswitch cmd {\n\tcase cmdTCPConnect:\n\t\trequest := &protocol.RequestHeader{\n\t\t\tCommand: protocol.RequestCommandTCP,\n\t\t\tAddress: address,\n\t\t\tPort:    port,\n\t\t\tVersion: socks4Version,\n\t\t}\n\t\tif err := writeSocks4Response(writer, socks4RequestGranted, net.AnyIP, net.Port(0)); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn request, nil\n\tdefault:\n\t\twriteSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0))","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/socks/protocol.go#L60-L96","documentation":"Thrown in handshake4 (proxy/socks/protocol.go:78) for a SOCKS4a request. When the 4-byte address starts with 0x00 the client is expected to send a null-terminated domain name after the userid; ReadUntilNull failing (EOF/reset before the terminating 0x00) produces this error.","triggerScenarios":"Client sets DSTIP bytes 0-2 to non-zero and byte 3 to 0x00 (the 4a convention) but never sends the domain string, sends it without the trailing null byte, or the connection breaks before the domain arrives.","commonSituations":"Buggy SOCKS4a client implementations that forget the null terminator; clients that craft the 4a marker bytes incorrectly; connection drops during slow handshakes.","solutions":["Fix the client to send: USERID + 0x00 + DOMAIN + 0x00 after the 6-byte header, with DSTIP = 0x00 0x00 0x00 <non-zero>.","Prefer SOCKS4a's modern replacement: use SOCKS5 hostname support (cmdTorResolve/connect with address type domain) instead.","Check the base error for EOF/reset to distinguish a client bug from a network break."],"exampleFix":"// before: 4a marker set but no domain sent\nconn.Write([]byte{0x04, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0xFF, 0x00}) // then close\n\n// after: append null-terminated domain\nconn.Write([]byte{0x04, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0xFF, 0x00})\nconn.Write([]byte(\"example.com\\x00\"))","handlingStrategy":"validation","validationCode":"// Client-side: build a well-formed SOCKS4a request with null-terminated fields\nfunc socks4aRequest(w io.Writer, domain string, port uint16) error {\n    if len(domain) > 253 || strings.IndexByte(domain, 0) >= 0 {\n        return fmt.Errorf(\"invalid domain %q\", domain)\n    }\n    req := []byte{0x04, 0x01, byte(port >> 8), byte(port), 0, 0, 0, 0xFF, 0x00}\n    req = append(req, domain...)\n    req = append(req, 0x00)\n    _, err := w.Write(req)\n    return err\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to read domain for socks 4a\") {\n    return errors.New(\"client sent a SOCKS4a request without a null-terminated domain\")\n}","preventionTips":["Always terminate userid and domain strings with 0x00.","Prefer SOCKS5 (ATYP 0x03) for hostname targets instead of SOCKS4a."],"tags":["socks","protocol","socks4a","domain","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}