日期:2014-05-16 浏览次数:20497 次
function toBase64(str){
return new Buffer(str).toString('base64');
}
function httpRequest(host, port){
var opts = {
host: 'your-proxy.your-subdomain.jit.su',
port: 80,
agent: false,
// 这里需要转义以避开gfw的url检测.
path: '/' + querystring.escape(toBase64(JSON.stringify({
host: host,
port: port
}))),
method: 'POST'
};
return http.request(opts);
}
/**
* 建立代理连接.
* @param socket socks5端口连接到的socket
* @param chunk socks5代理请求的包, 用于socks5协议响应.
* @param host 请求连接的host
* @param port 请求连接的port
*/
function proxy(socket, chunk, host, port){
var httpReq = httpRequest(host, port);
// 维持长连接.
httpReq.setSocketKeepAlive(1024);
// 发一个无用的字符使request发出第一个数据包, 以便服务器接受并建立连接.
httpReq.write('\n');
httpReq.on('response', function (httpRes){
// socks5协议部分,
var resp = new Buffer(chunk.length);
chunk.copy(resp);
// rewrite response header
resp[0] = SOCKS_VERSION;
resp[1] = 0x00;
resp[2] = 0x00;
// 告诉socks5客户端连接建议完毕.
socket.write(resp);
// 忽略那个无用的"\n".
httpRes.once('data', function (chunk){
if (chunk.toString() === '\n') {
httpRes.pipe(socket);
console.log('TUNNEL SUCCESS');
} else {
console.log('TUNNEL FAIL');
}
});
httpRes.on('close', function (){
socket.end();
});
});
socket.setKeepAlive(1024);
socket.pipe(httpReq);
socket.on('close', function (){
httpReq.abort();
});
}var http = require('http');
var net = require('net');
var querystring = require('querystring');
function fromBase64(str){
return new Buffer(str, 'base64').toString();
}
http.createServer(function (req, res){
var url = req.url;
// 这里解码path为host和port
var params = JSON.parse(fromBase64(querystring.unescape(url.slice(1))));
var host = params.host;
var port = params.port;
console.log('CONNECT: ' + host + ':' + port);
var buff = [];
function addChunk(chunk){
buff.push(chunk);
}
// 忽略第一个用来强制http发包的'\n'
req.once('data', function (chunk){
if (chunk.toString() === '\n') {
req.on('data', addChunk);
}
});
var socket = net.connect(port, host, function (){
req.removeListener('data', addChunk);
res.writeHead(200);
// 貌似nodejs为了优化, writeHead并不会立即响应给客户端.
// 所以这里需要额外发一个没用的字符.
res.write('\n');
for (var i=0; i<buff.length; i++) {
socket.write(buff[i]);
}
req.pipe(socket);
socket.pipe(res);
console.log('CONNECTED: ' + host + ':' + port);
});
}).listen(80);