shadow1ng/fscan · error
service_connection_failed
Error message
service_connection_failed
What it means
probeTarget's first step is to dial the target with session.DialTCP. If the dial fails, it returns service_connection_failed with the wrapped net error (note the i18n.Tr format places %w inside a translated template). This is the lowest-level SMB failure: the TCP connection to host:port could not be established at all, before any SMB negotiation.
Source
Thrown at plugins/services/smb_protocol.go:210
"\x00\x00" +
"\x03\x00" +
"\x0e\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" +
"\x00\x00" +
"\x01\x00\x00\x00" +
"\x01\x00" +
"\x00\x00" +
"\x00\x00\x00\x00"
)
// probeTarget 探测目标SMB信息(协议版本、系统信息)
func probeTarget(ctx context.Context, host string, port int, timeout time.Duration, session *common.ScanSession) (*SMBTarget, error) {
target := net.JoinHostPort(host, strconv.Itoa(port))
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
return nil, fmt.Errorf(i18n.Tr("service_connection_failed", "%w"), err)
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(timeout))
// 首先尝试SMBv1协商
_, err = conn.Write(smbv1NegotiatePacket)
if err != nil {
return nil, fmt.Errorf("%s: %w", i18n.GetText("smbv1_negotiate_send_failed"), err)
}
// 读取SMBv1协商响应
r1, err := readSMBMessage(conn)
if err != nil {
session.LogDebug(i18n.Tr("smbv1_negotiate_read_failed", err))
}
// 检查是否支持SMBv1View on GitHub (pinned to 95cc12e753)
Solutions
- Test basic reachability: nc -vz <host> 445 from the scanner host.
- Check firewall/security-group rules to allow outbound TCP to 445/139.
- Verify DNS resolution of the host and correct IP in the target list.
- Increase the timeout in config if the error is a deadline/timeout variant; retry transient network failures.
Example fix
// before
scanSMB("10.0.0.5", timeout: 2s) // service_connection_failed: dial tcp ... i/o timeout
// after
scanSMB("10.0.0.5", timeout: 10s) // with firewall rule allowing tcp/445 Defensive patterns
Strategy: retry
Validate before calling
addr := net.JoinHostPort(host, "445")
if _, err := net.DialTimeout("tcp", addr, 5*time.Second); err != nil {
return fmt.Errorf("target %s unreachable before SMB probe: %v", addr, err)
} Try / catch
res, err := plugin.Scan(ctx, target)
if err != nil && strings.Contains(err.Error(), "service_connection_failed") {
var ne net.Error
if errors.As(err, &ne) && ne.Timeout() {
// retry with larger timeout
} else {
// connection refused/filtered: mark host unreachable
}
} Prevention
- Run a cheap TCP dial health-check before dispatching SMB scans.
- Open firewall paths for TCP 445/139 from the scanner subnet.
- Verify DNS resolution of targets before scanning.
- Retry once on timeout-class dial errors before giving up.
When it happens
Trigger: session.DialTCP(ctx, "tcp", net.JoinHostPort(host, port), timeout) returns an error — connection refused (nothing listening), no route/filtered, or context/deadline timeout — triggering the return at smb_protocol.go:210.
Common situations: SMB ports closed or firewalled (very common: 445 blocked on WAN); host offline or DNS resolving to a dead IP; scanner lacking network route (VPN not connected); timeout too small for the environment.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- socks5_target_connect_failed: %w
- failed to connect host: %s
- netbios_smb_negotiate_read_failed: %w
- [dial err] %v
- ms17010_connection_error: %w
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/3123f04b27df65c3.
Report an issue: GitHub.