Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
TSocks is an implementation of the SOCKS protocol. It's designed to be very flexible and adhesive
npm install --save tscoks
or
yarn add tsocks
No matter which version of the proxy server you want V4 or V5 or even both you can easily implement it in a matter of seconds.
import { createServer } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
// Both versions with no authentication
const server = createServer({
socks4: true,
socks5: true,
})
// For development purposes
server.on('data', (data) => {
// Log incoming data
console.log(data)
})
server.on('error', (err) => {
// Log server errors
console.log(err)
})
server.listen(port, host)
There are two different authentication methods independent of which version of the SOCKS protocol you are working with. In case you are using V5, you can use the useAuth hook and use one of the available methods from the methods' directory, or if you want to create your implementations or custom methods, you have to define a function that implements the AuthMethod interface, like userPass.ts and pass it as an argument to useAuth hook, in case you are using V4 you have to use useIdent hook which receives a callback function that gives you userId, a string in which should be processed and the result, which is going to be a boolean should be returned from the callback function, in case you want to support both versions and also authenticate users on both you can use both useAuth and useIdent together.
Server socks5
import { createServer, serverAuthMethods } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const username = 'user'
const password = 'pass'
const server = createServer({
socks4: false,
socks5: true,
})
server.useAuth(
serverAuthMethods.userPass((user, pass) => {
return user === username && pass === password
})
)
server.listen(port, host)
Server socks4
import { createServer } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const id = 'user:pass'
const server = createServer({
socks4: true,
socks5: false,
})
server.useIdent((userId) => {
return userId === id
})
server.listen(port, host)
Server socks4 and SOCKS 5
import { createServer, serverAuthMethods } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const id = 'user:pass'
const username = 'user'
const password = 'pass'
const server = createServer({
socks4: true,
socks5: true,
})
// useAuth for socks5 requests
server.useAuth(
serverAuthMethods.userPass((user, pass) => {
// You can use an array or database query instead
return user === username && pass === password
})
)
// useIdent for socks4 requests
server.useIdent((userId) => {
// You can use an array or database query instead
return userId === id
})
server.listen(port, host)
The associate command assists you to send UDP packets to a remote host through the proxy server. the relay will listen for packets on the same port number as the SOCKS server does, and it doesn't support fragmentation, however, you could replace it with your implementation with the help of the useReq hook.
import { createServer } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const server = createServer({
socks4: true,
socks5: true,
})
server.useReq('associate', (info, socket) => {
const host = info.address.host
const port = info.address.port // Port number
const type = info.address.type // ipv4 | ipv6 | domain
const version = info.version // SOCKS version
// You can implement the rest however you want
// Just remember the response should be decided by version
})
server.listen(port, host)
When the bind command is sent to a SOCKS proxy server v4|v5, the proxy server starts to listen on a new TCP port and sends the relay information back to the client. When another remote client connects to the proxy server on this port the SOCKS proxy sends a notification that an incoming connection has been accepted to the initial client and a full duplex stream is now established to the initial client and the client that connected to that special port. according to the SOCKS RFC, only one inbound connection is allowed per bind request. you can easily change my implementation of the bind command with your implementation or even deactivate it with the help of the useReq hook and inform the client with a command not supported reply.
import { createServer, Reply } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const server = createServer({
socks4: true,
socks5: true,
})
server.useReq('bind', (info, socket) => {
const host = info.address.host
const port = info.address.port // Port number
const type = info.address.type // ipv4 | ipv6 | domain
const version = info.version // SOCKS version
// You can implement the rest however you want or reject the request
// With the proper reply code as below
// Remember the response should be decided by the version
let reply
if (version === 5) {
reply = new Reply(version, 0x07, info.address)
} else {
reply = new Reply(version, 0x5b, info.address)
}
socket.write(reply.toBuffer())
})
server.listen(port, host)
You may want to use the SOCKS protocol to handle incoming network traffic. so you can set up a SOCKS server and with the help of useReq hook you have access to the socket and request information which contains information like host address and port, therefore you can send traffic through a tunnel with any other protocol like WS or HTTP or whatever you want and then send the response back to the client through SOCKS.
import { createServer } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const server = createServer({
socks4: true,
socks5: true,
})
server.useReq('connect', (info, socket) => {
const host = info.address.host
const port = info.address.port // Port number
const type = info.address.type // ipv4 | ipv6 | domain
const version = info.version // SOCKS version
// You can implement the rest however you want
// Just remember the response should be decided by version
})
server.listen(port, host)
You can implement your obfuscation methods by extending your obfuscation class from the ObfsMethod class and creating a builder function for your class ObfsBuilder or use the available obfuscation methods by, passing their builder function to the useObfs hook as below:
import { createServer, obfsMethods } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const server = createServer({
socks4: true,
socks5: true,
})
server.useObfs(obfsMethods.websocket())
server.listen(port, host)
No matter which version of the proxy server you want to interact with V4 or V5 you can easily implement it in a matter of seconds.
Single connection
import { connect } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const httpPort = 80
try {
const info = await connect(port, host, 5).connect(httpPort, 'google.com')
info.socket.write(
Buffer.from(
'GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n'
)
)
info.socket.on('data', (data) => {
console.log(data)
})
} catch (err) {
console.log(err)
}
Multiple connections
import { connect } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const httpPort = 80
const client = connect(port, host, 5)
try {
const info1 = await client.connect(httpPort, 'google.com')
info1.socket.write(
Buffer.from(
'GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n'
)
)
info1.socket.on('data', (data) => {
console.log(data)
})
} catch (err) {
console.log(err)
}
try {
const info2 = await client.connect(httpPort, 'google.com')
info2.socket.write(
Buffer.from(
'GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n'
)
)
info2.socket.on('data', (data) => {
console.log(data)
})
} catch (err) {
console.log(err)
}
There are two different authentication methods independent of which version of the SOCKS protocol you are working with. In case you are using V5, you can use the useAuth hook and use one of the available methods from the methods' directory, or if you want to create your implementations or custom methods, you have to define a function that implements the AuthMethod interface, like userPass.ts and pass it as an argument to useAuth hook, in case you are using V4 you have to add your identification token as an argument (userId) to the request handler (connect | bind | associate).
Authentication socks5
import { connect, clientAuthMethods } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const username = 'user'
const password = 'pass'
const httpPort = 80
try {
const info = await connect(port, host, 5)
.useAuth(clientAuthMethods.userPass(username, password))
.connect(httpPort, 'google.com')
info.socket.write(
Buffer.from(
'GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n'
)
)
info.socket.on('data', (data) => {
console.log(data)
})
} catch (err) {
console.log(err)
}
Identification socks4
import { connect } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const userId = 'user:pass'
const httpPort = 80
try {
const info = await connect(port, host, 4, userId).connect(
httpPort,
'142.251.1.101'
)
info.socket.write(
Buffer.from(
'GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n'
)
)
info.socket.on('data', (data) => {
console.log(data)
})
} catch (err) {
console.log(err)
}
The associate command assists you to send UDP packets to a remote host through the proxy server. after sending an associate request the server will reply with the information about the relays host and port with that information, you can create a datagram socket and send your UDP packets to the address of the relay to get relayed. as you can see in the example below you have to wrap your data with the createUdpFrame and also unwrap it with parseUdpFrame as it's part of the protocol.
import {
createServer,
connect,
createUdpFrame,
parseUdpFrame,
Address,
} from 'tsocks'
import * as dgram from 'dgram'
const host = '127.0.0.1'
const port = 1080
// Create simple socks server
const server = createServer()
server.listen(port, host)
// Creates a simple echo server that returns whatever you send
const echoServerPort = 5467
const echoServer = dgram.createSocket('udp4')
echoServer.on('message', (msg, rinfo) => {
echoServer.send(msg, rinfo.port, rinfo.address)
})
echoServer.bind(echoServerPort)
try {
// Send an associate request
const info = await connect(port, host, 5).associate(0, '0.0.0.0')
const udpSocket = dgram.createSocket('udp4')
udpSocket.send(
createUdpFrame(
new Address(echoServerPort, '127.0.0.1'),
Buffer.from('Hello')
),
info.address.port,
info.address.host
)
udpSocket.once('message', (msg) => {
const parsedMsg = parseUdpFrame(msg)
console.log(parsedMsg.data.toString())
})
info.socket.on('data', (data) => {
console.log(data)
})
} catch (err) {
console.log(err)
}
When the bind command is sent to a SOCKS proxy server v4|v5, the proxy server starts to listen on a new TCP port and sends the relay information back to the client. When another remote client connects to the proxy server on this port the SOCKS proxy sends a notification that an incoming connection has been accepted to the initial client and a full duplex stream is now established to the initial client and the client that connected to that special port. according to the SOCKS RFC, only one inbound connection is allowed per bind request.
import { createServer, connect, Reply } from 'tsocks'
import * as net from 'net'
const host = '127.0.0.1'
const port = 1080
// v5 or v4
const version = 5
// Create simple socks server
const server = createServer()
server.listen(port, host)
try {
// Send a bind request
const info = await connect(port, host, version).bind(0, '0.0.0.0')
const remote = net.connect(info.address.port, info.address.host)
const states = ['information', 'relay']
let state = 0
console.log(info.address)
// The relays Address and port
// host: "143.123.35.425",
// port: 3342,
// type: "ipv4",
info.socket.on('data', (data) => {
switch (states[state]) {
case states[1]:
console.log(data.toString())
remote.destroy()
info.socket.destroy()
break
default:
const reply = Reply.from(data)
console.log(reply.addr)
// The remote address of the client that connected to the SOCKS proxy
//host: "122.153.15.225",
//port: 4562,
//type: "ipv4",
remote.write(Buffer.from('Hello'))
state++
}
})
} catch (err) {
console.log(err)
}
You can implement your obfuscation methods by extending your obfuscation class from the ObfsMethod class and creating a builder function for your class ObfsBuilder or use the available obfuscation methods by, passing their builder function to the useObfs hook as below:
import { connect, obfsMethods } from 'tsocks'
const host = '127.0.0.1'
const port = 1080
const httpPort = 80
try {
const info = await connect(port, host, 5)
.useObfs(obfsMethods.websocket())
.connect(httpPort, 'google.com')
// remember to use the obfuscate method before sending your data to the
// SOCKS server and deObfuscate methods when you receive any data from the
// SOCKS server when you are using an obfuscation method
info.socket.write(
info.obfs.obfuscate(
Buffer.from(
'GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n'
)
)
)
info.socket.on('data', (data) => {
console.log(info.obfs.deObfuscate(data).toString())
info.socket.end()
})
} catch (err) {
console.log(err)
}
Email : moizadloo@gmail.com
FAQs
SOCKS protocol in typescript
The npm package tsocks receives a total of 16 weekly downloads. As such, tsocks popularity was classified as not popular.
We found that tsocks demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers 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.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.