Skip to content

Instantly share code, notes, and snippets.

@normanzb
Created June 12, 2010 16:25
Show Gist options
  • Save normanzb/435868 to your computer and use it in GitHub Desktop.
Save normanzb/435868 to your computer and use it in GitHub Desktop.
/*
** Modification by Norman Xu
** Based on :
** Peteris Krumins (peter@catonmat.net)
** http://www.catonmat.net -- good coders code, great reuse
**
** A simple proxy server written in node.js.
**
*/
var http = require('http');
var sys = require('sys');
var fs = require('fs');
var Buffer = require('buffer').Buffer;
var blacklist = [];
var iplist = [];
var cachedMode = false;
const FILE_IPLIST = "./iplist";
const FILE_BLACKLIST = "./blacklist";
function watch_blacklist(){
fs.watchFile(FILE_BLACKLIST, function(c,p) { update_blacklist(); });
}
function watch_iplist(){
fs.watchFile(FILE_IPLIST, function(c,p) { update_iplist(); });
}
watch_blacklist();
watch_iplist();
function update_blacklist() {
fs.stat(FILE_BLACKLIST, function(err, stats) {
if (!err) {
sys.log("Updating blacklist.");
blacklist = fs.readFileSync(FILE_BLACKLIST).toString().split('\n')
.filter(function(rx) { return rx.length })
.map(function(rx) { return RegExp(rx) });
}
});
}
function update_iplist() {
fs.stat(FILE_IPLIST, function(err, stats) {
if (!err) {
// stop watch since we r going to access it.
fs.unwatchFile(FILE_IPLIST);
sys.log("Updating iplist.");
iplist = fs.readFileSync(FILE_IPLIST).toString().split('\n')
.filter(function(rx) { return rx.length });
watch_iplist();
}
});
}
function ip_allowed(ip) {
for (i in iplist) {
if (iplist[i] == ip) {
return true;
}
}
return false;
}
function host_allowed(host) {
for (i in blacklist) {
if (blacklist[i].test(host)) {
return false;
}
}
return true;
}
function deny(response, msg) {
response.writeHead(401);
response.write(msg);
response.end();
}
http.createServer(function(request, response) {
try{
var ip = request.connection.remoteAddress;
var host = "";
var port = 80;
if (!ip_allowed(ip)) {
msg = "IP " + ip + " is not allowed to use this proxy";
deny(response, msg);
sys.log(msg);
return;
}
if (!host_allowed(request.url)) {
msg = "Host " + request.url + " has been denied by proxy configuration";
deny(response, msg);
sys.log(msg);
return;
}
host = request.headers['host'];
if (host.indexOf(":") != -1){
tmp = host.split(":");
host = tmp[0];
port = tmp[1] * 1;
}
sys.log(ip + ": " + request.method + " " + host + ":" + port + " " + request.url );
var proxy = http.createClient(port, host)
var proxy_request = proxy.request(request.method, request.url, request.headers);
proxy_request.addListener('response', function(proxy_response) {
try{
var chunks = [];
proxy_response.setEncoding("binary");
proxy_response.addListener('data', function(chunk) {
try{
if (cachedMode){
chunks.push(chunk);
}
else{
response.write(chunk, "binary");
}
}
catch(ex){
sys.log("Error: " + ip +": " + ex.message);
}
});
proxy_response.addListener('end', function() {
try{
if (cachedMode){
var len = chunks.length;
var maxlen = 0;
while(len--){
maxlen += chunks[len].length;
}
if (maxlen <=0){
response.end();
}
var res = new Buffer(maxlen);
len = 0;
var currentlen = 0;
while(len < chunks.length){
chunks[len].copy(res, currentlen, 0, chunks[len].length);
currentlen += chunks[len].length;
len++;
}
response.write(res, "binary");
}
response.end();
}
catch(ex){
sys.log("Error: " + ip +": " + ex.message);
}
});
response.writeHead(proxy_response.statusCode, proxy_response.headers);
}
catch(ex){
sys.log("Error: " + ex.message);
};
});
request.addListener('data', function(chunk) {
try{
proxy_request.write(chunk);
}
catch(ex){
sys.log("Error: " + ip +": " + ex.message);
}
});
request.addListener('end', function() {
try{
proxy_request.end();
}
catch(ex){
sys.log("Error: " + ip +": " + ex.message);
}
});
}
catch(ex){
sys.log("Error: " + ex.message);
}
}).listen(3389);
update_blacklist();
update_iplist();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment