shadow1ng/fscan · warning

netbios_smb_negotiate_send_failed

Error message

netbios_smb_negotiate_send_failed: %w

What it means

This error occurs in queryNetBIOSSession when writing the SMB negotiate packet (smbNegotiate1) to a NetBIOS session service TCP connection on port 139 fails. The library wraps the underlying net.Conn.Write error with the i18n message 'netbios_smb_negotiate_send_failed'. It means the TCP connection was established (DialTCP succeeded) but broke before the first SMB packet could be delivered.

Solutions

  1. Verify the target host actually speaks SMB on TCP 139 (nmap -p139 --script smb-os-discovery); if it doesn't, exclude it from scanning.
  2. Increase config.ModuleTimeout() so the SetDeadline does not expire during the write.
  3. Check for firewalls/IPS between scanner and host that reset SMB packets; whitelist the scanner IP.
  4. Inspect the wrapped %w error to distinguish i/o timeout vs connection reset and handle each case specifically.

Example fix

// before
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.ModuleTimeout())
_, err = conn.Write(smbNegotiate1)

// after
conn, err := session.DialTCP(ctx, "tcp", target, 2*session.Config.ModuleTimeout())
if err != nil { return nil, err }
if n, werr := conn.Write(smbNegotiate1); werr != nil {
    var nerr net.Error
    if errors.As(werr, &nerr) && nerr.Timeout() {
        return nil, fmt.Errorf("smb negotiate timed out after %v: %w", session.Config.ModuleTimeout(), werr)
    }
    return nil, fmt.Errorf("%s: %w", i18n.GetText("netbios_smb_negotiate_send_failed"), werr)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: check TCP 139 reachability and a sane timeout before scanning
if config.ModuleTimeout() < 2*time.Second {
    return fmt.Errorf("module timeout %v too short for SMB negotiate", config.ModuleTimeout())
}
conn, err := net.DialTimeout("tcp", host+":139", config.ModuleTimeout())
if err != nil {
    return fmt.Errorf("host %s not reachable on TCP 139: %w", host, err)
}
_ = conn.Close()

Type guard

func isNetError(err error) (net.Error, bool) {
    var nerr net.Error
    if errors.As(err, &nerr) {
        return nerr, true
    }
    return nil, false
}

Try / catch

info, err := plugin.Scan(ctx, host, session)
if err != nil {
    var nerr net.Error
    if errors.As(err, &nerr) && nerr.Timeout() {
        log.Printf("skip %s: negotiate send timeout", host)
        return nil // treat as no NetBIOS service
    }
    if errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.EPIPE) {
        log.Printf("skip %s: connection reset during negotiate", host)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling Scan -> queryNetBIOSSession against a host where TCP 139 accepts the connection but the write fails: connection reset by peer immediately after accept, connection closed by the remote host mid-write, or the deadline set via SetDeadline(ModuleTimeout) expiring during the write.

Common situations: Windows hosts with SMB disabled but NetBIOS port-filtering middleware that accepts and drops connections; firewalls/IPS that RST SMB traffic; host crashed or rebooted between dial and write; extremely short ModuleTimeout values causing i/o timeout; scanning hosts that only expose UDP 137 but have a half-open TCP 139 listener.

Related errors


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

Appendix: source

Thrown at plugins/services/netbios.go:217

	_ = conn.SetDeadline(time.Now().Add(session.Config.ModuleTimeout()))

	// 发送SMB协商数据包
	smbNegotiate1 := []byte{
		0x00, 0x00, 0x00, 0x85, 0xFF, 0x53, 0x4D, 0x42, 0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xC8,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02, 0x50, 0x43, 0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F,
		0x52, 0x4B, 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D, 0x20, 0x31, 0x2E, 0x30, 0x00, 0x02,
		0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x31, 0x2E, 0x30, 0x00, 0x02, 0x57, 0x69, 0x6E, 0x64, 0x6F,
		0x77, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x57, 0x6F, 0x72, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x70,
		0x73, 0x20, 0x33, 0x2E, 0x31, 0x61, 0x00, 0x02, 0x4C, 0x4D, 0x31, 0x2E, 0x32, 0x58, 0x30, 0x30,
		0x32, 0x00, 0x02, 0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x32, 0x2E, 0x31, 0x00, 0x02, 0x4E, 0x54,
		0x20, 0x4C, 0x4D, 0x20, 0x30, 0x2E, 0x31, 0x32, 0x00,
	}

	_, err = conn.Write(smbNegotiate1)
	if err != nil {
		return nil, fmt.Errorf("%s: %w", i18n.GetText("netbios_smb_negotiate_send_failed"), err)
	}

	response1 := make([]byte, 1024)
	_, err = conn.Read(response1)
	if err != nil {
		return nil, fmt.Errorf("%s: %w", i18n.GetText("netbios_smb_negotiate_read_failed"), err)
	}

	// 发送Session Setup请求
	smbSessionSetup := []byte{
		0x00, 0x00, 0x01, 0x0A, 0xFF, 0x53, 0x4D, 0x42, 0x73, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0xC8,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
		0x00, 0x00, 0x40, 0x00, 0x0C, 0xFF, 0x00, 0x0A, 0x01, 0x04, 0x41, 0x32, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0xA0, 0xCF, 0x00, 0x60,
		0x48, 0x06, 0x06, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x02, 0xA0, 0x3E, 0x30, 0x3C, 0xA0, 0x0E, 0x30,
		0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0A, 0xA2, 0x2A, 0x04,
		0x28, 0x4E, 0x54, 0x4C, 0x4D, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x82, 0x08,
		0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View on GitHub (pinned to 95cc12e753)