@mutagen-d/node-proxy-server
Advanced tools
+1
-1
| { | ||
| "name": "@mutagen-d/node-proxy-server", | ||
| "version": "0.1.0", | ||
| "version": "0.2.0", | ||
| "description": "Http and socks proxy server", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
+89
-4
@@ -10,3 +10,3 @@ # node-proxy-server | ||
| ```bash | ||
| npm install node-proxy-server | ||
| npm install @mutagen-d/node-proxy-server | ||
| ``` | ||
@@ -18,5 +18,5 @@ | ||
| const net = require('net') | ||
| const { createHttpProxy, createSocksProxy } = require('node-proxy-server') | ||
| const { createHttpProxy, createSocksProxy } = require('@mutagen-d/node-proxy-server') | ||
| const server = net.createServer(); | ||
| const server = net.createServer() | ||
@@ -31,2 +31,87 @@ const options = { | ||
| server.listen(8080) | ||
| ``` | ||
| ``` | ||
| ## API | ||
| ### `createHttpProxy([serverOrOptions [, options]])` | ||
| - `serverOrOptions` - `net.Server` or `HttpProxyServerOptions` | ||
| - `options` - `HttpProxyServerOptions` | ||
| `HttpProxyServerOptions`: | ||
| | name | type | required | default | description | | ||
| | ---------------- | --------------------- | -------- | ------- | ---------------------------------------------------------------------------------------- | | ||
| | `keepAlive` | `boolean` | `no` | `true` | controls keep-alive behavior | | ||
| | `keepAliveMsecs` | `number` | `no` | `1000` | inactivity timeout before close connection | | ||
| | `authType` | `"Basic" \| "Bearer"` | `no` | - | if defined then proxy authentication required | | ||
| | `authRealm` | `string` | `no` | - | | | ||
| | `onAuth` | `OnAuth` | `no` | - | | | ||
| | `useHttpRequest` | `boolean` | `no` | - | if `ture` then use `http.request` for HTTP requests, otherwise directly use `net.Socket` | | ||
| | `rewriteOptions` | `RewriteOptions` | `no` | - | if defined then rewrite connection options for each subsequence connections | | ||
| 1. Authorization: | ||
| ```js | ||
| const server = createHttpProxy({ | ||
| authType: 'Basic', | ||
| onAuth: (auth, callback) => { | ||
| switch (auth.type) { | ||
| case 'Basic': | ||
| // authorize connection | ||
| callback(auth.username === 'test' && auth.password === '1234') | ||
| break | ||
| default: | ||
| // reject connection | ||
| callback(false) | ||
| break | ||
| } | ||
| }, | ||
| }) | ||
| ``` | ||
| 2. Rewrite options: | ||
| ```js | ||
| const server = createHttpProxy({ | ||
| rewriteOptions: (req, callback) => { | ||
| if (req.url === 'localhost:443') { | ||
| callback({ rejectUnauthorized: false }) | ||
| } | ||
| }, | ||
| }) | ||
| ``` | ||
| ### `createSocksProxy([serverOrOptions [, options]])` | ||
| - `serverOrOptions` - `net.Server` or `SocksProxyServerOptions` | ||
| - `options` - `SocksProxyServerOptions` | ||
| `SocksProxyServerOptions`: | ||
| | name | type | required | default | description | | ||
| | ---------------- | ---------------- | -------- | ------- | --------------------------------------------------------------------------- | | ||
| | `keepAlive` | `boolean` | `no` | `true` | controls keep-alive behavior | | ||
| | `keepAliveMsecs` | `number` | `no` | `1000` | inactivity timeout before close connection | | ||
| | `onAuth` | `OnAuth` | `no` | - | if defined then prefer password authentication | | ||
| | `rewriteOptions` | `RewriteOptions` | `no` | - | if defined then rewrite connection options for each subsequence connections | | ||
| 1. Authorization | ||
| ```js | ||
| const server = createSocksProxy({ | ||
| onAuth: (username, password, callback) => { | ||
| callback(username === 'test' && password === '1234') | ||
| }, | ||
| }) | ||
| ``` | ||
| 2. Rewrite options: | ||
| ```js | ||
| const server = createSocksProxy({ | ||
| rewriteOptions: (_, callback) => { | ||
| callback({ rejectUnauthorized: false }) | ||
| }, | ||
| }) | ||
| ``` |
+7
-13
@@ -16,6 +16,6 @@ const net = require('net') | ||
| UDP: 0x03, | ||
| [0x01]: 'CONNECT', | ||
| [0x02]: 'BIND', | ||
| [0x03]: 'UDP', | ||
| } | ||
| Object.keys(CMD).forEach(key => { | ||
| CMD[CMD[key]] = key | ||
| }) | ||
@@ -77,3 +77,3 @@ const REPv4 = { | ||
| const _socks = server instanceof net.Server ? opts : server; | ||
| proxy._socks = Object.assign({ onAuth: _unAuth, keepAlive: true, keepAliveMsecs: 1000 }, _socks) | ||
| proxy._socks = Object.assign({ keepAlive: true, keepAliveMsecs: 1000 }, _socks) | ||
| proxy._socksRewriteOptions = _socks ? _socks.rewriteOptions : undefined; | ||
@@ -203,3 +203,3 @@ proxy.on('connection', _onConnection) | ||
| } | ||
| const { keepAlive, keepAliveMsecs } = socket._socks; | ||
| const { onAuth, keepAlive, keepAliveMsecs } = socket._socks; | ||
| if (keepAlive) { | ||
@@ -210,3 +210,3 @@ _setKeepAlive(socket, keepAliveMsecs) | ||
| const auth = data.subarray(2, 2 + nauth) | ||
| if (auth.includes(0x02)) { | ||
| if (auth.includes(0x02) && onAuth) { | ||
| socket.write(Buffer.from([0x05, 0x02])) | ||
@@ -216,3 +216,3 @@ socket.once('data', _onPwAuth) | ||
| } | ||
| if (auth.includes(0x00)) { | ||
| if (auth.includes(0x00) && !onAuth) { | ||
| socket.write(Buffer.from([0x05, 0x00])) | ||
@@ -324,7 +324,1 @@ socket.once('data', _onSocks5Connection) | ||
| } | ||
| /** @type {OnAuth} */ | ||
| function _unAuth(_username, _password, _callback) { | ||
| _callback(false) | ||
| } |
@@ -146,3 +146,3 @@ const fs = require('fs') | ||
| }) | ||
| it('request', async () => { | ||
| it('Successfull request', async () => { | ||
| const config = { | ||
@@ -165,2 +165,4 @@ hostname: '127.0.0.1', | ||
| protocol: 'socks5h:', | ||
| username: proxy.auth.username, | ||
| password: proxy.auth.password, | ||
| }].map(opts => new SocksProxyAgent({ ...config, ...opts })) | ||
@@ -203,2 +205,41 @@ | ||
| }, 10 * 1000) | ||
| it('Unsupported auth type error', async () => { | ||
| const config = { | ||
| hostname: '127.0.0.1', | ||
| port: proxy.port, | ||
| tls: { | ||
| rejectUnauthorized: false, | ||
| }, | ||
| } | ||
| const agent = new SocksProxyAgent({ ...config, protocol: 'socks5h:' }) | ||
| const url = `http://localhost:${_http.port}/path?_=${Date.now()}` | ||
| expect.assertions(1) | ||
| try { | ||
| const res = await axios.get(url, { | ||
| httpAgent: agent, | ||
| validateStatus: (status) => status >= 200 && status < 600, | ||
| }) | ||
| } catch (e) { | ||
| expect(e.message).toBeDefined() | ||
| } | ||
| }) | ||
| it('No auth', async () => { | ||
| const config = { | ||
| hostname: '127.0.0.1', | ||
| port: proxy.port, | ||
| tls: { | ||
| rejectUnauthorized: false, | ||
| }, | ||
| } | ||
| proxy.server._socksRewriteOptions = (_, callback) => { | ||
| callback({ onAuth: undefined }) | ||
| } | ||
| const agent = new SocksProxyAgent({ ...config, protocol: 'socks5h:' }) | ||
| const url = `http://localhost:${_http.port}/path?_=${Date.now()}` | ||
| const res = await axios.get(url, { | ||
| httpAgent: agent, | ||
| validateStatus: (status) => status >= 200 && status < 600, | ||
| }) | ||
| expect(res.status).toBe(200) | ||
| }) | ||
| }) |
Network access
Supply chain riskThis module accesses the network.
Found 4 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 4 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
51350
10.12%1487
2.55%115
296.55%