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)
}
}
这个实现包含以下关键部分:
- SOCKS5检测:发送SOCKS5握手请求,验证服务器响应,然后发送连接请求确认
- SOCKS4检测:发送标准的SOCKS4连接请求
- SOCKS4a检测:发送包含域名的SOCKS4a请求
- 批量处理:
detectSocksTypes函数可以处理IP:Port列表
检测逻辑基于各版本SOCKS协议的响应格式:
- SOCKS5:版本号0x05,成功响应为0x00
- SOCKS4/SOCKS4a:成功响应第一个字节为0x00,第二个字节为0x5A
使用时需要注意:
- 需要处理网络超时和错误
- 某些代理服务器可能同时支持多个版本
- 检测过程需要按顺序进行,因为SOCKS5和SOCKS4的握手协议不同

