
Security News
GitHub Actions Pricing Whiplash: Self-Hosted Actions Billing Change Postponed
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.
simple-socks
Advanced tools
Creates a simple SOCKS5 server and exposes additional SOCKS5 proxy events.
npm install simple-socks
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);
});
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
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
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
For running multiple SOCKS5 servers on the same port, but bound to different interfaces, look at examples/createMultipleServers.js:
node examples/createMultipleServers
To run a SOCKS5 server that authenticates via GSSAPI/Negotiate using a minimal provider backed by the kerberos module:
Prerequisites:
npm install kerberosrcmd/<hostname>@REALM) and a keytab is accessible to the process.Run the example:
node examples/createServerWithGssapi
Client test (example with curl):
curl --socks5 127.0.0.1:1080 \
--socks5-gssapi \
--socks5-gssapi-service rcmd \
https://example.com
Provider reference: examples/gssapiKerberosProvider.js.
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 authenticationoptions.connectionFilter - A callback for connection filteringoptions.idleTimeout - Milliseconds of inactivity before destroying client/destination sockets (0 is disabled, default 0)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:
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:
For an example, see examples/createServerConnectionFilter.js.
If your machine has multiple IP addresses and you want a separate SOCKS5 server bound to each one, create a server per interface and bind explicitly using the object form of listen with exclusive: true:
import socks5 from 'simple-socks';
const hosts = ['10.0.0.1', '10.0.0.2', '10.0.0.3'];
const port = 1080;
hosts.forEach((host) => {
const server = socks5.createServer();
server.on('listening', () => {
const addr = server.address();
// should show the specific host, not 0.0.0.0
console.log('listening on %s:%d', addr.address, addr.port);
});
// Force an interface-specific, exclusive bind
server.listen({ port, host, exclusive: true });
});
Notes:
host (e.g., server.listen(1080)), Node binds to 0.0.0.0 and that listener will accept connections for all interfaces.listen(port, host, cb) and to set exclusive: true when running multiple listeners on the same port.server.address() after the listening event.See also: examples/createMultipleServers.js.
This library can be configured to prefer GSSAPI/Negotiate (RFC 1961) when a provider is supplied. This callback allows code to delegate the GSS exchange to a pluggable provider and, upon success, proceeds without wrapping subsequent data (auth-only).
Enable GSSAPI by supplying a gssapi option with a provider implementing authenticate(socket, firstChunk, callback):
import socks5 from 'simple-socks';
const server = socks5.createServer({
gssapi: {
enabled: true,
provider: {
authenticate(socket, firstChunk, callback) {
// Implement RFC 1961 token exchange here.
// Use system GSS libraries via your integration and call callback(err, principal)
// on success with the authenticated principal string.
callback(new Error('GSSAPI provider not implemented'));
}
}
}
});
server.listen(1080);
Notes:
gssapi.enabled is true, a provider is present, and the client offers method 0x01 (GSSAPI) during negotiation.authenticate event with the principal name.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:
proxyConnect occurs, this event is emitted when the remote destination ends the connectionNote:
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' }
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);
});
This event is emitted when successful authentication occurs. The callback accepts a single argument:
// When authentication succeeds
server.on('authenticate', function (username) {
console.log('user %s successfully authenticated!', username);
});
This event is emitted when authentication is not successful. The callback accepts the following arguments:
options.authenticate callback// When authentication fails
server.on('authenticateError', function (username, err) {
console.log('user %s failed to authenticate...', username);
console.error(err);
});
This event is emitted when a destination address and port is filtered by the connectionFilter callback. The callback accepts the following arguments:
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);
});
This event is emitted each time a connection is requested to a remote destination. The callback accepts two arguments:
// 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);
});
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);
});
});
This event is emitted after a proxyConnect when a connection to a remote destination has ended. The callback accepts three arguments:
// 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 ');
});
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);
});
When a socket connection is closed by the server, the proxyEnd event is emitted. It returns two arguments in the callback:
vercmdatypedst.addrdst.port// When a proxy connection ends
server.on('proxyEnd', function (response, args) {
console.log('socket closed with code %d', response);
console.log(args);
});
Some versions of the macOS built‑in SOCKS client (used when enabling a SOCKS proxy in Network settings) do not correctly implement RFC 1929 username/password authentication. They may not advertise BASIC (0x02) during method negotiation, or send a zero‑length password during the RFC 1929 sub‑negotiation.
authenticate is configured but the client does not offer BASIC, the server responds with “no acceptable methods” and closes.If you require username/password auth from macOS clients, use a client that supports RFC 1929 (for example, curl --socks5 --proxy-user, or browsers/extensions that implement SOCKS5 BASIC). Alternatively, consider a different method such as GSSAPI/Negotiate on both client and server; the built‑in macOS client may favor that, but it is not implemented by this library.
FAQs
proxies requests
The npm package simple-socks receives a total of 351 weekly downloads. As such, simple-socks popularity was classified as not popular.
We found that simple-socks demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.