forked from hola/lum_local_proxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lum_local.js
152 lines (140 loc) · 4.53 KB
/
lum_local.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
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
144
145
146
147
148
149
150
151
152
#!/usr/bin/env node
// LICENSE_CODE ZON
'use strict'; /*jslint node:true,esnext:true*/
var http = require('http');
var url = require('url');
var api_port = 11000;
var lum_customer = 'customer';
var lum_zones = {gen: 'password1', gen2: 'password2'};
var ports = [
{from: 12000, count: 3, opt: {zone: 'gen'}},
{from: 12010, count: 3, opt: {zone: 'gen2', country: 'ca'}},
];
var servers = [];
function start_servers(){
ports.forEach(function(port_range){
for (var i=0; i<(port_range.count||1); i++)
servers.push(start_server(port_range.from+i, port_range.opt));
});
servers.push(start_api(api_port));
}
function start_server(port, opt){
var server = http.createServer(run_proxy);
server.on('connect', run_proxy);
server.lum_port = port;
server.lum_opt = {session: port};
server.lum_agent = new http.Agent({keepAlive: true, keepAliveMsecs: 5000});
copy_opt(server.lum_opt, opt);
server.listen(port);
console.log(port+': '+JSON.stringify(server.lum_opt));
return server;
}
function start_api(port){
var server = http.createServer(api);
server.listen(port);
return server;
}
function lum_auth(opt){
var arr = ['lum-customer', lum_customer];
var username = arr.concat(opt_as_array(opt)).join('-');
return new Buffer(username+':'+lum_zones[opt.zone]).toString('base64');
}
function lum_superproxy(opt){
return 'servercountry-'+(opt.superproxy||'us')+'.zproxy.luminati.io'; }
const CRLF = '\r\n';
function write_http_reply(stream, res){
if (stream instanceof http.ServerResponse)
{
return stream.writeHead(res.statusCode, res.statusMessage,
res.headers);
}
var str = 'HTTP/1.1 '+res.statusCode+' '+res.statusMessage+CRLF;
for (var field in res.headers)
str += field+': '+res.headers[field]+CRLF;
str += CRLF;
stream.write(str);
}
function run_proxy(client_req, client_res, head){
var socket = client_req.socket;
var server = socket.server;
var lum_opt = server.lum_opt;
var log = server.lum_port+' '+new Date().toISOString()+' '
+client_req.socket.remoteAddress+' '+client_req.method+' '
+client_req.url+' ';
client_req.headers['proxy-authorization'] = 'Basic '+lum_auth(lum_opt);
var lum_req = {
protocol: 'http:',
host: lum_superproxy(lum_opt),
port: 22225,
method: client_req.method,
path: client_req.url,
headers: client_req.headers,
agent: server.lum_agent,
};
var proxy = http.request(lum_req);
if (client_req.method=='CONNECT')
proxy.end();
else
client_req.pipe(proxy);
proxy.on('response', function(proxy_res){
console.log(log+proxy_res.statusCode);
write_http_reply(client_res, proxy_res);
proxy_res.pipe(client_res);
});
proxy.on('connect', function(proxy_res, proxy_socket, proxy_head){
console.log(log+proxy_res.statusCode);
write_http_reply(client_res, proxy_res);
if (proxy_res.statusCode!=200)
return client_res.end();
proxy_socket.write(head);
client_res.write(proxy_head);
proxy_socket.pipe(client_res).pipe(proxy_socket);
});
proxy.on('error', function(error){
if (!client_res.ended)
{
write_http_reply(client_res, {statusCode: '502',
statusMessage: 'Bad gateway', headers: {Connection: 'close'}});
}
client_res.end();
console.log(log+'502');
});
}
function api_result(res, code, message, body){
res.writeHead(code, message);
res.end(body);
}
// API: /get?port=NN or /set?port=NN&country=ca&...
function api(req, res){
var request = url.parse(req.url, true);
var query = request.query;
if (!query.port)
return api_result(res, '400', 'Port not specified');
var server = servers.find(function(s){ return s.lum_port==query.port; });
if (!server)
return api_result(res, '400', 'Port not found');
delete query.port;
switch(request.pathname)
{
case '/get': break;
case '/set': copy_opt(server.lum_opt, query); break;
default: return api_result(res, '400', 'Bad API endpoint');
}
return api_result(res, '200', 'OK', JSON.stringify(server.lum_opt));
}
function copy_opt(to, from){
for (var key in from)
to[key] = from[key];
}
function opt_as_array(obj){
var arr = [];
for (var key in obj){
if (key=='superproxy')
continue;
arr.push(key);
arr.push(obj[key]);
}
return arr;
}
console.log('Starting servers:');
start_servers();