{"record":{"id":"16c81cf1b945bd0e","repo":"shadow1ng/fscan","slug":"service-not-identified-16c81c","errorCode":"service_not_identified","errorMessage":"service_not_identified: SSH","messagePattern":"service_not_identified: SSH","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"plugins/services/ssh.go","lineNumber":304,"sourceCode":"\t\t\tError:   err,\n\t\t}\n\t}\n\tdefer func() { _ = conn.Close() }()\n\n\tif banner := p.readSSHBanner(conn, session.Config); banner != \"\" {\n\t\tsession.LogSuccess(i18n.Tr(\"ssh_service_identified\", target, banner)) //nolint:govet\n\t\treturn &ScanResult{\n\t\t\tType:    plugins.ResultTypeService,\n\t\t\tSuccess: true,\n\t\t\tService: \"ssh\",\n\t\t\tBanner:  banner,\n\t\t}\n\t}\n\n\treturn &ScanResult{\n\t\tSuccess: false,\n\t\tService: \"ssh\",\n\t\tError:   fmt.Errorf(\"%s\", i18n.Tr(\"service_not_identified\", \"SSH\")),\n\t}\n}\n\n// readSSHBanner 读取SSH服务器Banner\nfunc (p *SSHPlugin) readSSHBanner(conn net.Conn, config *common.Config) string {\n\t_ = conn.SetReadDeadline(time.Now().Add(config.ModuleTimeout()))\n\n\t// RFC 4253 permits servers to send informational lines before the SSH\n\t// identification string. Read bounded lines until the protocol banner is\n\t// found instead of requiring SSH- at the first byte of the first read.\n\treader := bufio.NewReaderSize(conn, 256)\n\tfor range 50 {\n\t\tline, err := reader.ReadString('\\n')\n\t\tif len(line) > 255 {\n\t\t\treturn \"\"\n\t\t}\n\n\t\tbanner := strings.TrimSpace(line)","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/ssh.go#L286-L322","documentation":"The SSH plugin connected and read the banner but could not positively identify the service as SSH, so identifyService returns 'service_not_identified' with the received banner quoted ('SSH'). The banner exchange failed to match the plugin's identification criteria.","triggerScenarios":"Calling Scan when readSSHBanner returns a banner that does not match the SSH identification pattern (or is empty/timeout), causing the final fallback error in identifyService.","commonSituations":"Server on port 22 is not really SSH (a proxy, tarpit, or honeypot); banner delayed beyond ModuleTimeout; non-standard SSH servers with unusual banners; rate-limiting wrappers that greet differently.","solutions":["Manually connect (nc host 22) and inspect the actual banner to confirm it matches SSH format.","Increase the module read timeout so slow banners are captured.","Loosen/extend the banner identification pattern to cover the server's banner variant.","Verify the target port really hosts SSH and not a different or wrapped service."],"exampleFix":"// before\ncfg.SetModuleTimeout(2 * time.Second) // banner read times out\n// after\ncfg.SetModuleTimeout(10 * time.Second) // allow slow SSH banner exchange","handlingStrategy":"retry","validationCode":"conn.SetReadDeadline(time.Now().Add(10*time.Second))\nbuf := make([]byte, 256); n, _ := conn.Read(buf)\nif !strings.Contains(string(buf[:n]), \"SSH-\") { /* warn: not a standard SSH banner */ }","typeGuard":"func looksLikeSSH(banner string) bool { return strings.HasPrefix(banner, \"SSH-\") }","tryCatchPattern":null,"preventionTips":["Increase module timeout for slow banner exchange","Manually inspect banners of ambiguous hosts","Keep banner patterns updated for non-standard servers","Confirm port 22 actually hosts SSH"],"tags":["ssh","banner","identification"],"backgroundTag":"unexpected-response-shape","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}