From e0aebaf9ff5aff2d459b428cfdc3af148d767c86 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Mon, 21 Oct 2013 23:10:44 +0800 Subject: [PATCH 01/43] export socks.js for require --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index a1457e2..7c81919 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ , "version": "0.1.0" , "description": "A simple SOCKS implementation and demo proxy" , "author": "Gert Van Gool " + , "main": "socks.js" , "dependencies": { } } From d1f615507fa75cacc1e0489f2ec032165fd2beca Mon Sep 17 00:00:00 2001 From: tom zhou Date: Tue, 22 Oct 2013 00:35:44 +0800 Subject: [PATCH 02/43] fixed extract server port --- socks.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/socks.js b/socks.js index 3daeb5e..185e6f2 100644 --- a/socks.js +++ b/socks.js @@ -1,8 +1,6 @@ var net = require('net'), util = require('util'), - log = function(args) { - //console.log(args); - }, + log = function(){},///console.log, info = console.info, errorLog = console.error, clients = [], @@ -70,10 +68,10 @@ function createSocksServer(cb) { var socksServer = net.createServer(); socksServer.on('listening', function() { var address = socksServer.address(); - info('LISTENING %s:%s', address.address, address.port); + info('LISTENING %s:%d', address.address, address.port); }); socksServer.on('connection', function(socket) { - info('CONNECTED %s:%s', socket.remoteAddress, socket.remotePort); + info('CONNECTED %s:%d', socket.remoteAddress, socket.remotePort); initSocksConnection.bind(socket)(cb); }); return socksServer; @@ -153,10 +151,10 @@ function handleRequest(chunk) { return; } */ address = Address.read(chunk, 3); - offset = 3 + Address.sizeOf(chunk, 3) + 2; + offset = 4 + Address.sizeOf(chunk, 3); port = chunk.readUInt16BE(offset); - log('Request: type: %d -- to: %s:%s', chunk[1], address, port); + log('Request: type: %d -- to: %s:%d', chunk[1], address, port); if (cmd == REQUEST_CMD.CONNECT) { this.request = chunk; @@ -177,8 +175,7 @@ function proxyReady() { resp[1] = 0x00; resp[2] = 0x00; this.write(resp); - log('Connected to: %s:%d', resp.toString('utf8', 4, resp.length - 2), resp.readUInt16BE(resp.length - 2)); - + log('Connected to: %s:%d', Address.read(resp, 3), resp.readUInt16BE(resp.length - 2)); } From b42e8b458ee3acbaccb23f748758f0082aca26f7 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Tue, 22 Oct 2013 08:38:04 +0800 Subject: [PATCH 03/43] rename it as socks5 --- package.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c81919..dfe7176 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,18 @@ { - "name": "node-socks" + "name": "socks5" , "version": "0.1.0" , "description": "A simple SOCKS implementation and demo proxy" , "author": "Gert Van Gool " + , "repository": { + "type": "git", + "url": "git://github.com/sequoiar/node-socks.git" + } + , "keywords": [ + "socks", + "socks5", + "proxy", + "http" + ] , "main": "socks.js" , "dependencies": { } From 2293ecd9ed84af5ff270b5c79758038f61dd564f Mon Sep 17 00:00:00 2001 From: tom zhou Date: Thu, 24 Oct 2013 09:38:58 +0800 Subject: [PATCH 04/43] support socks4,socks4a --- AUTHORS | 1 + package.json | 11 +++- socks.js | 157 +++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 154 insertions(+), 15 deletions(-) diff --git a/AUTHORS b/AUTHORS index 89d6bec..a867227 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ Gert Van Gool John Cant +Tom Zhou diff --git a/package.json b/package.json index dfe7176..ab7e88a 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,11 @@ { "name": "socks5" - , "version": "0.1.0" - , "description": "A simple SOCKS implementation and demo proxy" - , "author": "Gert Van Gool " + , "version": "0.2.0" + , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" + , "author": [ + "Gert Van Gool ", + "Tom Zhou " + ] , "repository": { "type": "git", "url": "git://github.com/sequoiar/node-socks.git" @@ -10,6 +13,8 @@ , "keywords": [ "socks", "socks5", + "socks4", + "socks4a", "proxy", "http" ] diff --git a/socks.js b/socks.js index 185e6f2..9f90f75 100644 --- a/socks.js +++ b/socks.js @@ -1,10 +1,13 @@ var net = require('net'), util = require('util'), + DNS = require('dns'), log = function(){},///console.log, + ///log = console.log, info = console.info, errorLog = console.error, clients = [], - SOCKS_VERSION = 5, + SOCKS_VERSION5 = 5, + SOCKS_VERSION4 = 4, /* * Authentication methods ************************ @@ -76,7 +79,7 @@ function createSocksServer(cb) { }); return socksServer; } -// + // socket is available as this function initSocksConnection(on_accept) { // keep log of connected clients @@ -102,11 +105,28 @@ function initSocksConnection(on_accept) { function handshake(chunk) { this.removeListener('data', this.handshake); + // SOCKS Version 4/5 is the only support version + if (chunk[0] == SOCKS_VERSION5) { + this.socksVersion = SOCKS_VERSION5; + this.handshake5 = handshake5.bind(this); + this.handshake5(chunk); + } else if (chunk[0] == SOCKS_VERSION4) { + this.socksVersion = SOCKS_VERSION4; + this.handshake4 = handshake4.bind(this); + this.handshake4(chunk); + } else { + errorLog('handshake: wrong socks version: %d', chunk[0]); + this.end(); + } +} + +// SOCKS5 +function handshake5(chunk) { var method_count = 0; // SOCKS Version 5 is the only support version - if (chunk[0] != SOCKS_VERSION) { - errorLog('handshake: wrong socks version: %d', chunk[0]); + if (chunk[0] != SOCKS_VERSION5) { + errorLog('socks5 handshake: wrong socks version: %d', chunk[0]); this.end(); } // Number of authentication methods @@ -134,6 +154,94 @@ function handshake(chunk) { } } +// SOCKS4/4a +function handshake4(chunk) { + var cmd=chunk[1], + address, + port, + uid; + + // Wrong version! + if (chunk[0] !== SOCKS_VERSION4) { + this.end('%d%d', 0x00, 0x5b); + errorLog('socks4 handleRequest: wrong socks version: %d', chunk[0]); + return; + } + port = chunk.readUInt16BE(2); + + // SOCKS4a + if ((chunk[4] == 0 && chunk[5] == chunk[6] == 0) && (chunk[7] != 0)) { + var it = 0; + + uid = ''; + for (it=0; it < 1024; it++) { + uid += chunk[8+it]; + if (chunk[8+it] == 0x00) + break; + } + address = ''; + if (chunk[8+it] == 0x00) { + for (it++; it < 2048; it++) { + address += chunk[8+it]; + if (chunk[8+it] == 0x00) + break; + } + } + if (chunk[8+it] == 0x00) { + // DNS lookup + DNS.lookup(address, function(err, ip, family){ + if (err) { + errorLog(err+',socks4a dns lookup failed'); + + this.end('%d%d', 0x00, 0x5b); + return; + } else { + this.socksAddress = ip; + this.socksPort = port; + this.socksUid = uid; + + log('socks4a Request: type: %d -- to: %s:%d:%s', cmd, address, port, uid); + + if (cmd == REQUEST_CMD.CONNECT) { + this.request = chunk; + this.on_accept(this, port, ip, proxyReady4.bind(this)); + } else { + this.end('%d%d', 0x00, 0x5b); + return; + } + } + }); + } else { + this.end('%d%d', 0x00, 0x5b); + return; + } + } else { + // SOCKS4 + address = util.format('%s.%s.%s.%s', chunk[4], chunk[5], chunk[6], chunk[7]); + + uid = ''; + for (it=0; it < 1024; it++) { + uid += chunk[8+it]; + if (chunk[8+it] == 0x00) + break; + } + + this.socksAddress = address; + this.socksPort = port; + this.socksUid = uid; + + log('socks4 Request: type: %d -- to: %s:%d:%s', cmd, address, port, uid); + + if (cmd == REQUEST_CMD.CONNECT) { + this.request = chunk; + this.on_accept(this, port, address, proxyReady4.bind(this)); + } else { + this.end('%d%d', 0x00, 0x5b); + return; + } + } +} + function handleRequest(chunk) { this.removeListener('data', this.handleRequest); var cmd=chunk[1], @@ -141,42 +249,67 @@ function handleRequest(chunk) { port, offset=3; // Wrong version! - if (chunk[0] !== SOCKS_VERSION) { + if (chunk[0] !== SOCKS_VERSION5) { this.end('%d%d', 0x05, 0x01); - errorLog('handleRequest: wrong socks version: %d', chunk[0]); + errorLog('socks5 handleRequest: wrong socks version: %d', chunk[0]); return; } /* else if (chunk[2] == 0x00) { this.end(util.format('%d%d', 0x05, 0x01)); - errorLog('handleRequest: Mangled request. Reserved field is not null: %d', chunk[offset]); + errorLog('socks5 handleRequest: Mangled request. Reserved field is not null: %d', chunk[offset]); return; } */ address = Address.read(chunk, 3); offset = 4 + Address.sizeOf(chunk, 3); port = chunk.readUInt16BE(offset); - log('Request: type: %d -- to: %s:%d', chunk[1], address, port); + log('socks5 Request: type: %d -- to: %s:%d', chunk[1], address, port); if (cmd == REQUEST_CMD.CONNECT) { this.request = chunk; - this.on_accept(this, port, address, proxyReady.bind(this)); + this.on_accept(this, port, address, proxyReady5.bind(this)); } else { this.end('%d%d', 0x05, 0x01); return; } } -function proxyReady() { +function proxyReady5() { log('Indicating to the client that the proxy is ready'); // creating response var resp = new Buffer(this.request.length); this.request.copy(resp); // rewrite response header - resp[0] = SOCKS_VERSION; + resp[0] = SOCKS_VERSION5; resp[1] = 0x00; resp[2] = 0x00; + this.write(resp); - log('Connected to: %s:%d', Address.read(resp, 3), resp.readUInt16BE(resp.length - 2)); + + log('socks5 Connected to: %s:%d', Address.read(resp, 3), resp.readUInt16BE(resp.length - 2)); +} +function proxyReady4() { + log('Indicating to the client that the proxy is ready'); + // creating response + var resp = new Buffer(8); + + // write response header + resp[0] = 0x00; + resp[1] = 0x5a; + + // port + resp.writeUInt16BE(this.socksPort, 2); + + // ip + var ips = this.socksAddress.split('.'); + resp.writeUInt8(parseInt(ips[0]), 4); + resp.writeUInt8(parseInt(ips[1]), 5); + resp.writeUInt8(parseInt(ips[2]), 6); + resp.writeUInt8(parseInt(ips[3]), 7); + + this.write(resp); + + log('socks4 Connected to: %s:%d:%s', this.socksAddress, this.socksPort, this.socksUid); } module.exports = { From ae185f77b6be5b2953e76efd9422c80542ed2cb3 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Thu, 24 Oct 2013 13:43:59 +0800 Subject: [PATCH 05/43] code cleanup --- socks.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/socks.js b/socks.js index 9f90f75..1df0972 100644 --- a/socks.js +++ b/socks.js @@ -99,12 +99,10 @@ function initSocksConnection(on_accept) { // do a handshake this.handshake = handshake.bind(this); this.on_accept = on_accept; // No bind. We want 'this' to be the server, like it would be for net.createServer - this.on('data', this.handshake); + this.once('data', this.handshake); } function handshake(chunk) { - this.removeListener('data', this.handshake); - // SOCKS Version 4/5 is the only support version if (chunk[0] == SOCKS_VERSION5) { this.socksVersion = SOCKS_VERSION5; @@ -144,7 +142,7 @@ function handshake5(chunk) { if (this.auth_methods.indexOf(AUTHENTICATION.NOAUTH) > -1) { log('Handing off to handleRequest'); this.handleRequest = handleRequest.bind(this); - this.on('data', this.handleRequest); + this.once('data', this.handleRequest); resp[1] = AUTHENTICATION.NOAUTH; this.write(resp); } else { @@ -243,7 +241,6 @@ function handshake4(chunk) { } function handleRequest(chunk) { - this.removeListener('data', this.handleRequest); var cmd=chunk[1], address, port, From 9a1902b1b36bac782963ae076a1c6f2e8d69ce7a Mon Sep 17 00:00:00 2001 From: tom zhou Date: Sat, 9 Nov 2013 16:43:02 +0800 Subject: [PATCH 06/43] code cleanup --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab7e88a..fabfbb2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", - "Tom Zhou " + "Tom Zhou " ] , "repository": { "type": "git", From d144bbec3cee86c9f322cd47d7841001a12a2823 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Fri, 22 Nov 2013 09:09:32 +0800 Subject: [PATCH 07/43] fixed sock write --- package.json | 2 +- socks | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index fabfbb2..d7087bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.0" + , "version": "0.2.1" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", diff --git a/socks b/socks index 9c46f3a..adac82a 100755 --- a/socks +++ b/socks @@ -17,7 +17,16 @@ var HOST='127.0.0.1', proxy.on('data', function(d) { try { console.log('receiving ' + d.length + ' bytes from proxy'); - socket.write(d); + if (!socket.write(d)) { + proxy.pause(); + + socket.on('drain', function(){ + proxy.resume(); + }); + setTimeout(function(){ + proxy.resume(); + }, 100); + } } catch(err) { } }); @@ -25,7 +34,16 @@ var HOST='127.0.0.1', // If the application tries to send data before the proxy is ready, then that is it's own problem. try { console.log('sending ' + d.length + ' bytes to proxy'); - proxy.write(d); + if (!proxy.write(d)) { + socket.pause(); + + proxy.on('drain', function(){ + socket.resume(); + }); + setTimeout(function(){ + socket.resume(); + }, 100); + } } catch(err) { } }); From a6cfc654577b674822a40e20b09a904d3015a20b Mon Sep 17 00:00:00 2001 From: tom zhou Date: Fri, 22 Nov 2013 09:12:40 +0800 Subject: [PATCH 08/43] fixed sock write --- socks | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/socks b/socks index adac82a..b55148f 100755 --- a/socks +++ b/socks @@ -49,15 +49,22 @@ var HOST='127.0.0.1', }); proxy.on('close', function(had_error) { - socket.end(); - console.error('The proxy closed'); + try { + socket.end(); + console.error('The proxy closed'); + } catch (err) { + } }.bind(this)); + socket.on('close', function(had_error) { - if (this.proxy !== undefined) { - proxy.removeAllListeners('data'); - proxy.end(); + try { + if (this.proxy !== undefined) { + proxy.removeAllListeners('data'); + proxy.end(); + } + console.error('The application closed'); + } catch (err) { } - console.error('The application closed'); }.bind(this)); }); From b5ec23d757fff8537a0ce9cb2a7b8b91208bd16d Mon Sep 17 00:00:00 2001 From: tom zhou Date: Fri, 22 Nov 2013 18:48:31 +0800 Subject: [PATCH 09/43] fixed error check --- socks | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/socks b/socks index b55148f..c97b45d 100755 --- a/socks +++ b/socks @@ -48,6 +48,9 @@ var HOST='127.0.0.1', } }); + proxy.on('error', function(err){ + console.log('Ignore proxy error'); + }); proxy.on('close', function(had_error) { try { socket.end(); @@ -56,6 +59,9 @@ var HOST='127.0.0.1', } }.bind(this)); + socket.on('error', function(err){ + console.log('Ignore socket error'); + }); socket.on('close', function(had_error) { try { if (this.proxy !== undefined) { From e84edb5e1b812d3fec082bfa2aea824c2959020a Mon Sep 17 00:00:00 2001 From: tom zhou Date: Fri, 22 Nov 2013 18:48:51 +0800 Subject: [PATCH 10/43] fixed error check --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7087bb..799fc1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.1" + , "version": "0.2.2" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", From 2362d7365b7a2066ab5fdf49cc34472b95d26b6d Mon Sep 17 00:00:00 2001 From: tom zhou Date: Mon, 2 Dec 2013 08:42:57 +0800 Subject: [PATCH 11/43] check Address.read exception --- package.json | 2 +- socks.js | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 799fc1f..1dc0965 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.2" + , "version": "0.2.3" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", diff --git a/socks.js b/socks.js index 1df0972..e1c2f07 100644 --- a/socks.js +++ b/socks.js @@ -255,9 +255,15 @@ function handleRequest(chunk) { errorLog('socks5 handleRequest: Mangled request. Reserved field is not null: %d', chunk[offset]); return; } */ - address = Address.read(chunk, 3); - offset = 4 + Address.sizeOf(chunk, 3); - port = chunk.readUInt16BE(offset); + try { + address = Address.read(chunk, 3); + offset = 4 + Address.sizeOf(chunk, 3); + port = chunk.readUInt16BE(offset); + } catch (e) { + this.end('%d%d', 0x05, 0x01); + errorLog('socks5 handleRequest: Address.read '+e); + return; + } log('socks5 Request: type: %d -- to: %s:%d', chunk[1], address, port); From 2b772031589ddb4a82a95b72c4ff544d9a0b72d5 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Mon, 2 Dec 2013 08:45:06 +0800 Subject: [PATCH 12/43] ignore exception --- socks.js | 1 - 1 file changed, 1 deletion(-) diff --git a/socks.js b/socks.js index e1c2f07..103f0ba 100644 --- a/socks.js +++ b/socks.js @@ -260,7 +260,6 @@ function handleRequest(chunk) { offset = 4 + Address.sizeOf(chunk, 3); port = chunk.readUInt16BE(offset); } catch (e) { - this.end('%d%d', 0x05, 0x01); errorLog('socks5 handleRequest: Address.read '+e); return; } From 263184dcdbddc1d63b2173d2e2cee8ab4c801f95 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Sun, 6 Jul 2014 11:00:19 +0800 Subject: [PATCH 13/43] disable info log --- socks.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/socks.js b/socks.js index 103f0ba..600cfa5 100644 --- a/socks.js +++ b/socks.js @@ -3,7 +3,8 @@ var net = require('net'), DNS = require('dns'), log = function(){},///console.log, ///log = console.log, - info = console.info, + ///info = console.info, + info = function(){},///console.log, errorLog = console.error, clients = [], SOCKS_VERSION5 = 5, From cac1c57a19bb9b2deaa29a11a77c7a5c7eeed673 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Sun, 6 Jul 2014 11:21:59 +0800 Subject: [PATCH 14/43] fix author list --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index a867227..2576fc0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,3 @@ Gert Van Gool John Cant -Tom Zhou +Tom Zhou From a7bece2b3bf5ce17e09cdc4d415447fc6781f10f Mon Sep 17 00:00:00 2001 From: jjm2473 Date: Fri, 13 Mar 2015 16:17:38 +0800 Subject: [PATCH 15/43] fix wrong Port when using DNS --- README.rst | 2 +- socks => proxy.js | 29 +++++++++++++++++++---------- socks.js | 22 ++++++++++++++++------ 3 files changed, 36 insertions(+), 17 deletions(-) rename socks => proxy.js (71%) mode change 100755 => 100644 diff --git a/README.rst b/README.rst index b3af383..d48c59b 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ A simple SOCKS implementation and demo proxy in `node.js `_. You can run it easily as:: - ./socks + node proxy.js This will create a proxy at ``127.0.0.1`` on port ``8888``. diff --git a/socks b/proxy.js old mode 100755 new mode 100644 similarity index 71% rename from socks rename to proxy.js index c97b45d..10e011c --- a/socks +++ b/proxy.js @@ -1,6 +1,7 @@ -#!/usr/bin/env node + var net = require('net'), - socks = require('./socks.js'); + socks = require('./socks.js'), + info = console.log.bind(console); // Create server // The server accepts SOCKS connections. This particular server acts as a proxy. @@ -11,12 +12,17 @@ var HOST='127.0.0.1', // Implement your own proxy here! Do encryption, tunnelling, whatever! Go flippin' mental! // I plan to tunnel everything including SSH over an HTTP tunnel. For now, though, here is the plain proxy: - console.log('Got through the first part of the SOCKS protocol.') var proxy = net.createConnection(port, address, proxy_ready); - + var localAddress,localPort; + proxy.on('connect', function(){ + info('%s:%d <== %s:%d ==> %s:%d',socket.remoteAddress,socket.remotePort, + proxy.localAddress,proxy.localPort,proxy.remoteAddress,proxy.remotePort); + localAddress=proxy.localAddress; + localPort=proxy.localPort; + }.bind(this)); proxy.on('data', function(d) { try { - console.log('receiving ' + d.length + ' bytes from proxy'); + //console.log('receiving ' + d.length + ' bytes from proxy'); if (!socket.write(d)) { proxy.pause(); @@ -33,7 +39,7 @@ var HOST='127.0.0.1', socket.on('data', function(d) { // If the application tries to send data before the proxy is ready, then that is it's own problem. try { - console.log('sending ' + d.length + ' bytes to proxy'); + //console.log('sending ' + d.length + ' bytes to proxy'); if (!proxy.write(d)) { socket.pause(); @@ -49,18 +55,21 @@ var HOST='127.0.0.1', }); proxy.on('error', function(err){ - console.log('Ignore proxy error'); + //console.log('Ignore proxy error'); }); proxy.on('close', function(had_error) { try { + if(localAddress && localPort) + console.log('The proxy %s:%d closed', localAddress, localPort); + else + console.error('Connect to %s:%d failed', address, port); socket.end(); - console.error('The proxy closed'); } catch (err) { } }.bind(this)); socket.on('error', function(err){ - console.log('Ignore socket error'); + //console.log('Ignore socket error'); }); socket.on('close', function(had_error) { try { @@ -68,7 +77,7 @@ var HOST='127.0.0.1', proxy.removeAllListeners('data'); proxy.end(); } - console.error('The application closed'); + //console.error('The socket %s:%d closed',socket.remoteAddress,socket.remotePort); } catch (err) { } }.bind(this)); diff --git a/socks.js b/socks.js index 600cfa5..2b11d5d 100644 --- a/socks.js +++ b/socks.js @@ -2,10 +2,10 @@ var net = require('net'), util = require('util'), DNS = require('dns'), log = function(){},///console.log, - ///log = console.log, - ///info = console.info, + //log = console.log.bind(console), + //info = console.info.bind(console), info = function(){},///console.log, - errorLog = console.error, + errorLog = console.error.bind(console), clients = [], SOCKS_VERSION5 = 5, SOCKS_VERSION4 = 4, @@ -66,13 +66,24 @@ var net = require('net'), return 16; } } + }, + Port = { + read: function (buffer, offset) { + if (buffer[offset] == ATYP.IP_V4) { + return buffer.readUInt16BE(8); + } else if (buffer[offset] == ATYP.DNS) { + return buffer.readUInt16BE(5+buffer[offset+1]); + } else if (buffer[offset] == ATYP.IP_V6) { + return buffer.readUInt16BE(20); + } + }, }; function createSocksServer(cb) { var socksServer = net.createServer(); socksServer.on('listening', function() { var address = socksServer.address(); - info('LISTENING %s:%d', address.address, address.port); + console.log('LISTENING %s:%d', address.address, address.port); }); socksServer.on('connection', function(socket) { info('CONNECTED %s:%d', socket.remoteAddress, socket.remotePort); @@ -258,8 +269,7 @@ function handleRequest(chunk) { } */ try { address = Address.read(chunk, 3); - offset = 4 + Address.sizeOf(chunk, 3); - port = chunk.readUInt16BE(offset); + port = Port.read(chunk, 3); } catch (e) { errorLog('socks5 handleRequest: Address.read '+e); return; From ffbe0c7976e4fa2139591da399aacbb868f0a2f0 Mon Sep 17 00:00:00 2001 From: jjm2473 Date: Fri, 13 Mar 2015 20:11:23 +0800 Subject: [PATCH 16/43] we can binding NIC now. --- proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy.js b/proxy.js index 10e011c..b2b7d9e 100644 --- a/proxy.js +++ b/proxy.js @@ -12,7 +12,7 @@ var HOST='127.0.0.1', // Implement your own proxy here! Do encryption, tunnelling, whatever! Go flippin' mental! // I plan to tunnel everything including SSH over an HTTP tunnel. For now, though, here is the plain proxy: - var proxy = net.createConnection(port, address, proxy_ready); + var proxy = net.createConnection({port:port, host:address,localAddress:process.argv[2]||undefined}, proxy_ready); var localAddress,localPort; proxy.on('connect', function(){ info('%s:%d <== %s:%d ==> %s:%d',socket.remoteAddress,socket.remotePort, From d43e38d22409ea59f896d976cb7146b928e4ff10 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 7 Jun 2015 21:37:19 +0800 Subject: [PATCH 17/43] fixed port read when use dns --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1dc0965..f1370d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.3" + , "version": "0.2.4" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", From 259cb129fc1f6358f826042c34e35a55dbea2f1e Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 11:57:09 +0800 Subject: [PATCH 18/43] Update README.rst --- README.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index d48c59b..8d43634 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ SOCKS implementation in node.js =============================== -A simple SOCKS implementation and demo proxy in `node.js `_. +A simple SOCKS v5/v4/v4a implementation and demo proxy in `node.js `_. You can run it easily as:: @@ -10,3 +10,6 @@ You can run it easily as:: This will create a proxy at ``127.0.0.1`` on port ``8888``. You can use this as a good starting point for writing a proxy or a tunnel! + +### Install +- npm install socks5 From 1215cfe133332f37f97f587f0c3cda14f6eac396 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 11:57:50 +0800 Subject: [PATCH 19/43] Create README.md --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ + From 9ec7361983b3152ebedd674e63ad79b852ca690c Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 11:59:21 +0800 Subject: [PATCH 20/43] Update README.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 8b13789..58fa832 100644 --- a/README.md +++ b/README.md @@ -1 +1,16 @@ +SOCKS implementation in node.js +=============================== + +A simple SOCKS v5/v4/v4a implementation and demo proxy. + +You can run it easily as:: + + node proxy.js + +This will create a proxy at ``127.0.0.1`` on port ``8888``. + +You can use this as a good starting point for writing a proxy or a tunnel! + +### Install +- npm install socks5 From 0ec7dd4898c310ec1724b3833f751d392e4e43c3 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 11:59:45 +0800 Subject: [PATCH 21/43] Delete README.rst --- README.rst | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 README.rst diff --git a/README.rst b/README.rst deleted file mode 100644 index 8d43634..0000000 --- a/README.rst +++ /dev/null @@ -1,15 +0,0 @@ -SOCKS implementation in node.js -=============================== - -A simple SOCKS v5/v4/v4a implementation and demo proxy in `node.js `_. - -You can run it easily as:: - - node proxy.js - -This will create a proxy at ``127.0.0.1`` on port ``8888``. - -You can use this as a good starting point for writing a proxy or a tunnel! - -### Install -- npm install socks5 From c7f1939b1c3c02f459f12bf4883200f0c8489706 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 12:00:51 +0800 Subject: [PATCH 22/43] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 58fa832..7111a8b 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,7 @@ You can use this as a good starting point for writing a proxy or a tunnel! ### Install - npm install socks5 + +### License + +(The MIT License) From 1f51c169ce722520a3514679a81944d40d28aefd Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 12:02:33 +0800 Subject: [PATCH 23/43] fixed README.md add install step --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1370d9..d7087bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.4" + , "version": "0.2.1" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", From 90b29c801793a43c9d512b31c0af58e7cd345a2a Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 12:04:05 +0800 Subject: [PATCH 24/43] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7087bb..d2f3a1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.1" + , "version": "0.2.5" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", From e1d2c470ca83c5ecfc2bde24ffa378ab7a9bf362 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 12:06:58 +0800 Subject: [PATCH 25/43] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2f3a1a..70b8fae 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ] , "repository": { "type": "git", - "url": "git://github.com/sequoiar/node-socks.git" + "url": "git://github.com/sequoiar/socks5.git" } , "keywords": [ "socks", From aa9ea71c649efbe822feb88a248a335817c1ace9 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Sun, 10 Jul 2016 12:07:21 +0800 Subject: [PATCH 26/43] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 70b8fae..d841ec9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.5" + , "version": "0.2.6" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", From 3c4c9aa704c4bcb5ac5c4d31ece7c133c80a59d5 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Wed, 7 Sep 2016 18:57:40 +0800 Subject: [PATCH 27/43] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7111a8b..7e1ef21 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -SOCKS implementation in node.js +SOCKS v4/v4a/v5 server implementation in node.js =============================== -A simple SOCKS v5/v4/v4a implementation and demo proxy. +A simple SOCKS v5/v4/v4a server implementation and demo proxy. You can run it easily as:: From 932c42a5fc25767aeb914940e34de46e08e17302 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Wed, 14 Sep 2016 21:32:52 +0800 Subject: [PATCH 28/43] release v1.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d841ec9..8bb1a36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "0.2.6" + , "version": "1.0.0" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", From 842463d9698bc442ce91162863321578bfa507e9 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 23 Dec 2016 01:50:18 +0000 Subject: [PATCH 29/43] added go.js --- go.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 go.js diff --git a/go.js b/go.js new file mode 100644 index 0000000..ccd7545 --- /dev/null +++ b/go.js @@ -0,0 +1,72 @@ + +var net = require('net'), + socks = require('./socks.js'), + info = console.log.bind(console); + +// Create server +// The server accepts SOCKS connections. This particular server acts as a proxy. +var HOST = process.argv[3] || '127.0.0.1', + PORT = process.argv[2] || '6868', + server = socks.createServer(function(socket, port, address, proxy_ready) { + + // Implement your own proxy here! Do encryption, tunnelling, whatever! Go flippin' mental! + // I plan to tunnel everything including SSH over an HTTP tunnel. For now, though, here is the plain proxy: + + var proxy = net.createConnection({port:port, host:address}, proxy_ready); + var localAddress,localPort; + proxy.on('connect', function(){ + info('%s:%d <== %s:%d ==> %s:%d',socket.remoteAddress,socket.remotePort, + proxy.localAddress,proxy.localPort,proxy.remoteAddress,proxy.remotePort); + localAddress=proxy.localAddress; + localPort=proxy.localPort; + + // send ready res + proxy_ready(); + + proxy.pipe(socket).pipe(proxy); + }.bind(this)); + + proxy.on('error', function(err){ + //console.log('Ignore proxy error'); + }); + proxy.on('close', function(had_error) { + try { + if(localAddress && localPort) + console.log('The proxy %s:%d closed', localAddress, localPort); + else + console.error('Connect to %s:%d failed', address, port); + socket.end(); + } catch (err) { + } + }.bind(this)); + + socket.on('error', function(err){ + //console.log('Ignore socket error'); + }); + socket.on('close', function(had_error) { + try { + if (this.proxy !== undefined) { + proxy.removeAllListeners('data'); + proxy.end(); + } + //console.error('The socket %s:%d closed',socket.remoteAddress,socket.remotePort); + } catch (err) { + } + }.bind(this)); + + }); + +server.on('error', function (e) { + console.error('SERVER ERROR: %j', e); + if (e.code == 'EADDRINUSE') { + console.log('Address in use, retrying in 10 seconds...'); + setTimeout(function () { + console.log('Reconnecting to %s:%s', HOST, PORT); + server.close(); + server.listen(PORT, HOST); + }, 10000); + } +}); +server.listen(PORT, HOST); + +// vim: set filetype=javascript syntax=javascript : From b67dd6edfdc7dafde87a4bc7d690fb48eb23b78d Mon Sep 17 00:00:00 2001 From: root Date: Wed, 11 Jan 2017 14:05:35 +0000 Subject: [PATCH 30/43] fixed socks5 typo --- socks.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/socks.js b/socks.js index 2b11d5d..63ce485 100644 --- a/socks.js +++ b/socks.js @@ -138,6 +138,7 @@ function handshake5(chunk) { if (chunk[0] != SOCKS_VERSION5) { errorLog('socks5 handshake: wrong socks version: %d', chunk[0]); this.end(); + return; } // Number of authentication methods method_count = chunk[1]; @@ -204,7 +205,7 @@ function handshake4(chunk) { errorLog(err+',socks4a dns lookup failed'); this.end('%d%d', 0x00, 0x5b); - return; + return; } else { this.socksAddress = ip; this.socksPort = port; From 3d1488e8f3714098e4e4cbeafb52a70a641941cc Mon Sep 17 00:00:00 2001 From: tom zhou Date: Thu, 12 Jan 2017 01:00:01 +0000 Subject: [PATCH 31/43] support username/password auth --- socks.js | 190 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 123 insertions(+), 67 deletions(-) diff --git a/socks.js b/socks.js index 63ce485..bbc942b 100644 --- a/socks.js +++ b/socks.js @@ -1,3 +1,5 @@ +'use strict' + var net = require('net'), util = require('util'), DNS = require('dns'), @@ -6,9 +8,10 @@ var net = require('net'), //info = console.info.bind(console), info = function(){},///console.log, errorLog = console.error.bind(console), - clients = [], + ///clients = [], SOCKS_VERSION5 = 5, SOCKS_VERSION4 = 4, + USERPASS, /* * Authentication methods ************************ @@ -79,7 +82,10 @@ var net = require('net'), }, }; -function createSocksServer(cb) { +function createSocksServer(cb, userpass) { + // record userpass + USERPASS = userpass; + var socksServer = net.createServer(); socksServer.on('listening', function() { var address = socksServer.address(); @@ -94,6 +100,7 @@ function createSocksServer(cb) { // socket is available as this function initSocksConnection(on_accept) { + /* // keep log of connected clients clients.push(this); @@ -103,7 +110,8 @@ function initSocksConnection(on_accept) { if (idx != -1) { clients.splice(idx, 1); } - }); + });*/ + this.on('error', function(e) { errorLog('%j', e); }); @@ -144,7 +152,7 @@ function handshake5(chunk) { method_count = chunk[1]; this.auth_methods = []; - // i starts on 1, since we've read chunk 0 & 1 already + // i starts on 2, since we've read chunk 0 & 1 already for (var i=2; i < method_count + 2; i++) { this.auth_methods.push(chunk[i]); } @@ -152,10 +160,20 @@ function handshake5(chunk) { var resp = new Buffer(2); resp[0] = 0x05; + + // user/pass auth + if (USERPASS && this.auth_methods.indexOf(AUTHENTICATION.USERPASS) > -1) { + log('Handing off to handleAuthRequest'); + this.handleAuthRequest = handleAuthRequest.bind(this); + this.once('data', this.handleAuthRequest); + resp[1] = AUTHENTICATION.USERPASS; + this.write(resp); + } else + // NO Auth if (this.auth_methods.indexOf(AUTHENTICATION.NOAUTH) > -1) { - log('Handing off to handleRequest'); - this.handleRequest = handleRequest.bind(this); - this.once('data', this.handleRequest); + log('Handing off to handleConnRequest'); + this.handleConnRequest = handleConnRequest.bind(this); + this.once('data', this.handleConnRequest); resp[1] = AUTHENTICATION.NOAUTH; this.write(resp); } else { @@ -167,112 +185,150 @@ function handshake5(chunk) { // SOCKS4/4a function handshake4(chunk) { - var cmd=chunk[1], + var cmd = chunk[1], address, port, uid; - + // Wrong version! if (chunk[0] !== SOCKS_VERSION4) { this.end('%d%d', 0x00, 0x5b); - errorLog('socks4 handleRequest: wrong socks version: %d', chunk[0]); + errorLog('socks4 handleConnRequest: wrong socks version: %d', chunk[0]); return; } port = chunk.readUInt16BE(2); - + // SOCKS4a if ((chunk[4] == 0 && chunk[5] == chunk[6] == 0) && (chunk[7] != 0)) { var it = 0; - + uid = ''; - for (it=0; it < 1024; it++) { - uid += chunk[8+it]; - if (chunk[8+it] == 0x00) + for (it = 0; it < 1024; it++) { + uid += chunk[8 + it]; + if (chunk[8 + it] == 0x00) break; } address = ''; - if (chunk[8+it] == 0x00) { + if (chunk[8 + it] == 0x00) { for (it++; it < 2048; it++) { - address += chunk[8+it]; - if (chunk[8+it] == 0x00) - break; + address += chunk[8 + it]; + if (chunk[8 + it] == 0x00) + break; } } - if (chunk[8+it] == 0x00) { + if (chunk[8 + it] == 0x00) { // DNS lookup - DNS.lookup(address, function(err, ip, family){ - if (err) { - errorLog(err+',socks4a dns lookup failed'); - - this.end('%d%d', 0x00, 0x5b); - return; - } else { - this.socksAddress = ip; - this.socksPort = port; - this.socksUid = uid; - - log('socks4a Request: type: %d -- to: %s:%d:%s', cmd, address, port, uid); - - if (cmd == REQUEST_CMD.CONNECT) { - this.request = chunk; - this.on_accept(this, port, ip, proxyReady4.bind(this)); - } else { - this.end('%d%d', 0x00, 0x5b); - return; - } - } - }); + DNS.lookup(address, function (err, ip, family) { + if (err) { + errorLog(err + ',socks4a dns lookup failed'); + + this.end(new Buffer([0x00, 0x5b])); + return; + } else { + this.socksAddress = ip; + this.socksPort = port; + this.socksUid = uid; + + log('socks4a Request: type: %d -- to: %s:%d:%s', cmd, address, port, uid); + + if (cmd == REQUEST_CMD.CONNECT) { + this.request = chunk; + this.on_accept(this, port, ip, proxyReady4.bind(this)); + } else { + this.end(new Buffer([0x00, 0x5b])); + return; + } + } + }); } else { - this.end('%d%d', 0x00, 0x5b); + this.end(new Buffer([0x00, 0x5b])); return; } } else { // SOCKS4 address = util.format('%s.%s.%s.%s', chunk[4], chunk[5], chunk[6], chunk[7]); - + uid = ''; - for (it=0; it < 1024; it++) { - uid += chunk[8+it]; - if (chunk[8+it] == 0x00) + for (it = 0; it < 1024; it++) { + uid += chunk[8 + it]; + if (chunk[8 + it] == 0x00) break; } - - this.socksAddress = address; - this.socksPort = port; - this.socksUid = uid; - - log('socks4 Request: type: %d -- to: %s:%d:%s', cmd, address, port, uid); - - if (cmd == REQUEST_CMD.CONNECT) { - this.request = chunk; - this.on_accept(this, port, address, proxyReady4.bind(this)); - } else { - this.end('%d%d', 0x00, 0x5b); - return; - } + + this.socksAddress = address; + this.socksPort = port; + this.socksUid = uid; + + log('socks4 Request: type: %d -- to: %s:%d:%s', cmd, address, port, uid); + + if (cmd == REQUEST_CMD.CONNECT) { + this.request = chunk; + this.on_accept(this, port, address, proxyReady4.bind(this)); + } else { + this.end(new Buffer([0x00, 0x5b])); + return; + } + } +} + +function handlAuthRequest(chunk) { + var cmd=chunk[1], + username, + password; + // Wrong version! + if (chunk[0] !== SOCKS_VERSION5) { + this.end(new Buffer([0x05, x01])); + errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); + return; + } /* else if (chunk[2] == 0x00) { + this.end(util.format('%d%d', 0x05, 0x01)); + errorLog('socks5 handleConnRequest: Mangled request. Reserved field is not null: %d', chunk[offset]); + return; + } */ + try { + var na = [],pa=[],ni,pi; + for (ni= 2;ni<(2+chunk[1]); ni++) na.push(chunk[ni]);username = new Buffer(na).toString('utf8'); + for (pi=ni+1;pi<(ni+1+chunk[ni]);pi++) pa.push(chunk[pi]);password = new Buffer(pa).toString('utf8'); + } catch (e) { + errorLog('socks5 handleAuthRequest: username/password '+e); + return; + } + + log('socks5 Auth: username:%s,password:%s', username, password); + + // check user:pass + if (USERPASS && USERPASS.username===username && USERPASS.password===password) { + log('Handing off to handleConnRequest'); + this.handleConnRequest = handleConnRequest.bind(this); + this.once('data', this.handleConnRequest); + this.write(new Buffer([0x05, 0x00])); + } else { + this.end(new Buffer([0x05, x01])); + errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); + return; } } -function handleRequest(chunk) { +function handleConnRequest(chunk) { var cmd=chunk[1], address, port, offset=3; // Wrong version! if (chunk[0] !== SOCKS_VERSION5) { - this.end('%d%d', 0x05, 0x01); - errorLog('socks5 handleRequest: wrong socks version: %d', chunk[0]); + this.end(new Buffer([0x05, x01])); + errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); return; } /* else if (chunk[2] == 0x00) { this.end(util.format('%d%d', 0x05, 0x01)); - errorLog('socks5 handleRequest: Mangled request. Reserved field is not null: %d', chunk[offset]); + errorLog('socks5 handleConnRequest: Mangled request. Reserved field is not null: %d', chunk[offset]); return; } */ try { address = Address.read(chunk, 3); port = Port.read(chunk, 3); } catch (e) { - errorLog('socks5 handleRequest: Address.read '+e); + errorLog('socks5 handleConnRequest: Address.read '+e); return; } @@ -282,7 +338,7 @@ function handleRequest(chunk) { this.request = chunk; this.on_accept(this, port, address, proxyReady5.bind(this)); } else { - this.end('%d%d', 0x05, 0x01); + this.end(new Buffer([0x05, x01])); return; } } From d312c2da4b6181cea1517496e306695ce9b03782 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Thu, 12 Jan 2017 01:49:48 +0000 Subject: [PATCH 32/43] remove go.js --- go.js | 72 ----------------------------------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 go.js diff --git a/go.js b/go.js deleted file mode 100644 index ccd7545..0000000 --- a/go.js +++ /dev/null @@ -1,72 +0,0 @@ - -var net = require('net'), - socks = require('./socks.js'), - info = console.log.bind(console); - -// Create server -// The server accepts SOCKS connections. This particular server acts as a proxy. -var HOST = process.argv[3] || '127.0.0.1', - PORT = process.argv[2] || '6868', - server = socks.createServer(function(socket, port, address, proxy_ready) { - - // Implement your own proxy here! Do encryption, tunnelling, whatever! Go flippin' mental! - // I plan to tunnel everything including SSH over an HTTP tunnel. For now, though, here is the plain proxy: - - var proxy = net.createConnection({port:port, host:address}, proxy_ready); - var localAddress,localPort; - proxy.on('connect', function(){ - info('%s:%d <== %s:%d ==> %s:%d',socket.remoteAddress,socket.remotePort, - proxy.localAddress,proxy.localPort,proxy.remoteAddress,proxy.remotePort); - localAddress=proxy.localAddress; - localPort=proxy.localPort; - - // send ready res - proxy_ready(); - - proxy.pipe(socket).pipe(proxy); - }.bind(this)); - - proxy.on('error', function(err){ - //console.log('Ignore proxy error'); - }); - proxy.on('close', function(had_error) { - try { - if(localAddress && localPort) - console.log('The proxy %s:%d closed', localAddress, localPort); - else - console.error('Connect to %s:%d failed', address, port); - socket.end(); - } catch (err) { - } - }.bind(this)); - - socket.on('error', function(err){ - //console.log('Ignore socket error'); - }); - socket.on('close', function(had_error) { - try { - if (this.proxy !== undefined) { - proxy.removeAllListeners('data'); - proxy.end(); - } - //console.error('The socket %s:%d closed',socket.remoteAddress,socket.remotePort); - } catch (err) { - } - }.bind(this)); - - }); - -server.on('error', function (e) { - console.error('SERVER ERROR: %j', e); - if (e.code == 'EADDRINUSE') { - console.log('Address in use, retrying in 10 seconds...'); - setTimeout(function () { - console.log('Reconnecting to %s:%s', HOST, PORT); - server.close(); - server.listen(PORT, HOST); - }, 10000); - } -}); -server.listen(PORT, HOST); - -// vim: set filetype=javascript syntax=javascript : From 3566b1218a839377aa36a0b95d4c5a0fb2316ad7 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 12 Jan 2017 02:24:33 +0000 Subject: [PATCH 33/43] support user/pass auth --- proxy.js | 2 +- socks.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/proxy.js b/proxy.js index b2b7d9e..a200966 100644 --- a/proxy.js +++ b/proxy.js @@ -19,7 +19,7 @@ var HOST='127.0.0.1', proxy.localAddress,proxy.localPort,proxy.remoteAddress,proxy.remotePort); localAddress=proxy.localAddress; localPort=proxy.localPort; - }.bind(this)); + }.bind(this),process.argv[3]&&process.argv[4]&&{username:process.argv[3],password:process.argv[4]}); proxy.on('data', function(d) { try { //console.log('receiving ' + d.length + ' bytes from proxy'); diff --git a/socks.js b/socks.js index bbc942b..cdc1899 100644 --- a/socks.js +++ b/socks.js @@ -85,6 +85,7 @@ var net = require('net'), function createSocksServer(cb, userpass) { // record userpass USERPASS = userpass; + log('userpass:'+userpass); var socksServer = net.createServer(); socksServer.on('listening', function() { From 601f8bf05848caa2dcc68bc2639ac700a411fc00 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 12 Jan 2017 02:28:12 +0000 Subject: [PATCH 34/43] fixed typo --- proxy.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy.js b/proxy.js index a200966..8d03152 100644 --- a/proxy.js +++ b/proxy.js @@ -19,7 +19,7 @@ var HOST='127.0.0.1', proxy.localAddress,proxy.localPort,proxy.remoteAddress,proxy.remotePort); localAddress=proxy.localAddress; localPort=proxy.localPort; - }.bind(this),process.argv[3]&&process.argv[4]&&{username:process.argv[3],password:process.argv[4]}); + }.bind(this)); proxy.on('data', function(d) { try { //console.log('receiving ' + d.length + ' bytes from proxy'); @@ -80,7 +80,7 @@ var HOST='127.0.0.1', //console.error('The socket %s:%d closed',socket.remoteAddress,socket.remotePort); } catch (err) { } - }.bind(this)); + }.bind(this), process.argv[3]&&process.argv[4]&&{username:process.argv[3],password:process.argv[4]}); }); From fc3c5092e6792e149a0eea641dd059d4cfa798d1 Mon Sep 17 00:00:00 2001 From: tom zhou Date: Thu, 12 Jan 2017 11:06:30 +0800 Subject: [PATCH 35/43] use user/pass force auth --- socks.js | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/socks.js b/socks.js index cdc1899..8058d50 100644 --- a/socks.js +++ b/socks.js @@ -163,25 +163,31 @@ function handshake5(chunk) { resp[0] = 0x05; // user/pass auth - if (USERPASS && this.auth_methods.indexOf(AUTHENTICATION.USERPASS) > -1) { - log('Handing off to handleAuthRequest'); - this.handleAuthRequest = handleAuthRequest.bind(this); - this.once('data', this.handleAuthRequest); - resp[1] = AUTHENTICATION.USERPASS; - this.write(resp); + if (USERPASS) { + if (this.auth_methods.indexOf(AUTHENTICATION.USERPASS) > -1) { + log('Handing off to handleAuthRequest'); + this.handleAuthRequest = handleAuthRequest.bind(this); + this.once('data', this.handleAuthRequest); + resp[1] = AUTHENTICATION.USERPASS; + this.write(resp); + } else { + errorLog('Unsuported authentication method -- disconnecting'); + resp[1] = 0xFF; + this.end(resp); + } } else - // NO Auth - if (this.auth_methods.indexOf(AUTHENTICATION.NOAUTH) > -1) { - log('Handing off to handleConnRequest'); - this.handleConnRequest = handleConnRequest.bind(this); - this.once('data', this.handleConnRequest); - resp[1] = AUTHENTICATION.NOAUTH; - this.write(resp); - } else { - errorLog('Unsuported authentication method -- disconnecting'); - resp[1] = 0xFF; - this.end(resp); - } + // NO Auth + if (this.auth_methods.indexOf(AUTHENTICATION.NOAUTH) > -1) { + log('Handing off to handleConnRequest'); + this.handleConnRequest = handleConnRequest.bind(this); + this.once('data', this.handleConnRequest); + resp[1] = AUTHENTICATION.NOAUTH; + this.write(resp); + } else { + errorLog('Unsuported authentication method -- disconnecting'); + resp[1] = 0xFF; + this.end(resp); + } } // SOCKS4/4a From 29b6de06b6ec563bf5b8b961c35431f9df084ab1 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Thu, 12 Jan 2017 13:57:30 +0800 Subject: [PATCH 36/43] fixed typo --- socks.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/socks.js b/socks.js index 8058d50..f841cdd 100644 --- a/socks.js +++ b/socks.js @@ -278,13 +278,13 @@ function handshake4(chunk) { } } -function handlAuthRequest(chunk) { +function handleAuthRequest(chunk) { var cmd=chunk[1], username, password; // Wrong version! if (chunk[0] !== SOCKS_VERSION5) { - this.end(new Buffer([0x05, x01])); + this.end(new Buffer([0x05, 0x01])); errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); return; } /* else if (chunk[2] == 0x00) { @@ -297,6 +297,7 @@ function handlAuthRequest(chunk) { for (ni= 2;ni<(2+chunk[1]); ni++) na.push(chunk[ni]);username = new Buffer(na).toString('utf8'); for (pi=ni+1;pi<(ni+1+chunk[ni]);pi++) pa.push(chunk[pi]);password = new Buffer(pa).toString('utf8'); } catch (e) { + this.end(new Buffer([0x05, 0x01])); errorLog('socks5 handleAuthRequest: username/password '+e); return; } @@ -310,7 +311,7 @@ function handlAuthRequest(chunk) { this.once('data', this.handleConnRequest); this.write(new Buffer([0x05, 0x00])); } else { - this.end(new Buffer([0x05, x01])); + this.end(new Buffer([0x05, 0x01])); errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); return; } @@ -323,7 +324,7 @@ function handleConnRequest(chunk) { offset=3; // Wrong version! if (chunk[0] !== SOCKS_VERSION5) { - this.end(new Buffer([0x05, x01])); + this.end(new Buffer([0x05, 0x01])); errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); return; } /* else if (chunk[2] == 0x00) { @@ -332,8 +333,8 @@ function handleConnRequest(chunk) { return; } */ try { - address = Address.read(chunk, 3); - port = Port.read(chunk, 3); + address = Address.read(chunk, 3); + port = Port.read(chunk, 3); } catch (e) { errorLog('socks5 handleConnRequest: Address.read '+e); return; @@ -345,7 +346,7 @@ function handleConnRequest(chunk) { this.request = chunk; this.on_accept(this, port, address, proxyReady5.bind(this)); } else { - this.end(new Buffer([0x05, x01])); + this.end(new Buffer([0x05, 0x01])); return; } } From fb95e481dd114ac76e1b91c542ec7252db81eb4e Mon Sep 17 00:00:00 2001 From: root Date: Thu, 12 Jan 2017 14:56:46 +0000 Subject: [PATCH 37/43] fixed typo --- socks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/socks.js b/socks.js index f841cdd..91fe54b 100644 --- a/socks.js +++ b/socks.js @@ -199,7 +199,7 @@ function handshake4(chunk) { // Wrong version! if (chunk[0] !== SOCKS_VERSION4) { - this.end('%d%d', 0x00, 0x5b); + this.end(new Buffer([0x00, 0x5b])); errorLog('socks4 handleConnRequest: wrong socks version: %d', chunk[0]); return; } From 4b49dfbb01a0662890ab8fe858267dee7c73f83f Mon Sep 17 00:00:00 2001 From: tom zhou Date: Thu, 12 Jan 2017 23:05:11 +0800 Subject: [PATCH 38/43] fixed typo --- socks.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/socks.js b/socks.js index 91fe54b..8758646 100644 --- a/socks.js +++ b/socks.js @@ -279,8 +279,7 @@ function handshake4(chunk) { } function handleAuthRequest(chunk) { - var cmd=chunk[1], - username, + var username, password; // Wrong version! if (chunk[0] !== SOCKS_VERSION5) { From ab8ef45584b50daa50a1153317cdd88057392d30 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 12 Jan 2017 15:34:17 +0000 Subject: [PATCH 39/43] fixed socks support username/password auth --- proxy.js | 8 ++++---- socks.js | 24 ++++++++++-------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/proxy.js b/proxy.js index 8d03152..7bb979c 100644 --- a/proxy.js +++ b/proxy.js @@ -5,8 +5,8 @@ var net = require('net'), // Create server // The server accepts SOCKS connections. This particular server acts as a proxy. -var HOST='127.0.0.1', - PORT='8888', +var HOST='0.0.0.0', + PORT='6801', server = socks.createServer(function(socket, port, address, proxy_ready) { // Implement your own proxy here! Do encryption, tunnelling, whatever! Go flippin' mental! @@ -80,9 +80,9 @@ var HOST='127.0.0.1', //console.error('The socket %s:%d closed',socket.remoteAddress,socket.remotePort); } catch (err) { } - }.bind(this), process.argv[3]&&process.argv[4]&&{username:process.argv[3],password:process.argv[4]}); + }.bind(this)); - }); + }, process.argv[3]&&process.argv[4]&&{username:process.argv[3],password:process.argv[4]}); server.on('error', function (e) { console.error('SERVER ERROR: %j', e); diff --git a/socks.js b/socks.js index 91fe54b..ee7bb1f 100644 --- a/socks.js +++ b/socks.js @@ -85,7 +85,7 @@ var net = require('net'), function createSocksServer(cb, userpass) { // record userpass USERPASS = userpass; - log('userpass:'+userpass); + console.log('userpass:'+JSON.stringify(userpass)); var socksServer = net.createServer(); socksServer.on('listening', function() { @@ -279,25 +279,21 @@ function handshake4(chunk) { } function handleAuthRequest(chunk) { - var cmd=chunk[1], - username, + var username, password; // Wrong version! - if (chunk[0] !== SOCKS_VERSION5) { - this.end(new Buffer([0x05, 0x01])); - errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); + if (chunk[0] !== 1) { // MUST be 1 + this.end(new Buffer([0x01, 0x01])); + errorLog('socks5 handleAuthRequest: wrong socks version: %d', chunk[0]); return; - } /* else if (chunk[2] == 0x00) { - this.end(util.format('%d%d', 0x05, 0x01)); - errorLog('socks5 handleConnRequest: Mangled request. Reserved field is not null: %d', chunk[offset]); - return; - } */ + } + try { var na = [],pa=[],ni,pi; for (ni= 2;ni<(2+chunk[1]); ni++) na.push(chunk[ni]);username = new Buffer(na).toString('utf8'); for (pi=ni+1;pi<(ni+1+chunk[ni]);pi++) pa.push(chunk[pi]);password = new Buffer(pa).toString('utf8'); } catch (e) { - this.end(new Buffer([0x05, 0x01])); + this.end(new Buffer([0x01, 0x01])); errorLog('socks5 handleAuthRequest: username/password '+e); return; } @@ -309,9 +305,9 @@ function handleAuthRequest(chunk) { log('Handing off to handleConnRequest'); this.handleConnRequest = handleConnRequest.bind(this); this.once('data', this.handleConnRequest); - this.write(new Buffer([0x05, 0x00])); + this.write(new Buffer([0x01, 0x00])); } else { - this.end(new Buffer([0x05, 0x01])); + this.end(new Buffer([0x01, 0x01])); errorLog('socks5 handleConnRequest: wrong socks version: %d', chunk[0]); return; } From fe4d27a30a79ccaf8ece90a19703325e3c1cd120 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 12 Jan 2017 15:54:56 +0000 Subject: [PATCH 40/43] tag 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8bb1a36..af08fe3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socks5" - , "version": "1.0.0" + , "version": "1.0.1" , "description": "A simple SOCKS 5/4/4a implementation and demo proxy" , "author": [ "Gert Van Gool ", From 62b017937c98c5c412c4c1f7b36534e26a044153 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Fri, 13 Jan 2017 10:08:11 +0800 Subject: [PATCH 41/43] Update proxy.js --- proxy.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy.js b/proxy.js index 7bb979c..882b02f 100644 --- a/proxy.js +++ b/proxy.js @@ -5,8 +5,8 @@ var net = require('net'), // Create server // The server accepts SOCKS connections. This particular server acts as a proxy. -var HOST='0.0.0.0', - PORT='6801', +var HOST='127.0.0.1', + PORT='8888', server = socks.createServer(function(socket, port, address, proxy_ready) { // Implement your own proxy here! Do encryption, tunnelling, whatever! Go flippin' mental! From c02cddc743d7742c7f03be2cdf39e347b1bce1df Mon Sep 17 00:00:00 2001 From: tomzhou Date: Wed, 25 Jan 2017 21:52:39 +0800 Subject: [PATCH 42/43] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7e1ef21..43d5d6f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -SOCKS v4/v4a/v5 server implementation in node.js -=============================== +SOCKS v4/v4a/v5 server implementation with user/pass authenticationin node.js +============================================================================= A simple SOCKS v5/v4/v4a server implementation and demo proxy. From 3c76be828aa0b0f5f8f41ba2a19ac70134051e19 Mon Sep 17 00:00:00 2001 From: tomzhou Date: Wed, 25 Jan 2017 21:53:17 +0800 Subject: [PATCH 43/43] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43d5d6f..412ca72 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -SOCKS v4/v4a/v5 server implementation with user/pass authenticationin node.js +SOCKS v4/v4a/v5 server implementation with user/pass authentication node.js ============================================================================= A simple SOCKS v5/v4/v4a server implementation and demo proxy.