-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathreply.go
99 lines (90 loc) · 3.35 KB
/
reply.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
package socks
import (
"bytes"
"encoding/binary"
)
/*
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
Where:
o VER protocol version: X'05'
o REP Reply field:
o X'00' succeeded
o X'01' general SOCKS server failure
o X'02' connection not allowed by ruleset
o X'03' Network unreachable
o X'04' Host unreachable
o X'05' Connection refused
o X'06' TTL expired
o X'07' Command not supported
o X'08' Address type not supported
o X'09' to X'FF' unassigned
o RSV RESERVED
o ATYP address type of following address
o IP V4 address: X'01'
o DOMAINNAME: X'03'
o IP V6 address: X'04'
o BND.ADDR server bound address
o BND.PORT server bound port in network octet order
Fields marked RESERVED (RSV) must be set to X'00'.
CONNECT
In the reply to a CONNECT, BND.PORT contains the port number that the
server assigned to connect to the target host, while BND.ADDR
contains the associated IP address. The supplied BND.ADDR is often
different from the IP address that the client uses to reach the SOCKS
server, since such servers are often multi-homed. It is expected
that the SOCKS server will use DST.ADDR and DST.PORT, and the
client-side source address and port in evaluating the CONNECT
request.
*/
func requestReply(request *Request, reply RequestReplyReason) ([]byte, error) {
buffer := bytes.NewBuffer(nil)
if err := binary.Write(buffer, binary.BigEndian, Version5.Value()); err != nil {
return nil, err
}
if err := binary.Write(buffer, binary.BigEndian, reply.Value()); err != nil {
return nil, err
}
if err := binary.Write(buffer, binary.BigEndian, byte(0x00)); err != nil {
return nil, err
}
if request != nil {
if err := binary.Write(buffer, binary.BigEndian, request.AddressType.Value()); err != nil {
return nil, err
}
// type
if request.AddressType == RequestAddressTypeIPv4 {
if err := binary.Write(buffer, binary.BigEndian, request.DestinationAddress); err != nil {
return nil, err
}
} else if request.AddressType == RequestAddressTypeIPv6 {
if err := binary.Write(buffer, binary.BigEndian, request.DestinationAddress); err != nil {
return nil, err
}
} else {
if err := binary.Write(buffer, binary.BigEndian, byte(len(request.DestinationAddress))); err != nil {
return nil, err
}
if err := binary.Write(buffer, binary.BigEndian, request.DestinationAddress); err != nil {
return nil, err
}
}
if err := binary.Write(buffer, binary.BigEndian, request.DestinationPort); err != nil {
return nil, err
}
} else {
if err := binary.Write(buffer, binary.BigEndian, RequestAddressTypeIPv4.Value()); err != nil {
return nil, err
}
if err := binary.Write(buffer, binary.BigEndian, []byte{0, 0, 0, 0}); err != nil {
return nil, err
}
if err := binary.Write(buffer, binary.BigEndian, uint16(0)); err != nil {
return nil, err
}
}
return buffer.Bytes(), nil
}