Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/js/libs/net/net.go
2070 views
1
package net
2
3
import (
4
"context"
5
"crypto/tls"
6
"encoding/hex"
7
"fmt"
8
"net"
9
"time"
10
11
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
12
"github.com/projectdiscovery/nuclei/v3/pkg/types"
13
"github.com/projectdiscovery/utils/errkit"
14
"github.com/projectdiscovery/utils/reader"
15
)
16
17
var (
18
defaultTimeout = time.Duration(5) * time.Second
19
)
20
21
// Open opens a new connection to the address with a timeout.
22
// supported protocols: tcp, udp
23
// @example
24
// ```javascript
25
// const net = require('nuclei/net');
26
// const conn = net.Open('tcp', 'acme.com:80');
27
// ```
28
func Open(ctx context.Context, protocol, address string) (*NetConn, error) {
29
executionId := ctx.Value("executionId").(string)
30
dialer := protocolstate.GetDialersWithId(executionId)
31
if dialer == nil {
32
return nil, fmt.Errorf("dialers not initialized for %s", executionId)
33
}
34
conn, err := dialer.Fastdialer.Dial(ctx, protocol, address)
35
if err != nil {
36
return nil, err
37
}
38
return &NetConn{conn: conn, timeout: defaultTimeout}, nil
39
}
40
41
// Open opens a new connection to the address with a timeout.
42
// supported protocols: tcp, udp
43
// @example
44
// ```javascript
45
// const net = require('nuclei/net');
46
// const conn = net.OpenTLS('tcp', 'acme.com:443');
47
// ```
48
func OpenTLS(ctx context.Context, protocol, address string) (*NetConn, error) {
49
config := &tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS10}
50
host, _, _ := net.SplitHostPort(address)
51
if host != "" {
52
c := config.Clone()
53
c.ServerName = host
54
config = c
55
}
56
executionId := ctx.Value("executionId").(string)
57
dialer := protocolstate.GetDialersWithId(executionId)
58
if dialer == nil {
59
return nil, fmt.Errorf("dialers not initialized for %s", executionId)
60
}
61
62
conn, err := dialer.Fastdialer.DialTLSWithConfig(ctx, protocol, address, config)
63
if err != nil {
64
return nil, err
65
}
66
return &NetConn{conn: conn, timeout: defaultTimeout}, nil
67
}
68
69
type (
70
// NetConn is a connection to a remote host.
71
// this is returned/create by Open and OpenTLS functions.
72
// @example
73
// ```javascript
74
// const net = require('nuclei/net');
75
// const conn = net.Open('tcp', 'acme.com:80');
76
// ```
77
NetConn struct {
78
conn net.Conn
79
timeout time.Duration
80
}
81
)
82
83
// Close closes the connection.
84
// @example
85
// ```javascript
86
// const net = require('nuclei/net');
87
// const conn = net.Open('tcp', 'acme.com:80');
88
// conn.Close();
89
// ```
90
func (c *NetConn) Close() error {
91
err := c.conn.Close()
92
return err
93
}
94
95
// SetTimeout sets read/write timeout for the connection (in seconds).
96
// @example
97
// ```javascript
98
// const net = require('nuclei/net');
99
// const conn = net.Open('tcp', 'acme.com:80');
100
// conn.SetTimeout(10);
101
// ```
102
func (c *NetConn) SetTimeout(value int) {
103
c.timeout = time.Duration(value) * time.Second
104
}
105
106
// setDeadLine sets read/write deadline for the connection (in seconds).
107
// this is intended to be called before every read/write operation.
108
func (c *NetConn) setDeadLine() {
109
if c.timeout == 0 {
110
c.timeout = 5 * time.Second
111
}
112
_ = c.conn.SetDeadline(time.Now().Add(c.timeout))
113
}
114
115
// unsetDeadLine unsets read/write deadline for the connection.
116
func (c *NetConn) unsetDeadLine() {
117
_ = c.conn.SetDeadline(time.Time{})
118
}
119
120
// SendArray sends array data to connection
121
// @example
122
// ```javascript
123
// const net = require('nuclei/net');
124
// const conn = net.Open('tcp', 'acme.com:80');
125
// conn.SendArray(['hello', 'world']);
126
// ```
127
func (c *NetConn) SendArray(data []interface{}) error {
128
c.setDeadLine()
129
defer c.unsetDeadLine()
130
input := types.ToByteSlice(data)
131
length, err := c.conn.Write(input)
132
if err != nil {
133
return err
134
}
135
if length < len(input) {
136
return fmt.Errorf("failed to write all bytes (%d bytes written, %d bytes expected)", length, len(input))
137
}
138
return nil
139
}
140
141
// SendHex sends hex data to connection
142
// @example
143
// ```javascript
144
// const net = require('nuclei/net');
145
// const conn = net.Open('tcp', 'acme.com:80');
146
// conn.SendHex('68656c6c6f');
147
// ```
148
func (c *NetConn) SendHex(data string) error {
149
c.setDeadLine()
150
defer c.unsetDeadLine()
151
bin, err := hex.DecodeString(data)
152
if err != nil {
153
return err
154
}
155
length, err := c.conn.Write(bin)
156
if err != nil {
157
return err
158
}
159
if length < len(bin) {
160
return fmt.Errorf("failed to write all bytes (%d bytes written, %d bytes expected)", length, len(bin))
161
}
162
return nil
163
}
164
165
// Send sends data to the connection with a timeout.
166
// @example
167
// ```javascript
168
// const net = require('nuclei/net');
169
// const conn = net.Open('tcp', 'acme.com:80');
170
// conn.Send('hello');
171
// ```
172
func (c *NetConn) Send(data string) error {
173
c.setDeadLine()
174
defer c.unsetDeadLine()
175
bin := []byte(data)
176
length, err := c.conn.Write(bin)
177
if err != nil {
178
return err
179
}
180
if length < len(bin) {
181
return fmt.Errorf("failed to write all bytes (%d bytes written, %d bytes expected)", length, len(data))
182
}
183
return nil
184
}
185
186
// RecvFull receives data from the connection with a timeout.
187
// If N is 0, it will read all data sent by the server with 8MB limit.
188
// it tries to read until N bytes or timeout is reached.
189
// @example
190
// ```javascript
191
// const net = require('nuclei/net');
192
// const conn = net.Open('tcp', 'acme.com:80');
193
// const data = conn.RecvFull(1024);
194
// ```
195
func (c *NetConn) RecvFull(N int) ([]byte, error) {
196
c.setDeadLine()
197
defer c.unsetDeadLine()
198
if N == 0 {
199
// in utils we use -1 to indicate read all rather than 0
200
N = -1
201
}
202
bin, err := reader.ConnReadNWithTimeout(c.conn, int64(N), c.timeout)
203
if err != nil {
204
return []byte{}, errkit.Wrapf(err, "failed to read %d bytes", N)
205
}
206
return bin, nil
207
}
208
209
// Recv is similar to RecvFull but does not guarantee full read instead
210
// it creates a buffer of N bytes and returns whatever is returned by the connection
211
// for reading headers or initial bytes from the server this is usually used.
212
// for reading a fixed number of already known bytes (ex: body based on content-length) use RecvFull.
213
// @example
214
// ```javascript
215
// const net = require('nuclei/net');
216
// const conn = net.Open('tcp', 'acme.com:80');
217
// const data = conn.Recv(1024);
218
// log(`Received ${data.length} bytes from the server`)
219
// ```
220
func (c *NetConn) Recv(N int) ([]byte, error) {
221
c.setDeadLine()
222
defer c.unsetDeadLine()
223
if N == 0 {
224
N = 4096
225
}
226
b := make([]byte, N)
227
n, err := c.conn.Read(b)
228
if err != nil {
229
return []byte{}, errkit.Wrapf(err, "failed to read %d bytes", N)
230
}
231
return b[:n], nil
232
}
233
234
// RecvFullString receives data from the connection with a timeout
235
// output is returned as a string.
236
// If N is 0, it will read all data sent by the server with 8MB limit.
237
// @example
238
// ```javascript
239
// const net = require('nuclei/net');
240
// const conn = net.Open('tcp', 'acme.com:80');
241
// const data = conn.RecvFullString(1024);
242
// ```
243
func (c *NetConn) RecvFullString(N int) (string, error) {
244
bin, err := c.RecvFull(N)
245
if err != nil {
246
return "", err
247
}
248
return string(bin), nil
249
}
250
251
// RecvString is similar to RecvFullString but does not guarantee full read, instead
252
// it creates a buffer of N bytes and returns whatever is returned by the connection
253
// for reading headers or initial bytes from the server this is usually used.
254
// for reading a fixed number of already known bytes (ex: body based on content-length) use RecvFullString.
255
// @example
256
// ```javascript
257
// const net = require('nuclei/net');
258
// const conn = net.Open('tcp', 'acme.com:80');
259
// const data = conn.RecvString(1024);
260
// ```
261
func (c *NetConn) RecvString(N int) (string, error) {
262
bin, err := c.Recv(N)
263
if err != nil {
264
return "", err
265
}
266
return string(bin), nil
267
}
268
269
// RecvFullHex receives data from the connection with a timeout
270
// in hex format.
271
// If N is 0,it will read all data sent by the server with 8MB limit.
272
// until N bytes or timeout is reached.
273
// @example
274
// ```javascript
275
// const net = require('nuclei/net');
276
// const conn = net.Open('tcp', 'acme.com:80');
277
// const data = conn.RecvFullHex(1024);
278
// ```
279
func (c *NetConn) RecvFullHex(N int) (string, error) {
280
bin, err := c.RecvFull(N)
281
if err != nil {
282
return "", err
283
}
284
return hex.Dump(bin), nil
285
}
286
287
// RecvHex is similar to RecvFullHex but does not guarantee full read instead
288
// it creates a buffer of N bytes and returns whatever is returned by the connection
289
// for reading headers or initial bytes from the server this is usually used.
290
// for reading a fixed number of already known bytes (ex: body based on content-length) use RecvFull.
291
// @example
292
// ```javascript
293
// const net = require('nuclei/net');
294
// const conn = net.Open('tcp', 'acme.com:80');
295
// const data = conn.RecvHex(1024);
296
// ```
297
func (c *NetConn) RecvHex(N int) (string, error) {
298
bin, err := c.Recv(N)
299
if err != nil {
300
return "", err
301
}
302
return hex.Dump(bin), nil
303
}
304
305