shadow1ng/fscan · warning
redis_ping_failed
Error message
redis_ping_failed
What it means
After connecting and authenticating the handshake to a Redis server, the plugin sends a PING and expects a reply containing "PONG". If the raw response bytes do not contain PONG, it closes the connection and fails the auth attempt with redis_ping_failed, embedding the actual response text via i18n.Tr. This guards against servers that accept TCP on 6379 but do not speak RESP correctly (proxies, honeypots, HTTP endpoints, or a server requiring AUTH that returns an error string instead of PONG).
Source
Thrown at plugins/services/redis.go:173
_ = conn.SetReadDeadline(time.Now().Add(timeout))
response := make([]byte, 512)
n, pingReadErr := conn.Read(response)
if pingReadErr != nil {
_ = conn.Close()
return &AuthResult{
Success: false,
ErrorType: ErrorTypeNetwork,
Error: pingReadErr,
}
}
responseStr := string(response[:n])
if !strings.Contains(responseStr, "PONG") {
_ = conn.Close()
return &AuthResult{
Success: false,
ErrorType: ErrorTypeUnknown,
Error: fmt.Errorf("%s", i18n.Tr("redis_ping_failed", strings.TrimSpace(responseStr))),
}
}
return &AuthResult{
Success: true,
Conn: conn,
ErrorType: ErrorTypeUnknown,
Error: nil,
}
}
// classifyRedisErrorType Redis错误分类
func classifyRedisErrorType(err error) ErrorType {
if err == nil {
return ErrorTypeUnknown
}
redisAuthErrors := []string{View on GitHub (pinned to 95cc12e753)
Solutions
- Check the actual response text embedded in the error to see what the server returned.
- If it is -NOAUTH, provide correct Redis credentials before the PING (set the password in the auth config).
- Verify the target is really Redis: run redis-cli -h <host> -p <port> PING manually.
- Confirm protected-mode is disabled or the scanner source IP is allowed (bind/ACL settings in redis.conf).
Example fix
// before (server returns -NOAUTH)
conn.Write([]byte("PING\r\n")) // -> "-NOAUTH Authentication required."
// after
conn.Write([]byte("AUTH mypassword\r\n"))
conn.Write([]byte("PING\r\n")) // -> "+PONG" Defensive patterns
Strategy: try-catch
Validate before calling
conn, err := net.DialTimeout("tcp", host+":6379", 3*time.Second)
if err == nil {
fmt.Fprintf(conn, "PING\r\n")
buf := make([]byte, 64)
n, _ := conn.Read(buf)
if !strings.Contains(string(buf[:n]), "PONG") { /* expect redis_ping_failed; inspect raw response */ }
conn.Close()
} Type guard
func isPong(resp string) bool { return strings.Contains(resp, "PONG") } Try / catch
res, err := plugin.Scan(ctx, target)
if err != nil {
var ae *AuthResult
if strings.Contains(err.Error(), "-NOAUTH") {
// supply credentials and retry
} else {
log.Printf("redis probe not a real Redis server: %v", err)
}
} Prevention
- Always preflight with redis-cli PING before scanning a target as Redis.
- Include a valid credential pair so AUTH precedes PING.
- Filter out ports whose banner does not look like RESP before dispatching to the redis module.
When it happens
Trigger: doRedisAuth connects to a Redis port, completes its handshake, sends PING, and the response string does not contain "PONG" — e.g. the server returned "-NOAUTH Authentication required", "-ERR unknown command", an HTTP error page, or garbage bytes.
Common situations: Redis protected-mode or ACLs rejecting unauthenticated PING; the port actually hosts a different service (memcached, an HTTP proxy, a honeypot); a RESP-incompatible middleware in front of Redis; scanning a non-Redis service that happens to listen on 6379.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- mcs sendConnectInitial write error %v
- ReadConnectResponse %v
- mcs recvData get data error %v
- short oracle data packet
- oracle resend is not supported
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/06bb0808699e46a3.
Report an issue: GitHub.