npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

simple-socks

v3.1.0

Published

proxies requests

Downloads

2,819

Readme

Simple Socks Server

Creates a simple SOCKS5 server and exposes additional SOCKS5 proxy events.

Build Status

Installation

npm install simple-socks

Example Usage

In the examples folder exists two examples, one that requires no authentication and one that requires username/password authentication. Below is an example with no authentication:

import socks5 from 'simple-socks'

const server = socks5.createServer().listen(1080);

// When a reqest arrives for a remote destination
server.on('proxyConnect', (info, destination) => {
  console.log('connected to remote server at %s:%d', info.address, info.port);

  destination.on('data', (data) => {
    console.log(data.length);
  });
});

// When data arrives from the remote connection
server.on('proxyData', (data) => {
  console.log(data.length);
});

// When an error occurs connecting to remote destination
server.on('proxyError', (err) => {
  console.error('unable to connect to remote server');
  console.error(err);
});

// When a request for a remote destination ends
server.on('proxyDisconnect', (originInfo, destinationInfo, hadError) => {
  console.log(
    'client %s:%d request has disconnected from remote server at %s:%d with %serror',
    originInfo.address,
    originInfo.port,
    destinationInfo.address,
    destinationInfo.port,
    hadError ? '' : 'no ');
});

// When a proxy connection ends
server.on('proxyEnd', (response, args) => {
  console.log('socket closed with code %d', response);
  console.log(args);
});

Running The Examples

No Authentication

For a SOCKS5 server that does not require authentication, look at examples/createServer.js:

node examples/createServer

In a separate terminal window:

curl http://www.google.com --socks5 127.0.0.1:1080

Username/Password Authentication

For a SOCKS5 server that requires username/password authentication, look at examples/createServerWithAuthentication.js:

node examples/createServerWithAuthentication

In a separate terminal window:

curl http://www.google.com --socks5 127.0.0.1:1080 --proxy-user foo:bar

Connection Filter

For a SOCKS5 server that can perform either origin or destination (or both!) address filtering, look at examples/createServerConnectionFilter.js:

node examples/createServerConnectionFilter

In a separate terminal window:

curl http://www.github.com --socks5 127.0.0.1:1080 # allowed
curl http://www.google.com --socks5 127.0.0.1:1080 # denied

Methods

createServer

Factory method that creates an instance of a SOCKS5 proxy server:

import socks5 from 'simple-socks';

const server = socks5.createServer();

server.listen(1080, '0.0.0.0', function () {
  console.log('SOCKS5 proxy server started on 0.0.0.0:1080');
});

This method accepts an optional options argument:

  • options.authentication - A callback for authentication
  • options.connectionFilter - A callback for connection filtering

authentication

To make the socks5 server require username/password authentication, supply a function callback in the options as follows:

import socks5 from 'simple-socks';

const options = {
  authenticate : function (username, password, socket, callback) {
    if (username === 'foo' && password === 'bar') {
      return setImmediate(callback);
    }

    return setImmediate(callback, new Error('incorrect username and password'));
  }
};

const server = socks5.createServer(options);

// begin listening and require user/pass authentication
server.listen(1080);

The authenticate callback accepts three arguments:

  • username - username of the proxy user
  • password - password of the proxy user
  • socket - the socket for the client connection
  • callback - callback for authentication... if authentication is successful, the callback should be called with no arguments

connectionFilter

Allows you to filter incoming connections, based on either origin and/or destination, return false to disallow:

import socks5 from 'simple-socks';

const server = socks5.createServer({
  connectionFilter : function (destination, origin, callback) {
    if (origin.address === '127.0.0.1') {
      console.log('denying access from %s:%s', origin.address, origin.port);

      return setImmediate(callback, new Error('access from specified origin is denied'));
    }

    if (destination.address === '10.0.0.1') {
      console.log('denying access to %s:%s', remote.address, remote.port);

      return setImmediate(callback, new Error('access to specified destination is denied'));
    }

    return setImmediate(callback);
  }
});

The connectionFilter callback accepts three arguments:

  • destination - an information object containing details for destination connection
    • address - the TCP address of the remote server
    • port - the TCP port of the remote server
  • origin - an information object containing details for origin connection
    • address - the TCP address of the origin (client) connection
    • port - the TCP port of the origin (client) connection
  • callback - callback for destination and/or origin address validation... if connections are allowed to the destination address, the callback should be called with no arguments

For an example, see examples/createServerConnectionFilter.js.

Events

The socks5 server supports all events that exist on a native net.Server object. Additionally, the following events have been added that are specific to the SOCKS5 proxy:

  • handshake - The first event fired and it occurs when a new SOCKS5 client proxy negotiation occurs
  • authenticate - When username/password authentication is configured (see above), this event is fired when a successful authentication occurs
  • authenticateError - When username/password authentication is configured, this event is fired when authentication fails
  • connectionFilter - When a destination address is denied by the configured connection filter callback, this event is fired
  • proxyConnect - After handshake and optional authentication, this event is emitted upon successful connection with the remote destination
  • proxyError - If connection to the remote destination fails, this event is emitted
  • proxyDisconnect - If a successful proxyConnect occurs, this event is emitted when the remote destination ends the connection
  • proxyData - When data is recieved from the remote destination, this event is fired
  • proxyEnd - This event is emitted when the SOCKS5 client connection is closed for any reason

Note:

This module exports the above events as constants for convenience purposes via the property events:

console.log(socks5.events);

Outputs the following:

{ AUTHENTICATION: 'authenticate',
  AUTHENTICATION_ERROR: 'authenticateError',
  CONNECTION_FILTER: 'connectionFilter',
  HANDSHAKE: 'handshake',
  PROXY_CONNECT: 'proxyConnect',
  PROXY_DATA: 'proxyData',
  PROXY_DISCONNECT: 'proxyDisconnect',
  PROXY_END: 'proxyEnd',
  PROXY_ERROR: 'proxyError' }

handshake

This is event is emitted when a socks5 client connects to the server. The callback accepts a single argument:

// When a new request is initiated
server.on('handshake', function (socket) {
  console.log('new socks5 client from %s:%d', socket.remoteAddress, socket.remotePort);
});

authenticate

This event is emitted when successful authentication occurs. The callback accepts a single argument:

  • username - the username of the successfully authenticated SOCKS5 proxy user
// When authentication succeeds
server.on('authenticate', function (username) {
  console.log('user %s successfully authenticated!', username);
});

authenticateError

This event is emitted when authentication is not successful. The callback accepts the following arguments:

  • username - the username of the SOCKS5 proxy user
  • err - the error returned to the options.authenticate callback
// When authentication fails
server.on('authenticateError', function (username, err) {
  console.log('user %s failed to authenticate...', username);
  console.error(err);
});

connectionFilter

This event is emitted when a destination address and port is filtered by the connectionFilter callback. The callback accepts the following arguments:

  • destination - an information object containing details for destination connection
    • address - the TCP address of the remote server
    • port - the TCP port of the remote server
  • origin - an information object containing details for origin connection
    • address - the TCP address of the origin (client) connection
    • port - the TCP port of the origin (client) connection
  • err - the error returned to the options.connectionFilter callback
// When a destination connection is filtered
server.on('connectionFilter', function (port, address, err) {
  console.log('connection to %s:%s has been denied', address, port);
  console.error(err);
});

proxyConnect

This event is emitted each time a connection is requested to a remote destination. The callback accepts two arguments:

  • info - object with two fields
    • address - the TCP address of the remote (destination) server
    • port - the TCP port of the remote (destination) server
  • destination - the destination TCP net.Socket
// When a reqest arrives for a remote destination
server.on('proxyConnect', function (info, destination) {
  console.log('connected to remote server at %s:%d', info.address, info.port);
});

proxyData

This event is emitted each time a remote connection returns data:

// When a reqest arrives for a remote destination
server.on('proxyData', function (data) {
  console.log('data received from remote destination: %d', data.length);
});

Note: This can also be accomplished by listening to the data event on the destination connection received in the proxyConnect event:

// When a reqest arrives for a remote destination
server.on('proxyConnect', function (info, destination) {
  destination.on('data', function (data) {
    console.log('data received from remote destination: %d', data.length);
  });
});

proxyDisconnect

This event is emitted after a proxyConnect when a connection to a remote destination has ended. The callback accepts three arguments:

  • originInfo - object with two fields
    • address - the TCP address of the origin of the request
    • port - the TCP port of the origin of the request
  • destinationInfo - object with two fields
    • address - the TCP address of the remote (destination) server
    • port the TCP port of the remote (destination) server
  • hadError - a Boolean indicating if a transmission error occurred after connecting with the remote (destination) server
// When a request for a remote destination ends
server.on('proxyDisconnect', function (err) {
  console.log(
    'client %s:%d request has disconnected from remote server at %s:%d with %serror',
    originInfo.address,
    originInfo.port,
    destinationInfo.address,
    destinationInfo.port,
    hadError ? '' : 'no ');
});

proxyError

In the event that a network error occurs attempting to create communication with the destination, this event is raised.

// When an error occurs connecting to remote destination
server.on('proxyError', function (err) {
  console.error('unable to connect to remote server');
  console.error(err);
});

proxyEnd

When a socket connection is closed by the server, the proxyEnd event is emitted. It returns two arguments in the callback:

  • response - the specific RFC 1928 documented response code
  • args - RFC 1928 fields for the proxy request including
    • ver
    • cmd
    • atype
    • dst.addr
    • dst.port
// When a proxy connection ends
server.on('proxyEnd', function (response, args) {
  console.log('socket closed with code %d', response);
  console.log(args);
});