Golang实现socks5 proxy服务

平时难免有一些访问“外网”的需要,或者网络爬虫需要一些代理,也有方式能够购买一些代理ip,但如果想很简单的部署一个稳定的代理ip,那么这里提供一个参考,使用Golang实现的sock5代理服务。

可以参考https://github.com/innerpeace-forever/socks_proxy

基于README的说明,可以完成编译和部署

Installation

在linux服务器上,将源代码clone到$GOPATH/src/目录下,并执行编译。如果是云服务器,记得在安全组中开放网络端口。

git clone https://github.com/innerpeace-forever/socks_proxy.git
mv socks_proxy $GOPATH/src/
cd $GOPATH/src/socks_proxy
sh -x build/build.sh
# 如果运行可以直接
# sh -x build/deploy.sh

Configuration

除了基本的日志配置外(可以不用动),最主要的是配置端口。在conf/conf.toml上

[Other.Service]
Port = 8080

代码说明

原理其实比较简单,几个关键步骤如下。代码是从git中截取的散乱片段,如果要直接使用,可以从https://github.com/innerpeace-forever/socks_proxy 直接clone、编译和运行。

  • 建立tcp服务端口(用于客户端发起socks5的代理请求)
l, err := net.Listen("tcp", address)
		if err != nil {
			seelog.Infof("Listen[%v] Failed! ERR:%v", address, err)
			return err
		}

		for {
			client, err := l.Accept()
			if err != nil {
				seelog.Errorf("Accept Failed! Error:%v", err)
				continue
			}
			go handleClientRequest(client)

			if waitStopSignalNonBlock() {
				break
			}
		}
  • 解析socks5的头部协议,并且发起目标网站的tcp连接
if b[0] == 0x05 {
		// Just process Socks5 protocol
		// Without authentication
		client.Write([]byte{0x05, 0x00})
		n, err = client.Read(b[:])
		if err != nil || n < 4 {
			seelog.Errorf("handleClientRequest Read Failed! Error%:%v", err)
			return
		}
		var host, port string
		switch b[3] {
		case 0x01: //IP V4
			host = net.IPv4(b[4], b[5], b[6], b[7]).String()
		case 0x03: //Domain
			host = string(b[5 : n-2]) //b[4]表示域名的长度
		case 0x04: //IP V6
			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()
		}
		port = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1]))

		server, err := net.Dial("tcp", net.JoinHostPort(host, port))
		if err != nil {
			seelog.Errorf("handleClientRequest Dial(%s, %s) Failed! Error:%v", host, port, err)
			return
		}
		seelog.Infof("New Connection, Dial(%s:%s).", host, port)
		defer server.Close()
		client.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) //响应客户端连接成功
}
  • 双向的转发
go io.Copy(server, client)
io.Copy(client, server)