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))
	}

	// 检查是否支持SMBv1

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Test basic reachability: nc -vz <host> 445 from the scanner host.
  2. Check firewall/security-group rules to allow outbound TCP to 445/139.
  3. Verify DNS resolution of the host and correct IP in the target list.
  4. 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

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


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/3123f04b27df65c3. Report an issue: GitHub.