Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions example/cks5-hostname
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
29 changes: 14 additions & 15 deletions example/index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@

const socks5Stream = require("../src/index");
const net = require("net");
// Server mock
const socks5Stream = require('../src/index');
const net = require('net');
// Server mock

var server = net.createServer((socket) => {
// Create a new socks5 stream without Authentication
var sockStream = new socks5Stream(socket);

//Create a new socks5 stream with Type as "username" and Auth details as Username and Password

//Create a new socks5 stream with Username and Password Authentication
var sockStreamAuth = new socks5Stream(socket, {
authType:"username",
username:"username",
password:"password"
username: "username",
password: "password",
authType: "username"
});

//Piping the data to sock5 stream
socket.pipe(sockStream).once("data", (data) => {
console.log("<HOST>,<PORT> ==> " + data.toString());
socket.pipe(sockStream).once('data', (data) => {
console.log('<HOST>,<PORT> ==> ' + data.toString());
sockStream.acceptConnection(true);
sockStream.on("data", (chunk) => {
console.log(chunk.toString());
});
});
sockStream.on('data', (chunk) => {
// console.log(chunk.toString());
})
})
});

server.listen(8124, () => {
console.log("server bound");
console.log('server bound');
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
"url": "https://github.com/nimit95/socks5-stream/issues"
},
"homepage": "https://github.com/nimit95/socks5-stream#readme"
}
}
21 changes: 6 additions & 15 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,19 @@
module.exports.socksVersion = 0x05;

module.exports.states = {
NO_CONNECTION:0,
CONNECTING:1,
NO_CONNECTION: 0,
CONNECTING: 1,
CONNECTED: 3,
DISCONNECTED: 4,
AUTHENTICATION: 5
};
}

module.exports.authTypes = {
username:1
};
username: 1
}

module.exports.SOCKS_ADDRESS = {
IPV4: 0x01,
HOSTNAME: 0x03,
IPV6: 0x04
};

module.exports.SOCKET_ERRORS = {
NOT_DEFINED : "Socket is not defined or valid",
WRONG_AUTH : "Wrong Authentication Details givem",
INITIAL_HANSHAKE : "Got Wrong initial Handshake(not 5,0,x)",
INVALID_AUTH_PACKET: "Invalid Authentication Packet received",
INVALID_CONNECT: "Got Wrong Handshake(not 5,1,x,x,x...)",
NO_CONNECTION : "Connection not established yet"
};
}
94 changes: 48 additions & 46 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@

const { Transform } = require("stream");
const util = require("util");
const constants = require("./constants");
const socksUtils = require("./socksUtils");
const utils = require("./utils");
const { Transform } = require('stream');
const util = require('util');
const constants = require('./constants');
const socksUtils = require('./socksUtils');
const utils = require('./utils')

/**
* @param {net.Socket} socket
* @param {net.Socket} socket
* Socket from which the Socks stream is comming.
* @param {Object} authDetails
* Optional for authorization if any, Defaults to undefined
* {
* //In case of username and password
* //In case of username and password
* authType:"username",
* username:<username>,
* password:<password>
*
*
*
*
* }
*/
const socks5Stream = function(socket, authDetails) {
const socks5Stream = function (socket, authDetails) {

this.authDetails = authDetails || false;
this._socket = socket;
Expand All @@ -28,87 +28,89 @@ const socks5Stream = function(socket, authDetails) {

this.state = constants.states.NO_CONNECTION;

if(this.authDetails) {
this.authType = constants.authTypes[this.authDetails.authType];
if (this.authDetails) {
this.authType = constants.authTypes[this.authDetails.authType]
} else {
this.authType = false;
}
};

}

util.inherits(socks5Stream, Transform);

socks5Stream.prototype._transform = function(chunk, encoding, callback) {
socks5Stream.prototype._transform = function (chunk, encoding, callback) {

if(!utils.isSocketObjValid(this._socket)) {
return callback(new Error(constants.SOCKET_ERRORS.NOT_DEFINED));
if (!utils.isSocketObjValid(this._socket)) {
return callback(new Error("Socket is not defined or valid"));
}

if(this.authDetails && !utils.validateAuth(this.authDetails)) {
return callback(new Error(constants.SOCKET_ERRORS.WRONG_AUTH));
if (this.authDetails && !utils.validateAuth(this.authDetails)) {
return callback(new Error("Wrong Authentication Details"));
}

// console.log(chunk);

if(this.state === constants.states.NO_CONNECTION) {
if(!socksUtils.checkIntialSocksChunk(chunk)) {
return callback(new Error(constants.SOCKET_ERRORS.INITIAL_HANSHAKE));
if (this.state === constants.states.NO_CONNECTION) {

if (!socksUtils.checkIntialSocksChunk(chunk)) {
return callback(new Error("Got Wrong initial Handshake(not 5,0,x)"));
}
//We need to conect
//We need to conect
this._socket.write(socksUtils.generateInitialHandshakeResponse(this.authType), () => {
this.state = this.authDetails? constants.states.AUTHENTICATION : constants.states.CONNECTING;

this.state = this.authDetails ? constants.states.AUTHENTICATION : constants.states.CONNECTING;
callback(null);
});

}

if(this.state === constants.states.AUTHENTICATION) {
if(!socksUtils.checkAuthRequest(chunk, this.authType)) {
return callback(new Error(constants.SOCKET_ERRORS.INVALID_AUTH_PACKET));
if (this.state === constants.states.AUTHENTICATION) {
if (!socksUtils.checkAuthRequest(chunk, this.authType)) {
return callback(new Error("Wrong Authentication Details"));
}

var authDetailRequest = socksUtils.getUsernamePassFromRequest(chunk, this.authType);

if(this.authDetails.username == authDetailRequest.username && this.authDetails.password == authDetailRequest.password) {
if (this.authDetails.username == authDetailRequest.username && this.authDetails.password == authDetailRequest.password) {
this._socket.write(socksUtils.generateSuccessSocksAuthResponse(), () => {
this.state = constants.states.CONNECTING;
});
})
callback(null);
} else {

this._socket.write(socksUtils.generateFailSocksAuthResponse(), () => {
this.state = constants.states.DISCONNECTED;
});
})
//Closing the connection in case of wrong username/password
this._socket.end();
}

}

if(this.state === constants.states.CONNECTING) {
if(!socksUtils.checkConnectResponse(chunk)) {
return callback(new Error(constants.SOCKET_ERRORS.INVALID_CONNECT));
if (this.state === constants.states.CONNECTING) {
if (!socksUtils.checkConnectResponse(chunk)) {
return callback(new Error("Got Wrong Handshake(not 5,1,x,x,x...)"));
}

let hostnamePortObj = socksUtils.getHostnamePort(chunk);

return callback(null, `${hostnamePortObj.hostname}, ${hostnamePortObj.port}`);
return callback(null, `${hostnamePortObj.hostname},${hostnamePortObj.port}`);
}

if(this.state === constants.states.CONNECTED) {
if (this.state === constants.states.CONNECTED) {
// console.log('connected', chunk.toString());
callback(null, chunk);
}

if(this.state === constants.states.DISCONNECTED) {
if (this.state === constants.states.DISCONNECTED) {
callback(null);
}
this.acceptConnection = function(flag) {
if(this.state === constants.states.NO_CONNECTION) {
return callback(new Error(constants.SOCKET_ERRORS.NO_CONNECTION));
this.acceptConnection = function (flag) {
if (this.state === constants.states.NO_CONNECTION) {
return callback(new Error("Connection not established yet."));
}

if(flag) {
if (flag) {
this._socket.write(socksUtils.connectionSuccessfulResponse(), () => {
this.state = constants.states.CONNECTED;
});
Expand All @@ -119,15 +121,15 @@ socks5Stream.prototype._transform = function(chunk, encoding, callback) {
//return callback(null);
});
}
};
}

this._socket.on("close", () => {
this._socket.on('close', () => {
this.state = constants.states.DISCONNECTED;
});
this._socket.on("error", () => {
this._socket.on('error', () => {
this.state = constants.states.DISCONNECTED;
});
};

}

module.exports = socks5Stream;
Loading