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
|
func handShake(conn net.Conn) (err error) {
const (
idVer = 0
idNmethod = 1
)
buf := make([]byte, 258)
var n int
// make sure we get the nmethod field
if n, err = io.ReadAtLeast(conn, buf, idNmethod+1); err != nil {
return
}
if buf[idVer] != socksVer5 {
return errVer
}
nmethod := int(buf[idNmethod]) // client support auth mode
msgLen := nmethod + 2 // auth msg length
if n == msgLen { // handshake done, common case
// do nothing, jump directly to send confirmation
} else if n < msgLen { // has more methods to read, rare case
if _, err = io.ReadFull(conn, buf[n:msgLen]); err != nil {
return
}
} else { // error, should not get extra data
return errAuthExtraData
}
/*
X'00' NO AUTHENTICATION REQUIRED
X'01' GSSAPI
X'02' USERNAME/PASSWORD
X'03' to X'7F' IANA ASSIGNED
X'80' to X'FE' RESERVED FOR PRIVATE METHODS
X'FF' NO ACCEPTABLE METHODS
*/
if nmethod == 1 {
// 无密码登录,需要验证白名单
// if in list client.Write([]byte{0x05, 0x00})
// else client.Write([]byte{0x05, 0xff}) or client.Write([]byte{0x05, 0x02})
if AllowNobody {
_, err = conn.Write([]byte{socksVer5, 0x00}) //无需认证
return
}
_, _ = conn.Write([]byte{socksVer5, 0xff})
err = errors.New(" not Allow Nobody")
return
} else if nmethod == 2 {
// 用户名/ 密码登录
_, err = conn.Write([]byte{socksVer5, 0x02})
if err != nil {
return
}
} else {
_, err = conn.Write([]byte{socksVer5, 0xff})
if err != nil {
return
}
err = errors.New("method forbidden")
return
}
// 检测用户/密码
_, err = conn.Read(buf[0:])
if err != nil {
return
}
b0 := buf[0]
nameLens := int(buf[1])
uName := string(buf[2 : 2+nameLens])
passLens := int(buf[2+nameLens])
uPass := string(buf[2+nameLens+1 : 2+nameLens+1+passLens])
if uName != userName || uPass != userPass {
_, _ = conn.Write([]byte{b0, 0xff})
err = errors.New("authentication failed")
// 可以对 clientIp 处理,如出错次数,防止被穷取破解
return
}
// send confirmation: version 5, no authentication required
_, err = conn.Write([]byte{b0, 0x00})
return
}
|