socksjs
Advanced tools
Comparing version 0.3.4 to 0.4.0
{ | ||
"name": "socksjs", | ||
"version": "0.3.4", | ||
"version": "0.4.0", | ||
"description": "A SOCKS (v5) client library for node.js", | ||
@@ -5,0 +5,0 @@ "keywords": ["SOCKS", "SOCKS5", "SOCKS client", "client"], |
275
socks.js
@@ -9,2 +9,3 @@ var stream = require('stream'), | ||
var that = this; | ||
stream.Duplex.call(this); | ||
@@ -18,2 +19,4 @@ | ||
socks_options = defaults(socks_options, { | ||
localAddress: '0.0.0.0', | ||
allowHalfOpen: false, | ||
host: 'localhost', | ||
@@ -25,7 +28,14 @@ port: 1080, | ||
this._socksSetup = false; | ||
this.socksAddress = null; | ||
this.socksPort = null; | ||
this.socksSocket = net.connect({host: socks_options.host, port: socks_options.port}, socksConnected.bind(this, !(!socks_options.user))); | ||
this.socksSocket.once('data', socksAuth.bind(this, {user: socks_options.user, pass: socks_options.pass})); | ||
this.socksSocket = net.createConnection({ | ||
host: socks_options.host, | ||
port: socks_options.port, | ||
localAddress: socks_options.localAddress, | ||
allowHalfOpen: socks_options.allowHalfOpen | ||
}, socksConnected.bind(this, !(!socks_options.user))); | ||
this.socksSocket.on('error', function (err) { | ||
@@ -35,2 +45,4 @@ that.emit('error', err); | ||
socksAuth.call(this, {user: socks_options.user, pass: socks_options.pass}); | ||
this.outSocket = this.socksSocket; | ||
@@ -50,7 +62,20 @@ }; | ||
SocksConnection.prototype._read = function () { | ||
this.outSocket.resume(); | ||
var data; | ||
if (this._socksSetup) { | ||
while ((data = this.outSocket.read()) !== null) { | ||
if ((this.push(data)) === false) { | ||
break; | ||
} | ||
} | ||
} else { | ||
this.push(''); | ||
} | ||
}; | ||
SocksConnection.prototype._write = function (chunk, encoding, callback) { | ||
this.outSocket.write(chunk, 'utf8', callback); | ||
if (this._socksSetup) { | ||
this.outSocket.write(chunk, 'utf8', callback); | ||
} else { | ||
callback("Not connected"); | ||
} | ||
}; | ||
@@ -68,2 +93,15 @@ | ||
var getData = function (socket, bytes, callback) { | ||
var dataReady = function () { | ||
var data = socket.read(bytes); | ||
if (data !== null) { | ||
socket.removeListener('readable', dataReady); | ||
callback(data); | ||
} else { | ||
socket.on('readable', dataReady); | ||
} | ||
}; | ||
dataReady(); | ||
}; | ||
var socksConnected = function (auth) { | ||
@@ -76,32 +114,44 @@ if (auth) { | ||
} | ||
}; | ||
var socksAuth = function (auth, data) { | ||
var bufs = []; | ||
switch (data.readUInt8(1)) { | ||
case 255: | ||
this.emit('error', 'SOCKS: No acceptable authentication methods'); | ||
this.socksSocket.destroy(); | ||
break; | ||
case 2: | ||
bufs[0] = new Buffer([1]); | ||
bufs[1] = new Buffer([Buffer.byteLength(auth.user)]); | ||
bufs[2] = new Buffer(auth.user); | ||
bufs[3] = new Buffer([Buffer.byteLength(auth.pass)]); | ||
bufs[4] = new Buffer(auth.pass); | ||
this.socksSocket.write(Buffer.concat(bufs)); | ||
this.socksSocket.once('data', socksAuthStatus.bind(this)); | ||
break; | ||
default: | ||
socksRequest.call(this, this.remote_options.host, this.remote_options.port); | ||
} | ||
var socksAuth = function (auth) { | ||
var that = this; | ||
getData(this.socksSocket, 2, function (data) { | ||
if (data.readUInt8(0) !== 5) { | ||
that.emit('error', 'Only SOCKS version 5 is supported'); | ||
that.socksSocket.destroy(); | ||
return; | ||
} | ||
switch (data.readUInt8(1)) { | ||
case 255: | ||
that.emit('error', 'SOCKS: No acceptable authentication methods'); | ||
that.socksSocket.destroy(); | ||
return; | ||
case 2: | ||
that.socksSocket.write(Buffer.concat([ | ||
new Buffer([1]), | ||
new Buffer([Buffer.byteLength(auth.user)]), | ||
new Buffer(auth.user), | ||
new Buffer([Buffer.byteLength(auth.pass)]), | ||
new Buffer(auth.pass) | ||
])); | ||
socksAuthStatus.call(that); | ||
break; | ||
default: | ||
socksRequest.call(that, that.remote_options.host, that.remote_options.port); | ||
} | ||
}); | ||
}; | ||
var socksAuthStatus = function (data) { | ||
if (data.readUInt8(1) === 1) { | ||
socksRequest.call(this, this.remote_options.host, this.remote_options.port); | ||
} else { | ||
this.emit('error', 'SOCKS: Authentication failed'); | ||
this.socksSocket.destroy(); | ||
} | ||
var that = this; | ||
getData(this.socksSocket, 2, function (data) { | ||
if (data.readUInt8(1) === 0) { | ||
socksRequest.call(that, that.remote_options.host, that.remote_options.port); | ||
} else { | ||
that.emit('error', 'SOCKS: Authentication failed'); | ||
that.socksSocket.destroy(); | ||
} | ||
}); | ||
}; | ||
@@ -127,74 +177,98 @@ | ||
this.socksSocket.write(Buffer.concat([header, type, hostBuf, portBuf])); | ||
this.socksSocket.once('data', socksReply.bind(this)); | ||
socksReply.call(this); | ||
}; | ||
var socksReply = function (data) { | ||
var err, port, i, addr_len, addr = ''; | ||
var status = data.readUInt8(1); | ||
if (status === 0) { | ||
switch (data.readUInt8(3)) { | ||
case 1: | ||
for (i = 0; i < 4; i++) { | ||
if (i !== 0) { | ||
addr += '.'; | ||
} | ||
addr += data.readUInt8(4 + i); | ||
var that = this; | ||
getData(this.socksSocket, 4, function (data) { | ||
var status, err, cont; | ||
cont = function (addr, port) { | ||
that.socksAddress = addr; | ||
that.socksPort = port; | ||
if (that.remote_options.ssl) { | ||
startTLS.call(that); | ||
} else { | ||
proxyData.call(that); | ||
that.emit('connect'); | ||
} | ||
port = data.readUInt16BE(8); | ||
break; | ||
case 4: | ||
for (i = 0; i < 16; i++) { | ||
if (i !== 0) { | ||
addr += ':'; | ||
} | ||
addr += data.readUInt8(4 + i); | ||
}; | ||
status = data.readUInt8(1); | ||
if (status === 0) { | ||
switch(data.readUInt8(3)) { | ||
case 1: | ||
getData(that.socksSocket, 6, function (data2) { | ||
var addr = '', port, i; | ||
for (i = 0; i < 4; i++) { | ||
if (i !== 0) { | ||
addr += '.'; | ||
} | ||
addr += data2.readUInt8(i).toString(); | ||
} | ||
port = data2.readUInt16BE(4); | ||
cont(addr, port); | ||
}); | ||
break; | ||
case 3: | ||
getData(that.socksSocket, 18, function (data2) { | ||
var length = data2.readUInt8(0); | ||
getData(that.socksSocket, length + 2, function (data3) { | ||
var addr, port; | ||
addr = (data3.slice(0, -2)).toString(); | ||
port = data3.readUInt16BE(length); | ||
cont(addr, port); | ||
}); | ||
}); | ||
break; | ||
case 4: | ||
getData(that.socksSocket, 1, function (data2) { | ||
var addr = '', port, i; | ||
for (i = 0; i < 16; i++) { | ||
if (i !== 0) { | ||
addr += ':'; | ||
} | ||
addr += data2.readUInt8(i); | ||
} | ||
port = data2.readUInt16BE(16); | ||
cont(addr, port); | ||
}); | ||
break; | ||
default: | ||
that.emit('error', "Invalid address type"); | ||
that.socksSocket.destroy(); | ||
break; | ||
} | ||
port = data.readUInt16BE(20); | ||
break; | ||
case 3: | ||
addr_len = data.readUInt8(4); | ||
addr = (data.slice(5, 5 + addr_len)).toString(); | ||
port = data.readUInt16BE(5 + addr_len); | ||
} | ||
this.socksAddress = addr; | ||
this.socksPort = port; | ||
if (this.remote_options.ssl) { | ||
startTLS.call(this); | ||
} else { | ||
proxyData.call(this); | ||
this.emit('connect'); | ||
switch (status) { | ||
case 1: | ||
err = 'SOCKS: general SOCKS server failure'; | ||
break; | ||
case 2: | ||
err = 'SOCKS: Connection not allowed by ruleset'; | ||
break; | ||
case 3: | ||
err = 'SOCKS: Network unreachable'; | ||
break; | ||
case 4: | ||
err = 'SOCKS: Host unreachable'; | ||
break; | ||
case 5: | ||
err = 'SOCKS: Connection refused'; | ||
break; | ||
case 6: | ||
err = 'SOCKS: TTL expired'; | ||
break; | ||
case 7: | ||
err = 'SOCKS: Command not supported'; | ||
break; | ||
case 8: | ||
err = 'SOCKS: Address type not supported'; | ||
break; | ||
default: | ||
err = 'SOCKS: Unknown error'; | ||
} | ||
that.emit('error', err); | ||
} | ||
} else { | ||
switch (status) { | ||
case 1: | ||
err = 'SOCKS: general SOCKS server failure'; | ||
break; | ||
case 2: | ||
err = 'SOCKS: Connection not allowed by ruleset'; | ||
break; | ||
case 3: | ||
err = 'SOCKS: Network unreachable'; | ||
break; | ||
case 4: | ||
err = 'SOCKS: Host unreachable'; | ||
break; | ||
case 5: | ||
err = 'SOCKS: Connection refused'; | ||
break; | ||
case 6: | ||
err = 'SOCKS: TTL expired'; | ||
break; | ||
case 7: | ||
err = 'SOCKS: Command not supported'; | ||
break; | ||
case 8: | ||
err = 'SOCKS: Address type not supported'; | ||
break; | ||
default: | ||
err = 'SOCKS: Unknown error'; | ||
} | ||
this.emit('error', err); | ||
} | ||
}); | ||
}; | ||
@@ -216,2 +290,3 @@ | ||
}); | ||
this.outSocket = plaintext; | ||
@@ -224,6 +299,8 @@ proxyData.call(this); | ||
this.outSocket.on('data', function (data) { | ||
var buffer_not_full = that.push(data); | ||
if (!buffer_not_full) { | ||
this.pause(); | ||
this.outSocket.on('readable', function () { | ||
var data; | ||
while ((data = that.outSocket.read()) !== null) { | ||
if ((that.push(data)) === false) { | ||
break; | ||
} | ||
} | ||
@@ -239,2 +316,4 @@ }); | ||
}); | ||
this._socksSetup = true; | ||
}; | ||
@@ -241,0 +320,0 @@ |
@@ -12,3 +12,8 @@ var socksjs = require('./socks.js'); | ||
sock.on('data', function (data) { | ||
console.log('data: %s', data); | ||
}); | ||
console.log(data.toString()); | ||
//console.log('data'); | ||
}); | ||
sock.on('end', function () { | ||
console.log('end'); | ||
}); |
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
24038
6
575
50
1
5