Go语言如何建立并维护带身份认证的SOCKS5代理服务器连接
Go语言获取带身份认证的SOCKS5代理服务器连接方案
核心实现逻辑:标准库golang.org/x/net/proxy的SOCKS5方法封装了完整的代理转发流程,如果你只需要和代理本身完成认证后的原始连接,手动实现SOCKS5的认证握手步骤即可,不需要走后续的目标地址CONNECT请求。
可直接使用的实现代码
package main import ( "errors" "net" ) // SOCKS5认证相关常量,符合RFC 1928/RFC 1929规范 const ( socks5Version = 0x05 authMethodPassword = 0x02 authMethodNone = 0x00 authMethodNoAcceptable = 0xFF authPasswordVersion = 0x01 authStatusSuccess = 0x00 ) // DialSocks5WithAuth 直接返回和SOCKS5代理完成认证后的net.Conn连接 func DialSocks5WithAuth(proxyAddr string, username, password string) (net.Conn, error) { // 第一步:先建立和代理服务器的基础TCP连接 conn, err := net.Dial("tcp", proxyAddr) if err != nil { return nil, err } // 第二步:发送认证方法协商请求 // 包结构:版本号+支持的认证方法数量+支持的认证方法列表 authMethods := []byte{authMethodNone, authMethodPassword} negotiateReq := make([]byte, 2+len(authMethods)) negotiateReq[0] = socks5Version negotiateReq[1] = byte(len(authMethods)) copy(negotiateReq[2:], authMethods) if _, err = conn.Write(negotiateReq); err != nil { conn.Close() return nil, err } // 第三步:读取代理返回的认证方法选择响应 negotiateResp := make([]byte, 2) if _, err = conn.Read(negotiateResp); err != nil { conn.Close() return nil, err } if negotiateResp[0] != socks5Version { conn.Close() return nil, errors.New("invalid SOCKS5 version") } chosenMethod := negotiateResp[1] if chosenMethod == authMethodNoAcceptable { conn.Close() return nil, errors.New("proxy does not support any offered auth methods") } // 第四步:如果代理要求用户名密码认证,发送认证凭证 if chosenMethod == authMethodPassword { authReq := make([]byte, 3+len(username)+len(password)) authReq[0] = authPasswordVersion authReq[1] = byte(len(username)) copy(authReq[2:], []byte(username)) authReq[2+len(username)] = byte(len(password)) copy(authReq[3+len(username):], []byte(password)) if _, err = conn.Write(authReq); err != nil { conn.Close() return nil, err } // 读取认证结果 authResp := make([]byte, 2) if _, err = conn.Read(authResp); err != nil { conn.Close() return nil, err } if authResp[1] != authStatusSuccess { conn.Close() return nil, errors.New("SOCKS5 authentication failed") } } // 到这里连接已经完成认证,直接返回即可 return conn, nil } func main() { // 使用示例 proxyConn, err := DialSocks5WithAuth("11.11.11.11:1111", "your_username", "your_password") if err != nil { panic("connect to proxy failed: " + err.Error()) } defer proxyConn.Close() // 后续可以直接使用这个proxyConn和代理服务器交互 }
注意事项
- 上述代码严格遵循SOCKS5协议规范,兼容无认证和用户名密码认证两种场景
- 返回的
proxyConn就是和代理服务器完成认证后的原生net.Conn对象,完全符合预期调用效果 - 如果后续需要用这个代理连接转发请求到目标地址,只需要继续按照SOCKS5协议发送CONNECT请求即可,不需要重复走认证流程
内容的提问来源于stack exchange,提问作者PitaHat
相关产品推荐
相关产品推荐

