- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation
🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
151 lines
4.6 KiB
Markdown
151 lines
4.6 KiB
Markdown
# 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:
|
|
```js
|
|
const { createServer } = require('@pondwader/socks5-server');
|
|
|
|
createServer({
|
|
port: 5000
|
|
})
|
|
```
|
|
Or handle the listening yourself:
|
|
```js
|
|
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
|
|
```js
|
|
const { createServer } = require('@pondwader/socks5-server');
|
|
|
|
createServer({
|
|
port: 5000,
|
|
auth: {
|
|
username: 'user123',
|
|
password: 'password123'
|
|
}
|
|
})
|
|
```
|
|
Or handle the authentication yourself:
|
|
```js
|
|
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:
|
|
```js
|
|
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.](https://github.com/PondWader/node-socks5-server/blob/main/src/connectionHandler.ts)
|
|
You can set your handling function:
|
|
```js
|
|
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) instance.
|
|
For example:
|
|
`<Socks5Server>.supportedCommands.add('udp');`
|
|
|
|
## You can also pass Duplex streams as connections...
|
|
```js
|
|
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. |