-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
111 lines (82 loc) · 3.13 KB
/
index.js
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
var util = require('util');
var net = require('net'),
lookup = require('./lookup').lookup,
tunnel = require('./tunnel').open,
trans = require('./transparent').open,
TUNNEL_HOST = '127.0.0.1',
HEADERS = "Proxy-agent: protonet-proxy/0.0.1\r\n";
process.on('uncaughtException',function(error){
// process error
util.log(error);
});
var server = net.createServer(function (socket) {
var buffer = '',
http_version = 'HTTP/1.0';
send_response = function(numeric, text, close) {
util.log('Sending HTTP ' + numeric + ' ' + text + ' response');
try {
socket.write(http_version + ' ' + numeric + ' ' + text + "\r\n");
socket.write(HEADERS + "\r\n");
if (close) {
util.log('Disconnecting client');
socket.end();
}
} catch(ex) {
util.log('Error occurred while sending HTTP response');
}
}
// define it here so it can be unassigned
var handler = function(data) {
buffer += data.toString();
if (buffer.indexOf("\r\n\r\n") > 0) {
socket.removeListener('data', handler);
var captures = buffer.match(/^CONNECT ([^:]+):([0-9]+) (HTTP\/1\.[01])/);
if (!captures || captures.length < 2) {
util.log('Received invalid HTTP request');
return send_response(400, 'Bad Request', true);
}
var tmp = captures[1].split('~');
var target = tmp[0];
var old_style = tmp.length > 1;
util.log('Client requested a tunnel to ' + target + ' port ' + captures[2]);
if (old_style) util.log('Using the old HTTP CONNECT method');
http_version = captures[3];
lookup(target, function(port) {
util.log('Remote port is ' + port);
if (!port) { return send_response(401, 'Unknown Proxy Target', true); }
var method = old_style ? tunnel : trans;
var remote = method(TUNNEL_HOST, port, 'localhost:' + captures[2], function(data) {
if (data == null) { return send_response(500, 'Remote node refused tunnel or does not respond', true); }
util.log('Connected to upstream service, initiating tunnel pumping');
var closeBoth = function() {
util.log('Disconnecting tunnel');
try { socket.end(); } catch(ex) {}
try { remote.end(); } catch(ex) {}
}
var tunnel = function(other) {
return function(data) {
try { other.write(data); }
catch(ex) {
util.log('Error during socket write');
closeBoth();
}
}
};
socket.addListener('data', tunnel(remote));
remote.addListener('data', tunnel(socket));
socket.addListener('close', closeBoth);
remote.addListener('close', closeBoth);
socket.addListener('error', closeBoth);
socket.addListener('error', closeBoth);
send_response(200, 'Connection Established');
if (data.length > 0) {
try { socket.write(data); } catch(ex) {}
}
});
});
}
}
socket.addListener('data', handler);
});
server.listen(8022);
util.log('Proxy server running at http://0.0.0.0:8022/');