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

socks4

v0.1.1

Published

SOCKS4/a server which extends net.Server. It has a simple interface that allows you to inspect, log, and manipulate traffic before forwarding to the client.

Downloads

716

Readme

Socks4

Install

npm install socks4

Introduction

This is a SOCKS4/a server implementation, it extends net.server so will have a familiar interface. The most basic example is:

var socks4 = require('socks4');

socks4.createServer().listen(1080);

The above example creates a very simple server listening on port 1080, all traffic will be forwarded directly to the client.

Of course it's possible to create more advanced servers, allowing you to inspect, log, and manipulate traffic before forwarding it onto the client, continue reading to find out how...

Events

  • connect: The client has issued a CONNECT command
  • connection The client has issued any command

Note - The server does not currently support the BIND command, this means that the 2 events above are equivelant. In the future there will also be a bind event for BIND commands.

SocksRequest object

All events are emitted with a single argument, an instance of the SocksRequest class (req). This object has properties pertaining to the details of the request, and provides access to the raw socket connection.

Properties:

  • req.host: The hostname requested by the client, either an IPv4 or domain name
  • req.port: The port requested by the client
  • req.socket: The raw socket connection
  • req.version: The SOCKS protocol version, will always = 4

Methods:

  • req.accept(): Accept the clients request
  • req.reject(reason): Reject the clients request and terminate the socket. Optionally supply a valid reason, see the constants in socks4.protocol.status

Note - The request can only be accepted or rejected once, if you call either of these functions more than once then an error will be emitted.

Events:

  • end: Emitted when the client's socket is closed. It is always emitted

Properties & Methods

Remember that socks4.Server extends net.Server so will have all the same properties and methods, including listen() and maxConnections. The server only has one method of its own...

server.proxyRequest(req, direct = true): This is a convenience method, it simply makes the connection to the remote host (as requested by the client), and forwards the response directly to the client.

  • req: The request object, instance of SocksRequest
  • [direct]: Pipe the response directly to the client's socket? Defaults to true.

Returns net.Socket, the socket to the remote server (not the client).

If no event listeners are added to the server, then this method is called automatically, that's how the introduction example works.

This method will call req.accept() if it has not been called already.

Examples

In the introduction example we created a very basic server, because we didn't add any event listeners, the clients request was automatically accepted and satisfied.

Once you add listeners to the connect or connection events then it will be your responsibilty to satisfy the client and proxy the request. To do this call req.accept() and then send some data to the client's socket.

Only allow connections from one IP address:

var socks4 = require('socks4');
var server = socks4.createServer();

server.on('connect', function(req){
    if(req.socket.remoteAddress == '192.168.0.5'){
        req.accept();
        server.proxyRequest(req);
    }
    else{
        req.reject();
    }
});

server.listen(1080);

If the client's IP is 192.168.0.5, then the request is accepted. server.proxyRequest() is a convenience method, it simply makes a connection to the remote host (as requested by the client) and then forwards it on.

Modify data before forwarding it:

var socks4 = require('socks4');
var server = socks4.createServer();

server.on('connect', function(req){
    var remote = server.proxyRequest(req, false);

    req.socket.pipe(remote);

    remote.on('data', function(buffer){
        var text = buffer.toString();

        text = text.replace('<h1>', '<h1>Hello World</h1>');
        req.socket.write(text);
    });
});

server.listen(1080);

In this example we replace the H1 tag with "Hello World". server.proxyRequest() returns the socket of the remote host, and can be prevented from directly forwarding the response by passing false as the 2nd argument.

The code pipes the clients request to the remote server, then listens for incoming data from the remote host, this data is first altered before forwarding to the client.

Of course the above code is full of problems, for a start it would only work with HTTP traffic, and would completely break all binary data. If you really want to do something like this, you should write better code with some checks.

Send the client something different

var socks4 = require('socks4');
var net = require('net');

var server = socks4.createServer();

server.on('connect', function(req){
    req.accept();
    var remote = net.connect(80, 'www.example.com', function(){
        remote.pipe(req.socket);
    });

    var http = 'GET / HTTP/1.1\r\n' +
               'Host: www.example.com\r\n\r\n';

    remote.write(http);
});

server.listen(1080);

In this example, instead of following the clients request, the server will always serve the homepage of example.com. It's possible to send any data you like to the client, just write it to req.socket. You don't always need to call server.proxyRequest(), it's just there for your convenience.

Once again, this example is full of problems, for a start you should at least check that the client is making an HTTP request, and perhaps that the port is 80. If the client is requesting anything other than HTTP, the response would just appear garbled to them.

Error Handling

  • socks4.Server will emit the same errors as net.Server
  • SocksRequest will emit errors from the client's socket

All errors are emitted not thrown.

Warnings

If you're setting up a public proxy, then you will have a security issue to overcome. Considder the following:

require('socks4').createServer().listen(1080);

This code will blindly accept and follow any request, including your LAN. Anything your server has access to, the client will have access to aswell. You can overcome this problem by checking req.host before accepting the request.

You may think you have nothing of interest on your LAN, and that this problem doesn't apply to you, however, one example could be clients issuing requests to 127.0.0.1, they could attack your server from within.

TODO

  • BIND command implementation
  • Ident authentication - http://www.ietf.org/rfc/rfc1413.txt