socks
Fully featured SOCKS proxy client supporting SOCKSv4, SOCKSv4a, and SOCKSv5. Includes Bind and Associate functionality.
Highlights
- Supports SOCKS 4, 4a, and 5 protocols.
- Supports the CONNECT, BIND, and ASSOCIATE commands.
- Supports callbacks, promises, and events for proxy connection creation flows.
- Supports Proxy chaining (CONNECT only).
- Built in UDP frame creationg & parsing methods.
- Built in TypeScript, typings are provided.
Installing:
yarn add socks
or
npm install socks
Getting Started Example
For this example, say you wanted to grab the html of google's home page.
var Socks = require('socks');
var options = {
proxy: {
ipaddress: "202.101.228.108",
port: 1080,
type: 5
},
target: {
host: "google.com",
port: 80
},
command: 'connect'
};
Socks.createConnection(options, function(err, socket, info) {
if (err)
console.log(err);
else {
socket.write("GET / HTTP/1.1\nHost: google.com\n\n");
socket.on('data', function(data) {
console.log(data.length);
console.log(data);
});
socket.resume();
}
});
BIND Example:
When sending the BIND command to a SOCKS proxy server, this will cause the proxy server to open up a new tcp port. Once this port is open, you, another client, application, etc, can then connect to the SOCKS proxy on that tcp port and communications will be forwarded to each connection through the proxy itself.
var options = {
proxy: {
ipaddress: "202.101.228.108",
port: 1080,
type: 4,
command: "bind"
},
target: {
host: "1.2.3.4",
port: 1080
}
};
Socks.createConnection(options, function(err, socket, info) {
if (err)
console.log(err);
else {
console.log(info);
socket.on('data', function(data) {
console.log(data.length);
console.log(data);
});
socket.resume();
}
});
At this point, your original connection to the proxy server remains open, and no data will be received until a tcp connection is made to the given endpoint in the info object.
For an example, I am going to connect to the endpoint with telnet:
Joshs-MacBook-Pro:~ Josh$ telnet 202.101.228.108 1494
Trying 202.101.228.108...
Connected to 202.101.228.108.
Escape character is '^]'.
hello
aaaaaaaaa
Note that this connection to the newly bound port does not need to go through the SOCKS handshake.
Back at our original connection we see that we have received some new data:
8
<Buffer 00 5a ca 61 43 a8 09 01> // This first piece of information can be ignored.
7
<Buffer 68 65 6c 6c 6f 0d 0a> // Hello <\r\n (enter key)>
11
<Buffer 61 61 61 61 61 61 61 61 61 0d 0a> // aaaaaaaaa <\r\n (enter key)>
As you can see the data entered in the telnet terminal is routed through the SOCKS proxy and back to the original connection that was made to the proxy.
Note Please pay close attention to the first piece of data that was received.
<Buffer 00 5a ca 61 43 a8 09 01>
[005a] [PORT:2} [IP:4]
This piece of data is technically part of the SOCKS BIND specifications, but because of my design decisions that were made in an effort to keep this library simple to use, you will need to make sure to ignore and/or deal with this initial packet that is received when a connection is made to the newly opened port.
Associate Example:
The associate command sets up a UDP relay for the remote SOCKS proxy server to relay UDP packets to the remote host of your choice.
var options = {
proxy: {
ipaddress: "202.101.228.108",
port: 1080,
type: 5,
command: "associate"
},
target: {
host: "0.0.0.0",
port: 0
}
};
Socks.createConnection(options, function(err, socket, info) {
if (err)
console.log(err);
else {
console.log(info);
var udp = new dgram.Socket('udp4');
var pack = Socks.createUDPFrame({ host: "1.2.3.4", port: 2323}, new Buffer("hello"));
udp.send(pack, 0, pack.length, info.port, info.host);
}
});
Now assuming that the associate request went through correctly. Anything that is typed in the stdin will first be sent to the SOCKS proxy on the endpoint that was provided in the info object. Once the SOCKS proxy receives it, it will then forward on the actual UDP packet to the host you you wanted.
1.2.3.4:2323 should now receive our relayed UDP packet from 202.101.228.108 (SOCKS proxy)
// <Buffer 68 65 6c 6c 6f>
Using socks as an HTTP Agent
You can use socks as a http agent which will relay all your http
connections through the socks server.
The object that Socks.Agent
accepts is the same as Socks.createConnection
, you don't need to set a target since you have to define it in http.request
or http.get
methods.
The second argument is a boolean which indicates whether the remote endpoint requires TLS.
var socksAgent = new Socks.Agent({
proxy: {
ipaddress: "202.101.228.108",
port: 1080,
type: 5,
}},
true,
false
);
http.get({ hostname: 'google.com', port: '443', agent: socksAgent}, function (res) {
socksAgent.encryptedSocket.end();
});
Api Reference:
There are only three exported functions that you will ever need to use.
Socks.createConnection( options, callback(err, socket, info) )
Object
Object containing options to use when creating this connection
function
Callback that is called when connection completes or errors
Options:
var options = {
proxy: {
ipaddress: "1.2.3.4",
port: 1080,
type: 4,
command: "connect",
userid: "someuserid",
authentication: {
username: "Josh",
password: "somepassword"
}
},
target: {
host: "1.2.3.4",
port: 1080
},
timeout: 10000
};
Callback:
function(err, socket, info) {
}
Socks.createUDPFrame( target, data, [frame] )
Object
Target host object containing destination for UDP packet
Buffer
Data Buffer to send in the UDP packet
Number
Frame number in UDP packet. (defaults to 0)
Creates a UDP packet frame for using with UDP association relays.
returns Buffer
The completed UDP packet container to be sent to the proxy for forwarding.
target:
var target =
{
host: "1.2.3.4",
port: 2323
}
Socks.Agent( options, tls) )
Object
Object containing options to use when creating this connection (see above in createConnection)
boolean
Boolean indicating if we upgrade the connection to TLS on the socks server
Further Reading:
Please read the SOCKS 5 specifications for more information on how to use BIND and Associate.
http://www.ietf.org/rfc/rfc1928.txt
License
This work is licensed under the MIT license.