@pondwader/socks5-server
v1.0.10
Published
A Node.js socks5 server implementation enabling fine-grained connection control.
Downloads
68
Maintainers
Readme
node-socks5-server
A Node.js implementation of a socks5 server written in TypeScript.
The library handles the protocol side but allows you to gain fine-grained control of connections and how they're handled.
Features:
- Override the handling of socket proxying
- Handle authentication yourself
- Full type support
- Process Duplex streams as connections
Installation
With npm:
npm i @pondwader/socks5-server
With yarn:
yarn add @pondwader/socks5-server
Basic usage
Spin up a basic socks5 proxy server with just this code:
const { createServer } = require('@pondwader/socks5-server');
createServer({
port: 5000
})
Or handle the listening yourself:
const { createServer } = require('@pondwader/socks5-server');
const server = createServer();
server.listen(5000, '127.0.0.1', () => {
console.log('Server listening on port 5000');
})
Username-password authentication
const { createServer } = require('@pondwader/socks5-server');
createServer({
port: 5000,
auth: {
username: 'user123',
password: 'password123'
}
})
Or handle the authentication yourself:
const { createServer } = require('@pondwader/socks5-server');
const server = createServer({
port: 5000
})
// Using a synchronous function
server.setAuthHandler((conn) => {
return conn.username === 'user123' && conn.password === 'password123';
})
// Using a promise
server.setAuthHandler((conn) => {
return new Promise(resolve => {
resolve(conn.username === 'user123' && conn.password === 'password123');
})
})
// Using callbacks
server.setAuthHandler((conn, accept, reject) => {
if (conn.username === 'user123' && conn.password === 'password123') accept();
else reject();
})
Rejecting connections for breaking ruleset
You can reject connections that beak your ruleset:
const { createServer } = require('@pondwader/socks5-server');
const server = createServer({
port: 5000
})
// Using a synchronous return
server.setRulesetValidator((conn) => {
return conn.destPort !== 25;
});
// Using a promise
server.setRulesetValidator((conn) => {
return new Promise(resolve => {
resolve(conn.destPort !== 25);
})
});
// Using callbacks
server.setRulesetValidator((conn, accept, deny) => {
if (conn.destPort === 25) deny();
else accept();
});
You also have to access to <Socks5Connection>.destAddress
.
Handling the proxying of connections
By default the library will handle connections itself using the built in connection handler, but you can override this to use your own handler.
See the built in connection handling function here to further your understanding on how to handle connections.
You can set your handling function:
const { createServer } = require('@pondwader/socks5-server');
const server = createServer({
port: 5000
})
server.setConnectionHandler((conn, sendStatus) => {
const { socket, destAddress, destPort } = conn;
/*
You need to send a status before the client should start sending data in the socket.
If you send REQUEST_GRANTED the client should begin sending data, any other status will close the socket.
REQUEST_GRANTED,
GENERAL_FAILURE,
CONNECTION_NOT_ALLOWED,
NETWORK_UNREACHABLE,
HOST_UNREACHABLE,
CONNECTION_REFUSED,
TTL_EXPIRED,
COMMAND_NOT_SUPPORTED
*/
// Do stuff here
})
Handling commands other than connect
The library only has a built in handler for connections using the connect
command, this is used for TCP socket proxying and is by far the most common command however, you may wish to add support for other commands.
The other command types are udp
and bind
. To handle these you will need to make your own connection handler (see section above). Note: the Socks5Connection
class exposes the command
property which gives you access to the command sent by the client.
You will also need to add the commands you want to handle to the supported commands set. The Socks5Server
class has the supportedCommands
property which is a Set instance.
For example:
<Socks5Server>.supportedCommands.add('udp');
You can also pass Duplex streams as connections...
const { Duplex } = require('streams');
server._handleConnection(new Duplex());
Metadata
The Socks5Connection
class has a metadata attribute which starts as an empty object, you can put data in this to pass data about a connection between seperate handlers.