go语言是一个异步IO的高并发编程语言,用他开发的socks5服务器同样继承了其高并发的特点。下面的代码是我根据网上流传的版本修改的,解决了网上的代码存在内存泄漏的问题,可以很好的运用于小文件的代理上网。
package main import ( "log" "net" "io" "runtime" "strconv" ) func main() { runtime.GOMAXPROCS(1) log.SetFlags(log.LstdFlags | log.Lshortfile) log.Println("version: " + runtime.Version()) Socks5Accept(8889) } func Socks5Accept (port int) { tcpaddr := &net.TCPAddr{ IP: []byte{0, 0, 0, 0}, Port: port, Zone: "", } l, err := net.ListenTCP("tcp", tcpaddr) if err != nil { log.Println(err) return } for { client, err := l.AcceptTCP() if err != nil { log.Println(err) l.Close() return } go Socks5Request(client) } } func Socks5Request (client *net.TCPConn) { client.SetReadBuffer(32*1024) client.SetWriteBuffer(32*1024) b := make([]byte, 32*1024) _, err := client.Read(b) if err != nil { log.Println(err) client.Close() return } if b[0] == 0x05 { //只处理Socks5协议 // 客户端回应:Socks服务端不需要验证方式 _, err = client.Write([]byte{0x05, 0x00}) if err != nil { log.Println(err) client.Close() return } n, err := client.Read(b) if err != nil { log.Println(err) client.Close() return } var host string switch b[3] { case 0x01: //IP V4 if n <= 9 { client.Close() return } host = net.IPv4(b[4], b[5], b[6], b[7]).String() case 0x03: //域名 if n <= 7 { client.Close() return } host = string(b[5 : n-2]) //b[4]表示域名的长度 case 0x04: //IP V6 if n <= 21 { client.Close() return } host = net.IP{b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19]}.String() default: client.Close() return } address := net.JoinHostPort(host, strconv.Itoa(int(b[n-2])<<8 | int(b[n-1]))) log.Println(address); tcpaddr, err := net.ResolveTCPAddr("tcp", address) if err != nil { log.Println(err) client.Close() return } server, err := net.DialTCP("tcp", nil, tcpaddr) if err != nil { log.Println(err) client.Close() return } _, err = client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) //响应客户端连接成功 if err != nil { log.Println(err) client.Close() server.Close() return } go IoCopy(client, server) go IoCopy(server, client) } } func IoCopy(dst *net.TCPConn, src *net.TCPConn) { io.Copy(dst, src) dst.Close() }
大家可以根据实际需求对这个服务进行修改。
文章作者:沃航科技