shadow1ng/fscan · info

local_address_unavailable

Error message

local_address_unavailable

What it means

After a successful dial, the code type-asserts targetConn.LocalAddr() to *net.TCPAddr to learn the local outbound port; the assertion failed, so the local port cannot be reported in the SOCKS5 success reply and the request aborts.

Solutions

  1. Confirm the connection is dialed with the standard "tcp" network (it is), making this branch unreachable in practice
  2. If a custom dialer is injected, ensure it returns *net.TCPAddr for LocalAddr
  3. Handle gracefully by falling back to port 0 or skipping the assertion instead of failing the request

Example fix

// before
localAddr, ok := targetConn.LocalAddr().(*net.TCPAddr)
if !ok {
    return nil, 0, fmt.Errorf("%s", i18n.GetText("local_address_unavailable"))
}
// after
localPort := 0
if localAddr, ok := targetConn.LocalAddr().(*net.TCPAddr); ok {
    localPort = localAddr.Port
}
Defensive patterns

Strategy: fallback

Validate before calling

// unreachable via public API; ensure standard "tcp" dial is used

Type guard

func tcpLocalPort(c net.Conn) (int, bool) {
    a, ok := c.LocalAddr().(*net.TCPAddr)
    if !ok { return 0, false }
    return a.Port, true
}

Prevention

When it happens

Trigger: LocalAddr() returns a non-*net.TCPAddr value. Practically almost impossible for a net.DialTimeout("tcp") connection; would require a nonstandard net implementation or mocked conn.

Common situations: Custom or test net.Dialer wrappers returning non-TCP addr types; hypothetical changes to dial transport.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at plugins/local/socks5proxy.go:267

	}
	if targetPort == 0 {
		return nil, 0, fmt.Errorf("%s", i18n.GetText("socks5_invalid_request"))
	}

	// 连接目标服务器
	targetAddr := net.JoinHostPort(targetHost, strconv.Itoa(int(targetPort)))
	targetConn, err := net.DialTimeout("tcp", targetAddr, 10*time.Second)
	if err != nil {
		// 发送连接失败响应
		response := []byte{0x05, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
		_, _ = clientConn.Write(response)
		return nil, 0, fmt.Errorf("%s: %w", i18n.GetText("socks5_target_connect_failed"), err)
	}

	// 获取本地监听端口(从targetConn获取)
	localAddr, ok := targetConn.LocalAddr().(*net.TCPAddr)
	if !ok {
		return nil, 0, fmt.Errorf("%s", i18n.GetText("local_address_unavailable"))
	}
	localPort := localAddr.Port

	// 发送成功响应
	response := make([]byte, 10)
	response[0] = 0x05 // SOCKS版本
	response[1] = 0x00 // 成功
	response[2] = 0x00 // 保留
	response[3] = 0x01 // IPv4地址类型
	// 绑定地址和端口(使用127.0.0.1:localPort)
	copy(response[4:8], []byte{127, 0, 0, 1})
	response[8] = byte(localPort >> 8)
	response[9] = byte(localPort & 0xff)

	_, err = clientConn.Write(response)
	if err != nil {
		_ = targetConn.Close()
		return nil, 0, fmt.Errorf("%s: %w", i18n.GetText("socks5_success_response_failed"), err)

View on GitHub (pinned to 95cc12e753)