-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshared.go
More file actions
143 lines (128 loc) · 2.62 KB
/
shared.go
File metadata and controls
143 lines (128 loc) · 2.62 KB
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
package socks5 // import go.ideatocode.tech/socks5
import (
"encoding/binary"
"fmt"
"io"
"net"
)
// RequestHeader holds the header of the socks5 connection request
type RequestHeader struct {
Bin struct {
ver byte
cmd byte
rsv byte
atyp byte
addr *[]byte
port []byte
}
Port int
Addr string
}
type requestBinHeader struct {
ver byte
cmd byte
rsv byte
atyp byte
addr *[]byte
port []byte
}
// AuthHeader is used to perform User/Password socks5 authentication
type AuthHeader struct {
Bin authBinHeader
Username string
Password string
}
type authBinHeader struct {
ver byte
ulen byte
uname []byte
plen byte
passwd []byte
}
// WriteTo writes the header to w
func (h *authBinHeader) WriteTo(w io.Writer) (int64, error) {
buf := []byte{h.ver, h.ulen}
buf = append(buf, h.uname...)
buf = append(buf, h.plen)
buf = append(buf, h.passwd...)
n, err := w.Write(buf)
return int64(n), err
}
// WriteTo writes the header to w
func (h *requestBinHeader) WriteTo(w io.Writer) (int64, error) {
buf := []byte{h.ver, h.cmd, h.rsv, h.atyp}
buf = append(buf, *h.addr...)
buf = append(buf, h.port...)
n, err := w.Write(buf)
return int64(n), err
}
func readReqHeader(c net.Conn, outgoing bool) (*RequestHeader, error) {
rh := RequestHeader{}
h1 := make([]byte, 4)
n, err := c.Read(h1)
if n != 4 || err != nil {
return nil, err
}
cmd := h1[1]
rh.Bin.ver = h1[0]
rh.Bin.cmd = h1[1]
atyp := h1[3]
rh.Bin.atyp = h1[3]
var addr string
switch atyp {
// if ipv4
case 0x01:
var b net.IP
b = make([]byte, 4)
n, err = c.Read(b)
if n != 4 || err != nil {
return nil, err
}
bn := []byte(b)
rh.Bin.addr = &bn
addr = b.String()
// if domain
case 0x03:
addrl := make([]byte, 1)
n, err = c.Read(addrl)
if n != 1 || err != nil {
return nil, err
}
addrb := make([]byte, int(addrl[0])+1)
addrb[0] = addrl[0]
n, err = c.Read(addrb[1:])
if n != int(addrl[0]) || err != nil {
return nil, err
}
rh.Bin.addr = &addrb
addr = string(addrb[1:])
// if ipv6
case 0x04:
var b net.IP
b = make([]byte, 16)
n, err = c.Read(b)
if n != 16 || err != nil {
return nil, err
}
bn := []byte(b)
rh.Bin.addr = &bn
addr = b.String()
}
portb := make([]byte, 2)
rh.Bin.port = portb
n, err = c.Read(portb)
if n != 2 || err != nil {
return nil, err
}
port := binary.BigEndian.Uint16(portb)
rh.Addr = addr
rh.Port = int(port)
// only connect allowed
if outgoing && cmd != 0x01 {
return nil, fmt.Errorf("Only Connect: %X, %s:%d", cmd, addr, rh.Port)
}
if !outgoing && cmd != 0x00 {
return nil, fmt.Errorf("Server refused: %X, %s:%d", cmd, addr, rh.Port)
}
return &rh, nil
}