Golang中如何判断socks类型

Golang中如何判断socks类型 如何确定 socks 类型?socks4、4a、5?

我有一组 ip:port 列表,该如何实现?

1 回复

更多关于Golang中如何判断socks类型的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,可以通过与SOCKS代理服务器进行握手来检测其支持的SOCKS类型(SOCKS4、SOCKS4a或SOCKS5)。以下是基于SOCKS协议规范实现的检测方法:

package main

import (
    "encoding/binary"
    "fmt"
    "net"
    "time"
)

const (
    SOCKS4Version = 0x04
    SOCKS5Version = 0x05
)

// SOCKS4请求结构
var socks4Request = []byte{
    SOCKS4Version, // SOCKS版本号
    0x01,          // CONNECT命令
    0x00, 0x50,    // 端口80
    0x00, 0x00, 0x00, 0x01, // IP地址 0.0.0.1
    0x00, // 用户ID结束
}

// SOCKS5握手请求
var socks5Handshake = []byte{
    SOCKS5Version, // SOCKS版本号
    0x01,          // 认证方法数量
    0x00,          // 不需要认证
}

// SOCKS5连接请求
var socks5ConnectRequest = []byte{
    SOCKS5Version, // SOCKS版本号
    0x01,          // CONNECT命令
    0x00,          // 保留字段
    0x01,          // IPv4地址类型
    0x00, 0x00, 0x00, 0x01, // 目标IP 0.0.0.1
    0x00, 0x50, // 端口80
}

func detectSocksType(host string, port string) (string, error) {
    address := net.JoinHostPort(host, port)
    conn, err := net.DialTimeout("tcp", address, 5*time.Second)
    if err != nil {
        return "", err
    }
    defer conn.Close()

    // 设置读取超时
    conn.SetReadDeadline(time.Now().Add(5 * time.Second))

    // 首先尝试SOCKS5
    _, err = conn.Write(socks5Handshake)
    if err != nil {
        return "", err
    }

    // 读取SOCKS5握手响应
    response := make([]byte, 2)
    _, err = conn.Read(response)
    if err == nil && response[0] == SOCKS5Version && response[1] == 0x00 {
        // 发送SOCKS5连接请求确认
        _, err = conn.Write(socks5ConnectRequest)
        if err != nil {
            return "", err
        }

        // 读取连接响应
        connectResponse := make([]byte, 10)
        _, err = conn.Read(connectResponse)
        if err == nil && connectResponse[0] == SOCKS5Version && connectResponse[1] == 0x00 {
            return "SOCKS5", nil
        }
    }

    // 重置连接进行SOCKS4检测
    conn.Close()
    conn, err = net.DialTimeout("tcp", address, 5*time.Second)
    if err != nil {
        return "", err
    }
    defer conn.Close()
    conn.SetReadDeadline(time.Now().Add(5 * time.Second))

    // 尝试SOCKS4
    _, err = conn.Write(socks4Request)
    if err != nil {
        return "", err
    }

    // 读取SOCKS4响应
    socks4Response := make([]byte, 8)
    _, err = conn.Read(socks4Response)
    if err == nil && socks4Response[0] == 0x00 && socks4Response[1] == 0x5A {
        return "SOCKS4", nil
    }

    // 尝试SOCKS4a(需要发送域名)
    socks4aRequest := make([]byte, 0)
    socks4aRequest = append(socks4aRequest, socks4Request[:8]...)
    socks4aRequest = append(socks4aRequest, []byte("example.com")...)
    socks4aRequest = append(socks4aRequest, 0x00)

    _, err = conn.Write(socks4aRequest)
    if err != nil {
        return "", err
    }

    _, err = conn.Read(socks4Response)
    if err == nil && socks4Response[0] == 0x00 && socks4Response[1] == 0x5A {
        return "SOCKS4a", nil
    }

    return "Unknown", nil
}

// 批量检测函数
func detectSocksTypes(proxies []string) map[string]string {
    results := make(map[string]string)
    
    for _, proxy := range proxies {
        host, port, err := net.SplitHostPort(proxy)
        if err != nil {
            results[proxy] = "Invalid address"
            continue
        }

        socksType, err := detectSocksType(host, port)
        if err != nil {
            results[proxy] = "Error: " + err.Error()
        } else {
            results[proxy] = socksType
        }
    }
    
    return results
}

func main() {
    // 示例用法
    proxies := []string{
        "127.0.0.1:1080",
        "192.168.1.1:1080",
        "10.0.0.1:1080",
    }

    results := detectSocksTypes(proxies)
    
    for proxy, socksType := range results {
        fmt.Printf("%s: %s\n", proxy, socksType)
    }
}

这个实现包含以下关键部分:

  1. SOCKS5检测:发送SOCKS5握手请求,验证服务器响应,然后发送连接请求确认
  2. SOCKS4检测:发送标准的SOCKS4连接请求
  3. SOCKS4a检测:发送包含域名的SOCKS4a请求
  4. 批量处理detectSocksTypes函数可以处理IP:Port列表

检测逻辑基于各版本SOCKS协议的响应格式:

  • SOCKS5:版本号0x05,成功响应为0x00
  • SOCKS4/SOCKS4a:成功响应第一个字节为0x00,第二个字节为0x5A

使用时需要注意:

  • 需要处理网络超时和错误
  • 某些代理服务器可能同时支持多个版本
  • 检测过程需要按顺序进行,因为SOCKS5和SOCKS4的握手协议不同
回到顶部