@@ -11,6 +11,7 @@ import (
11
11
"net/url"
12
12
"os"
13
13
"strconv"
14
+ "strings"
14
15
15
16
"github.com/gorilla/websocket"
16
17
uuid "github.com/satori/go.uuid"
@@ -46,91 +47,125 @@ func main() {
46
47
go handleConnection (conn )
47
48
}
48
49
}
50
+ func convertToMap (input string ) map [string ]string {
51
+ result := make (map [string ]string )
52
+
53
+ lines := strings .Split (input , "\n " )
54
+ for _ , line := range lines {
55
+ parts := strings .SplitN (line , ": " , 2 )
56
+ if len (parts ) == 2 {
57
+ result [strings .ToLower (strings .TrimSpace (parts [0 ]))] = strings .TrimSpace (parts [1 ])
58
+ }
59
+ }
60
+
61
+ return result
62
+ }
49
63
50
64
func handleConnection (clientConn net.Conn ) {
51
65
defer clientConn .Close ()
52
66
53
67
// Step 1: Version identification and authentication
54
68
// Read and verify the SOCKS5 initial handshake message
55
69
buf := make ([]byte , 257 )
56
- _ , err := io .ReadAtLeast (clientConn , buf , 2 )
70
+ nbytes , err := io .ReadAtLeast (clientConn , buf , 2 )
57
71
if err != nil {
58
72
log .Printf ("Failed to read client handshake: %v" , err )
59
73
return
60
74
}
75
+ _ = nbytes
61
76
77
+ var destAddr string
78
+ var destPort string
79
+ isSocks5 := false
80
+ isHttps := false
62
81
// Check SOCKS version and authentication methods
63
- if buf [0 ] != 0x05 {
64
- log .Printf ("Unsupported SOCKS version: %v" , buf [0 ])
65
- return
66
- }
82
+ if buf [0 ] == 0x05 {
83
+ isSocks5 = true
84
+ // Number of authentication methods supported
85
+ numMethods := int (buf [1 ])
86
+ authMethods := buf [2 : 2 + numMethods ]
67
87
68
- // Number of authentication methods supported
69
- numMethods := int (buf [1 ])
70
- authMethods := buf [2 : 2 + numMethods ]
88
+ // Check if "no authentication" method (0x00) is supported
89
+ noAuth := false
90
+ for _ , m := range authMethods {
91
+ if m == 0x00 {
92
+ noAuth = true
93
+ break
94
+ }
95
+ }
71
96
72
- // Check if "no authentication" method (0x00) is supported
73
- noAuth := false
74
- for _ , m := range authMethods {
75
- if m == 0x00 {
76
- noAuth = true
77
- break
97
+ if ! noAuth {
98
+ log .Printf ("No supported authentication methods" )
99
+ // Send handshake failure response to client
100
+ clientConn .Write ([]byte {0x05 , 0xFF })
101
+ return
78
102
}
79
- }
80
103
81
- if ! noAuth {
82
- log .Printf ("No supported authentication methods" )
83
- // Send handshake failure response to client
84
- clientConn .Write ([]byte {0x05 , 0xFF })
85
- return
86
- }
104
+ // Send handshake response to client indicating "no authentication" method
105
+ clientConn .Write ([]byte {0x05 , 0x00 })
87
106
88
- // Send handshake response to client indicating "no authentication" method
89
- clientConn .Write ([]byte {0x05 , 0x00 })
107
+ // Step 2: Request processing
108
+ // Read and verify the SOCKS5 request
109
+ _ , err = io .ReadAtLeast (clientConn , buf , 4 )
110
+ if err != nil {
111
+ log .Printf ("Failed to read client request: %v" , err )
112
+ return
113
+ }
90
114
91
- // Step 2: Request processing
92
- // Read and verify the SOCKS5 request
93
- _ , err = io .ReadAtLeast (clientConn , buf , 4 )
94
- if err != nil {
95
- log .Printf ("Failed to read client request: %v" , err )
96
- return
97
- }
115
+ if buf [0 ] != 0x05 {
116
+ log .Printf ("Unsupported SOCKS version: %v" , buf [0 ])
117
+ return
118
+ }
98
119
99
- if buf [0 ] != 0x05 {
100
- log .Printf ("Unsupported SOCKS version : %v" , buf [0 ])
101
- return
102
- }
120
+ if buf [1 ] != 0x01 {
121
+ log .Printf ("Unsupported command : %v" , buf [1 ])
122
+ return
123
+ }
103
124
104
- if buf [1 ] != 0x01 {
105
- log .Printf ("Unsupported command: %v" , buf [1 ])
106
- return
107
- }
125
+ // Check the address type
126
+ switch buf [3 ] {
127
+ case 0x01 : // IPv4 address
128
+ ip := net .IP (buf [4 : 4 + net .IPv4len ])
129
+ destAddr = ip .String ()
130
+ destPort = fmt .Sprintf ("%d" , int (buf [8 ])<< 8 + int (buf [9 ]))
131
+ case 0x03 : // Domain name
132
+ domainLen := int (buf [4 ])
133
+ domain := string (buf [5 : 5 + domainLen ])
134
+ destAddr = domain
135
+ destPort = strconv .Itoa (int (buf [5 + domainLen ])<< 8 + int (buf [5 + domainLen + 1 ]))
136
+ case 0x04 : // IPv6 address
137
+ ip := net .IP (buf [4 : 4 + net .IPv6len ])
138
+ destAddr = ip .String ()
139
+ destPort = strconv .Itoa (int (buf [20 ])<< 8 + int (buf [21 ]))
140
+ default :
141
+ log .Printf ("Unsupported address type: %v" , buf [3 ])
142
+ return
143
+ }
108
144
109
- // Check the address type
110
- var destAddr string
111
- var destPort string
112
- switch buf [3 ] {
113
- case 0x01 : // IPv4 address
114
- ip := net .IP (buf [4 : 4 + net .IPv4len ])
115
- destAddr = ip .String ()
116
- destPort = fmt .Sprintf ("%d" , int (buf [8 ])<< 8 + int (buf [9 ]))
117
- case 0x03 : // Domain name
118
- domainLen := int (buf [4 ])
119
- domain := string (buf [5 : 5 + domainLen ])
120
- destAddr = domain
121
- destPort = strconv .Itoa (int (buf [5 + domainLen ])<< 8 + int (buf [5 + domainLen + 1 ]))
122
- case 0x04 : // IPv6 address
123
- ip := net .IP (buf [4 : 4 + net .IPv6len ])
124
- destAddr = ip .String ()
125
- destPort = strconv .Itoa (int (buf [20 ])<< 8 + int (buf [21 ]))
126
- default :
127
- log .Printf ("Unsupported address type: %v" , buf [3 ])
128
- return
145
+ // Send request response to client indicating success
146
+ clientConn .Write ([]byte {0x05 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 })
147
+ } else if (buf [0 ] == 'G' && buf [1 ] == 'E' ) || (buf [0 ] == 'P' && buf [1 ] == 'O' ) || (buf [0 ] == 'O' && buf [1 ] == 'P' ) || (buf [0 ] == 'P' && buf [1 ] == 'U' ) || (buf [0 ] == 'D' && buf [1 ] == 'E' ) || (buf [0 ] == 'H' && buf [1 ] == 'E' ) || (buf [0 ] == 'T' && buf [1 ] == 'R' ) {
148
+ r := convertToMap (string (buf [:nbytes ]))
149
+ hosts := r ["host" ]
150
+ if strings .Index (hosts , ":" ) == - 1 {
151
+ destAddr = hosts
152
+ destPort = "80"
153
+ } else {
154
+ destAddr = strings .Split (hosts , ":" )[0 ]
155
+ destPort = strings .Split (hosts , ":" )[1 ]
156
+ }
157
+ } else if buf [0 ] == 'C' && buf [1 ] == 'O' {
158
+ isHttps = true
159
+ r := convertToMap (string (buf [:nbytes ]))
160
+ hosts := r ["host" ]
161
+ if strings .Index (hosts , ":" ) == - 1 {
162
+ destAddr = hosts
163
+ destPort = "443"
164
+ } else {
165
+ destAddr = strings .Split (hosts , ":" )[0 ]
166
+ destPort = strings .Split (hosts , ":" )[1 ]
167
+ }
129
168
}
130
-
131
- // Send request response to client indicating success
132
- clientConn .Write ([]byte {0x05 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 })
133
-
134
169
u := url.URL {
135
170
Scheme : "ws" ,
136
171
Host : * wsServer ,
@@ -175,6 +210,15 @@ func handleConnection(clientConn net.Conn) {
175
210
clientConn .Close ()
176
211
return
177
212
}
213
+ if isHttps {
214
+ clientConn .Write ([]byte ("HTTP/1.1 200 Connection Established\r \n \r \n " ))
215
+ }
216
+ if false == isSocks5 && false == isHttps {
217
+ err = ws .Conn .WriteJSON (common.Proto {MsgType : common .ReqData , Data : buf [:nbytes ]})
218
+ if err != nil {
219
+ log .Printf ("[%s]Failed to send http data to WebSocket server: %v" , msgId , err )
220
+ }
221
+ }
178
222
go func () {
179
223
resp := common.Proto {}
180
224
for {
0 commit comments