shadow1ng/fscan · error

%s: %w

Error message

%s: %w

What it means

performNetworkDiscovery wraps a failed conn.Write of the first RPC request buffer (rpcBuffer1) used for RPC network discovery over a raw TCP connection. The i18n message ('RPC request 1 failed'-style) is prefixed to the underlying net error with %w so callers can errors.Is/As the wrapped cause. This is a low-level I/O failure, not an authentication result.

Source

Thrown at plugins/services/findnet.go:142

	if len(parts) == 0 {
		return i18n.GetText("findnet_complete")
	}
	return strings.Join(parts, ", ")
}

// RPC数据包定义
var (
	rpcBuffer1, _ = hex.DecodeString("05000b03100000004800000001000000b810b810000000000100000000000100c4fefc9960521b10bbcb00aa0021347a00000000045d888aeb1cc9119fe808002b10486002000000")
	rpcBuffer2, _ = hex.DecodeString("050000031000000018000000010000000000000000000500")
	rpcBuffer3, _ = hex.DecodeString("0900ffff0000")
)

// performNetworkDiscovery 执行RPC网络发现
func (p *FindNetPlugin) performNetworkDiscovery(conn net.Conn) (*NetworkInfo, error) {
	// 发送第一个RPC请求
	if _, err := conn.Write(rpcBuffer1); err != nil {
		return nil, fmt.Errorf("%s: %w", i18n.GetText("findnet_rpc_request1_failed"), err)
	}

	// 读取响应
	reply := make([]byte, 4096)
	if _, err := conn.Read(reply); err != nil {
		return nil, fmt.Errorf("%s: %w", i18n.GetText("findnet_rpc_response1_failed"), err)
	}

	// 发送第二个RPC请求
	if _, err := conn.Write(rpcBuffer2); err != nil {
		return nil, fmt.Errorf("%s: %w", i18n.GetText("findnet_rpc_request2_failed"), err)
	}

	// 读取网络信息响应
	n, err := conn.Read(reply)
	if err != nil || n < 42 {
		return nil, fmt.Errorf("%s: %w", i18n.GetText("findnet_rpc_response2_failed"), err)
	}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Check that the target port actually hosts the service (nmap/service probe) before scanning
  2. Retry the scan; transient resets are common on lossy networks
  3. Inspect the wrapped error with errors.Is(err, syscall.ECONNRESET)/net.Error to classify host vs network issues
  4. Verify firewall rules don't drop/reset connections to the discovery port

Example fix

// before
if _, err := conn.Write(rpcBuffer1); err != nil {
    return nil, fmt.Errorf("%s: %w", i18n.GetText("findnet_rpc_request1_failed"), err)
}
// after
if _, err := conn.Write(rpcBuffer1); err != nil {
    if errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) {
        return nil, fmt.Errorf("%s: %w", i18n.GetText("findnet_rpc_request1_failed"), err) // host not RPC; skip
    }
    return nil, fmt.Errorf("%s: %w", i18n.GetText("findnet_rpc_request1_failed"), err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: pre-check connectivity before Scan
conn, err := net.DialTimeout("tcp", target, 3*time.Second)
if err != nil { return fmt.Errorf("target unreachable: %w", err) }
conn.Close()

Type guard

func isTransientNetErr(err error) bool {
    var ne net.Error
    return errors.As(err, &ne) && ne.Timeout() || errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.EPIPE)
}

Try / catch

info, err := plugin.performNetworkDiscovery(conn)
if err != nil {
    if isTransientNetErr(err) { /* retry or skip host */ }
    log.Printf("discovery failed for %s: %v", target, err)
    return
}

Prevention

When it happens

Trigger: Scan -> performNetworkDiscovery: the first conn.Write(rpcBuffer1) on the target host's RPC port returns an error — connection reset, broken pipe, or write on an already-closed/failed connection.

Common situations: Target host closes the TCP connection immediately upon connect (RPC service not actually listening on that port); firewall or IDS resets the connection after inspecting the payload; scanning a non-RPC port that got bound by another service; network unreachable mid-scan.

Related errors


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