/
sock5_client.go
186 lines (164 loc) · 4.4 KB
/
sock5_client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package h2proxy
import (
"fmt"
"net"
"strconv"
//"os"
"errors"
)
type targetInfo struct {
host string
port string
}
type Sock5Proxy struct {
Config *ClientConfig
}
func auth(conn net.Conn) error {
/* VER NMETHODS METHODS
1 1 1-255
VER是SOCKS版本,这里应该是0x05;
NMETHODS是METHODS部分的长度;
METHODS是客户端支持的认证方式列表,每个方法占1字节。当前的定义是:
0x00 不需要认证
0x01 GSSAPI
0x02 用户名、密码认证
0x03 - 0x7F由IANA分配(保留)
0x80 - 0xFE为私人方法保留
0xFF 无可接受的方法*/
res := make([]byte, 2)
_, err := conn.Read(res)
if err != nil {
Log.Error(err)
return err
}
Log.Info(res)
methodLength := res[1]
method := make([]byte, methodLength)
conn.Read(method)
Log.Info(method)
/* 服务器从客户端提供的方法中选择一个并通过以下消息通知客户端(以字节为单位):
VER METHOD
1 1
VER是SOCKS版本,这里应该是0x05;
METHOD是服务端选中的方法。如果返回0xFF表示没有一个认证方法被选中,客户端需要关闭连接。
REP应答字段
0x00表示成功
0x01普通SOCKS服务器连接失败
0x02现有规则不允许连接
0x03网络不可达
0x04主机不可达
0x05连接被拒
0x06 TTL超时
0x07不支持的命令
0x08不支持的地址类型
0x09 - 0xFF未定义*/
resp := []byte{5, 0}
conn.Write(resp)
return nil
}
func buildDestConn(conn net.Conn) (*targetInfo, error) {
/* VER CMD RSV ATYP DST.ADDR DST.PORT
1 1 0x00 1 动态 2
VER是SOCKS版本,这里应该是0x05;
CMD是SOCK的命令码
0x01表示CONNECT请求
0x02表示BIND请求
0x03表示UDP转发
RSV 0x00,保留
ATYP DST.ADDR类型
0x01 IPv4地址,DST.ADDR部分4字节长度
0x03 域名,DST.ADDR部分第一个字节为域名长度,DST.ADDR剩余的内容为域名,没有\0结尾。
0x04 IPv6地址,16个字节长度。
DST.ADDR 目的地址
DST.PORT 网络字节序表示的目的端口*/
res := make([]byte, 1024)
n, err := conn.Read(res)
if err != nil {
Log.Error(err)
return nil, err
}
Log.Info(res[:n])
if res[1] != 1 {
Log.Warn("MEHOTDS NOT SUPPORTED")
resp := []byte{5, 7, 0}
conn.Write(resp)
return nil, err
}
target := targetInfo{}
if res[3] == 1 {
// ipv4
addr := fmt.Sprintf("%d.%d.%d.%d", res[4], res[5], res[6], res[7])
port := int(res[8])*256 + int(res[9])
target.port = strconv.Itoa(port)
target.host = addr
resp := []byte{5, 0, 0, res[3], res[4], res[5], res[6], res[7], res[8], res[9]}
conn.Write(resp)
} else if res[3] == 3 {
// domain`
length := int(res[4])
addr := res[5 : 5+length]
target.host = string(addr)
port := int(res[4+length+1])*256 + int(res[4+length+2])
target.port = strconv.Itoa(port)
resp := []byte{5, 0, 0, res[3], res[4]}
resp = append(resp, res[5:n]...)
Log.Info(string(resp))
Log.Info((resp))
conn.Write(resp)
} else if res[3] == 4 {
resp := []byte{5, 8, 0}
conn.Write((resp))
Log.Info("IPV6 Not Implemented")
return nil, errors.New("ipv6 NotImplemnted")
}
/* 服务器按以下格式回应客户端的请求(以字节为单位):
VER REP RSV ATYP BND.ADDR BND.PORT
1 1 0x00 1 动态 2
VER是SOCKS版本,这里应该是0x05;
REP应答字段
0x00表示成功
0x01普通SOCKS服务器连接失败
0x02现有规则不允许连接
0x03网络不可达
0x04主机不可达
0x05连接被拒
0x06 TTL超时
0x07不支持的命令
0x08不支持的地址类型
0x09 - 0xFF未定义
RSV 0x00,保留
ATYP BND.ADDR类型
0x01 IPv4地址,DST.ADDR部分4字节长度
0x03域名,DST.ADDR部分第一个字节为域名长度,DST.ADDR剩余的内容为域名,没有\0结尾。
0x04 IPv6地址,16个字节长度。
BND.ADDR 服务器绑定的地址
BND.PORT 网络字节序表示的服务器绑定的端口*/
return &target, nil
}
func handleConnection(conn net.Conn, config *ClientConfig) {
defer closeConn(conn)
err := auth(conn)
if err != nil {
return
}
dest, err := buildDestConn(conn)
if dest == nil || err != nil {
return
}
remoteAddr := "http://" + dest.host + ":" + dest.port
CreateTunnel(conn, remoteAddr, config)
}
func (s Sock5Proxy) Start() {
config := s.Config
ln, err := net.Listen("tcp", config.Local)
if err != nil {
Log.Fatal(err)
}
for {
conn, err := ln.Accept()
if err != nil {
Log.Fatal(err)
}
go handleConnection(conn, config)
}
}