Socks5ProxyAgent.md 8.6 KB

Class: Socks5ProxyAgent

Extends: undici.Dispatcher

A SOCKS5 proxy wrapper class that implements the Dispatcher API. It enables HTTP requests to be routed through a SOCKS5 proxy server, providing connection tunneling and authentication support.

new Socks5ProxyAgent(proxyUrl[, options])

Arguments:

  • proxyUrl string | URL (required) - The SOCKS5 proxy server URL. Must use socks5:// or socks:// protocol.
  • options Socks5ProxyAgent.Options (optional) - Additional configuration options.

Returns: Socks5ProxyAgent

Parameter: Socks5ProxyAgent.Options

Extends: PoolOptions

  • headers IncomingHttpHeaders (optional) - Additional headers to send with proxy connections.
  • username string (optional) - SOCKS5 proxy username for authentication. Can also be provided in the proxy URL.
  • password string (optional) - SOCKS5 proxy password for authentication. Can also be provided in the proxy URL.
  • connect Function (optional) - Custom connector function for the proxy connection.
  • proxyTls BuildOptions (optional) - TLS options for the proxy connection (when using SOCKS5 over TLS).
  • requestTls BuildOptions (optional) - TLS options applied to the HTTPS connection to the target server through the SOCKS5 tunnel. Use this to configure ca, cert, key, rejectUnauthorized, servername, etc. for the target HTTPS endpoint.

Examples:

import { Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')
// or with authentication
const socks5ProxyWithAuth = new Socks5ProxyAgent('socks5://user:pass@localhost:1080')
// or with options
const socks5ProxyWithOptions = new Socks5ProxyAgent('socks5://localhost:1080', {
  username: 'user',
  password: 'pass',
  connections: 10
})

Example - Basic SOCKS5 Proxy instantiation

This will instantiate the Socks5ProxyAgent. It will not do anything until registered as the dispatcher to use with requests.

import { Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

Example - Basic SOCKS5 Proxy Request with global dispatcher

import { setGlobalDispatcher, request, Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')
setGlobalDispatcher(socks5Proxy)

const { statusCode, body } = await request('http://localhost:3000/foo')

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}

Example - Basic SOCKS5 Proxy Request with local dispatcher

import { Socks5ProxyAgent, request } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

const {
  statusCode,
  body
} = await request('http://localhost:3000/foo', { dispatcher: socks5Proxy })

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}

Example - SOCKS5 Proxy Request with authentication

import { setGlobalDispatcher, request, Socks5ProxyAgent } from 'undici'

// Authentication via URL
const socks5Proxy = new Socks5ProxyAgent('socks5://username:password@localhost:1080')

// Or authentication via options
// const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080', {
//   username: 'username',
//   password: 'password'
// })

setGlobalDispatcher(socks5Proxy)

const { statusCode, body } = await request('http://localhost:3000/foo')

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}

Example - SOCKS5 Proxy with HTTPS requests

SOCKS5 proxy supports both HTTP and HTTPS requests through tunneling:

import { Socks5ProxyAgent, request } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

const response = await request('https://api.example.com/data', {
  dispatcher: socks5Proxy,
  method: 'GET'
})

console.log('Response status:', response.statusCode)
console.log('Response data:', await response.body.json())

Example - SOCKS5 Proxy with Fetch

import { Socks5ProxyAgent, fetch } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

const response = await fetch('http://localhost:3000/api/users', {
  dispatcher: socks5Proxy,
  method: 'GET'
})

console.log('Response status:', response.status)
console.log('Response data:', await response.text())

Example - Connection Pooling

SOCKS5ProxyWrapper automatically manages connection pooling for better performance:

import { Socks5ProxyAgent, request } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080', {
  connections: 10, // Allow up to 10 concurrent connections
  pipelining: 1    // Enable HTTP/1.1 pipelining
})

// Multiple requests will reuse connections through the SOCKS5 tunnel
const responses = await Promise.all([
  request('http://api.example.com/endpoint1', { dispatcher: socks5Proxy }),
  request('http://api.example.com/endpoint2', { dispatcher: socks5Proxy }),
  request('http://api.example.com/endpoint3', { dispatcher: socks5Proxy })
])

console.log('All requests completed through the same SOCKS5 proxy')

Socks5ProxyAgent.close()

Closes the SOCKS5 proxy wrapper and waits for all underlying pools and connections to close before resolving.

Returns: Promise<void>

Example - clean up after tests are complete

import { Socks5ProxyAgent, setGlobalDispatcher } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')
setGlobalDispatcher(socks5Proxy)

// ... make requests

await socks5Proxy.close()

Socks5ProxyAgent.destroy([err])

Destroys the SOCKS5 proxy wrapper and all underlying connections immediately.

Arguments:

  • err Error (optional) - The error that caused the destruction.

Returns: Promise<void>

Example - force close all connections

import { Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

// Force close all connections
await socks5Proxy.destroy()

Socks5ProxyAgent.dispatch(options, handlers)

Implements Dispatcher.dispatch(options, handlers).

Socks5ProxyAgent.request(options[, callback])

See Dispatcher.request(options [, callback]).

Debugging

SOCKS5 proxy connections can be debugged using Node.js diagnostics:

NODE_DEBUG=undici:socks5 node script.js

This will output detailed information about the SOCKS5 handshake, authentication, and connection establishment.

SOCKS5 Protocol Support

The Socks5ProxyAgent supports the following SOCKS5 features:

Authentication Methods

  • No Authentication (0x00) - For public or internal proxies
  • Username/Password (0x02) - RFC 1929 authentication

Address Types

  • IPv4 (0x01) - Standard IPv4 addresses
  • Domain Name (0x03) - Domain names (recommended for flexibility)
  • IPv6 (0x04) - IPv6 addresses (full support for standard and compressed notation)

Commands

  • CONNECT (0x01) - Establish TCP connection (primary use case for HTTP)

Error Handling

The wrapper handles various SOCKS5 error conditions:

  • Connection refused by proxy
  • Authentication failures
  • Network unreachable
  • Host unreachable
  • Unsupported address types or commands

Performance Considerations

  • Connection Pooling: Automatically pools connections through the SOCKS5 tunnel for better performance
  • HTTP/1.1 Pipelining: Supports pipelining when enabled
  • DNS Resolution: Domain names are resolved by the SOCKS5 proxy, reducing local DNS queries
  • TLS Termination: HTTPS connections are encrypted end-to-end, with the SOCKS5 proxy only handling the TCP tunnel

Security Notes

  1. Authentication: Credentials are sent to the SOCKS5 proxy in plaintext unless using SOCKS5 over TLS
  2. DNS Leaks: All DNS resolution happens on the proxy server, preventing DNS leaks
  3. End-to-end Encryption: HTTPS traffic remains encrypted between client and final destination
  4. Connection Security: Consider using authenticated proxies and secure networks

Compatibility

  • Protocol: SOCKS5 (RFC 1928) with Username/Password Authentication (RFC 1929)
  • Transport: TCP only (UDP support not implemented)
  • Node.js: Compatible with all supported Node.js versions
  • HTTP Versions: Works with HTTP/1.1 and HTTP/2 over the tunnel