#!/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 = '用户名';
var lum_zones = {gen: '密码', gen2: '密码'};
var ports = [
{from: 12000, count: 10, opt: {zone: 'gen'}},
{from: 12100, count: 10, 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();
proxy.js
pm2 start proxy.js




