Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add intrinsic support for SOCKS proxies #1966

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ The arguments are:
CONNACK is received
- `username`: the username required by your broker, if any
- `password`: the password required by your broker, if any
- `socksProxy`: establish TCP and TLS connections via a socks proxy (URL, supported protocols are `socks5://`, `socks5h://`, `socks4://`, `socks4a://`)
- `socksTimeout`: timeout for connecting to the socks proxy
- `incomingStore`: a [Store](#store) for the incoming packets
- `outgoingStore`: a [Store](#store) for the outgoing packets
- `queueQoSZero`: if connection is broken, queue outgoing QoS zero messages (default `true`)
Expand Down Expand Up @@ -485,6 +487,8 @@ The arguments are:
- `forceNativeWebSocket`: set to true if you're having detection issues (i.e. the `ws does not work in the browser` exception) to force the use of native WebSocket. It is important to note that if set to true for the first client created, then all the clients will use native WebSocket. And conversely, if not set or set to false, all will use the detection result.
- `unixSocket`: if you want to connect to a unix socket, set this to true

Instead of setting `socksProxy` you can also supple the same parameter via the environment variable `MQTTJS_SOCKS_PROXY`.

In case mqtts (mqtt over tls) is required, the `options` object is passed through to [`tls.connect()`](http://nodejs.org/api/tls.html#tls_tls_connect_options_callback). If using a **self-signed certificate**, set `rejectUnauthorized: false`. However, be cautious as this exposes you to potential man in the middle attacks and isn't recommended for production.

For those supporting multiple TLS protocols on a single port, like MQTTS and MQTT over WSS, utilize the `ALPNProtocols` option. This lets you define the Application Layer Protocol Negotiation (ALPN) protocol. You can set `ALPNProtocols` as a string array, Buffer, or Uint8Array based on your setup.
Expand Down
20 changes: 20 additions & 0 deletions esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,26 @@ const options = {
)
}
},
{
name: 'resolve-socks',
setup(build) {
// socks is not supported in the browser and adds several 100kb to the build, so stub it
build.onResolve({ filter: /socks$/ }, args => {
return {
path: args.path,
namespace: 'socks-stub'
}
})

build.onLoad({ filter: /.*/, namespace: 'socks-stub' }, args => {
return {
contents: 'module.exports = {}',
loader: 'js'
}
}
)
}
},
],
}

Expand Down
36 changes: 14 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
"readable-stream": "^4.7.0",
"reinterval": "^1.1.0",
"rfdc": "^1.4.1",
"socks": "^2.8.3",
"split2": "^4.2.0",
"worker-timers": "^7.1.8",
"ws": "^8.18.0"
Expand Down
4 changes: 4 additions & 0 deletions src/lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ export interface IClientOptions extends ISecureClientOptions {
query?: Record<string, string>
/** Auth string in the format <username>:<password> */
auth?: string
/** Optional SOCKS proxy to use for TCP / TLS connections , i.e. socks5://localhost:1333, socks4://localhost:1333, socks5h://localhost:1333 . Default is socks5h. */
socksProxy?: string
/** Timeout for establishing a socks connection */
socksTimeout?: number
/** Custom ack handler */
customHandleAcks?: AckHandler
/** Broker port */
Expand Down
9 changes: 9 additions & 0 deletions src/lib/connect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ function connect(
opts.clientId = opts.query.clientId
}

if (isBrowser || opts.unixSocket) {
opts.socksProxy = undefined
} else if (
opts.socksProxy === undefined &&
typeof process !== 'undefined'
) {
opts.socksProxy = process.env['MQTTJS_SOCKS_PROXY']
}

if (opts.cert && opts.key) {
if (opts.protocol) {
if (['mqtts', 'wss', 'wxs', 'alis'].indexOf(opts.protocol) === -1) {
Expand Down
Loading