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()
}大家可以根据实际需求对这个服务进行修改。
文章作者:沃航科技