Skip to content

Commit

Permalink
🐛 fix: Fix a few bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
MoIzadloo committed Apr 19, 2023
1 parent 6660b34 commit a27e5a9
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 29 deletions.
73 changes: 68 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# TSocks

TSocks is an implementation of SOCKS protocol.
TSocks is an implementation of the SOCKS protocol.
It's designed to be very flexible and adhesive

- **Modular** to be suited to your needs
Expand All @@ -13,8 +13,8 @@ It's designed to be very flexible and adhesive
# Pros

1. TSocks is powered with hooks and events which give you
the ability to implement different parts of protocol yourself
2. We used an API similar to the [net](https://nodejs.org/api/net.html) module which you are propably familiar with
the ability to implement different parts of the protocol yourself
2. We used an API similar to the [net](https://nodejs.org/api/net.html) module which you are probably familiar with
3. You have access to incoming connections socket through available hooks

## Install
Expand Down Expand Up @@ -176,7 +176,7 @@ server.useReq('associate', (info, socket) => {
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 how ever you want
// You can implement the rest however you want
// Just remember the response should be decided by version
})

Expand Down Expand Up @@ -248,13 +248,35 @@ server.useReq('connect', (info, socket) => {
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 how ever you want
// You can implement the rest however you want
// Just remember the response should be decided by version
})

server.listen(port, host)
```

### SOCKS server obfuscation

You can implement your obfuscation methods by extending your obfuscation class from the [ObfsMethod'](src/obfs/obfs.ts) class
and creating a builder function for your class [ObfsBuilder'](src/obfs/obfs.ts) or use the available obfuscation methods
by, passing their builder function to the useObfs hook as below:

```typescript
import { createServer, obfsMethods } from 'tsocks'

const host = '127.0.0.1'
const port = 1080

const server = createServer({
socks4: true,
socks5: true,
})

server.useObfs(obfsMethods.http())

server.listen(port, host)
```

### Proxy Client

No matter which version of the proxy server you want to interact with V4 or V5
Expand Down Expand Up @@ -529,6 +551,47 @@ try {
}
```

### SOCKS client obfuscation

You can implement your obfuscation methods by extending your obfuscation class from the [ObfsMethod'](src/obfs/obfs.ts) class
and creating a builder function for your class [ObfsBuilder'](src/obfs/obfs.ts) or use the available obfuscation methods
by, passing their builder function to the useObfs hook as below:

```typescript
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.http())
.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)
}
```

## References

- [RFC - SOCKS Protocol Version 5](https://www.rfc-editor.org/rfc/rfc1928)
Expand Down
4 changes: 2 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

- [ ] Complete documentation
- [ ] Complete test coverage
- [ ] Add obfuscation support
- [ ] Add encryption and compression to the http obfuscation method

### In Progress

- [ ] Complete documentation
- [ ] Complete test coverage
- [ ] Add obfuscation support

### Done ✓

Expand All @@ -18,3 +17,4 @@
- [x] Implementation of client Associate
- [x] Implementation of server Bind
- [x] Implementation of client Bind
- [x] Add obfuscation support
9 changes: 7 additions & 2 deletions src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,13 @@ export class Client {
return this
}

public useObfs(method: ObfsBuilder): Client {
this.obfs = method
/**
* Get the handler function, and update this.handlers.obfs
* @param handler - Emitted when new request appears
* @returns Server
*/
public useObfs(handler: ObfsBuilder): Client {
this.obfs = handler
return this
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/helper/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Address {
/**
* Regular expression for domain
*/
const domainRegex = '^[a-zA-Z0-9-\\_]+\\.[a-zA-Z]+?$'
const domainRegex = '([a-z0-9|-]+\\.)*[a-z0-9|-]+\\.[a-z]+'

/**
* Port
Expand Down
3 changes: 3 additions & 0 deletions src/helper/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ class Connection {
socks4: true,
}

/**
* The obfuscation method
*/
public obfs: ObfsMethod

/**
Expand Down
6 changes: 6 additions & 0 deletions src/helper/readable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ class Readable {
this.data = data
}

/**
* Read n bytes of data without modifying the data property,
* reads all the data if no argument is passed
* @param bytes - Number of bytes to be read from data
* @returns Buffer
*/
public cat(bytes?: number) {
let slice
if (bytes) {
Expand Down
40 changes: 34 additions & 6 deletions src/obfs/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import {
compressionMethods,
} from '../helper/constants'

/**
* The Http class is an obfuscation method based on the
* HTTP protocol
*/
class Http extends ObfsMethod {
public path
public name = 'HTTP'
Expand All @@ -27,10 +31,11 @@ class Http extends ObfsMethod {
this.method = method
}

handshake(callback: () => void): void {
callback()
}

/**
* Checks if the message format is Appropriate with
* this obfuscation method
* @param message - The incoming message
*/
check(message: Buffer) {
const regex = new RegExp(
`^(?<method>GET|POST|PUT|DELETE|HEAD|OPTIONS).\\/(?<path>[^HTTP]*) HTTP\\/(?<version>.*)`
Expand All @@ -44,6 +49,18 @@ class Http extends ObfsMethod {
return false
}

/**
* Begins the handshake process for the encryption
* @param callback - Emitted after the handshake process
*/
handshake(callback: () => void): void {
callback()
}

/**
* DeObfuscates the obfuscated message
* @param message - The obfuscated message
*/
deObfuscate(message: Buffer): Buffer {
const http = message.toString()
const bodyIndex = http.indexOf('\r\n\r\n')
Expand All @@ -62,6 +79,10 @@ class Http extends ObfsMethod {
return body
}

/**
* Obfuscates the non-obfuscated message
* @param message - The non-obfuscated message
*/
obfuscate(message: Buffer): Buffer {
let http = ''
if (this.type === ObfsMethod.SERVER) {
Expand All @@ -82,12 +103,19 @@ class Http extends ObfsMethod {
}
}

/**
* builds a Http obfuscation method object
* @param path - Endpoint path
* @param compression - Compression method
* @param encryption - Encryption algorithm
* @param method - HTTP method
*/
export const http =
(
path = '',
method = obfsHttpMethods.post,
compression = compressionMethods.none,
encryption = encryptionMethods.none,
method = obfsHttpMethods.post
encryption = encryptionMethods.none
) =>
(
connection: Connection,
Expand Down
31 changes: 27 additions & 4 deletions src/obfs/none.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
import ObfsMethod from './obfs'
import Connection from '../helper/connection'

/**
* The none is the simplest available obfuscation method
*/
class None extends ObfsMethod {
name = 'None'

/**
* Checks if the message format is Appropriate with
* this obfuscation method
* @param message - The incoming message
*/
check(message: Buffer): boolean {
return message[0] === 5 || message[0] === 4 || message[0] === 1
}

/**
* Begins the handshake process for the encryption
* @param callback - Emitted after the handshake process
*/
handshake(callback: () => void): void {
callback()
}

/**
* DeObfuscates the obfuscated message
* @param message - The obfuscated message
*/
deObfuscate(message: Buffer): Buffer {
return message
}

/**
* Obfuscates the non-obfuscated message
* @param message - The non-obfuscated message
*/
obfuscate(message: Buffer): Buffer {
return message
}

handshake(callback: () => void): void {
callback()
}
}

/**
* builds a None obfuscation method object
*/
export const none =
() =>
(
Expand Down
42 changes: 41 additions & 1 deletion src/obfs/obfs.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,61 @@
import Connection from '../helper/connection'

/**
* The ObfsMethod class is an abstract class that all other,
* extended classes should implement its methods and properties
* every obfuscation method should extend this class
*/
abstract class ObfsMethod {
public static readonly CLIENT = 'CLIENT'

public static readonly SERVER = 'SERVER'

/**
* The type of obfuscation
*/
public type: typeof ObfsMethod.CLIENT | typeof ObfsMethod.SERVER

/**
* Connection object
*/
protected connection: Connection

/**
* The Obfuscation method name
*/
public abstract name: string

constructor(
connection: Connection,
type: typeof ObfsMethod.CLIENT | typeof ObfsMethod.SERVER
) {
this.connection = connection
this.type = type
}
public abstract name: string

/**
* Checks if the message format is Appropriate with
* this obfuscation method
* @param message - The incoming message
*/
public abstract check(message: Buffer): boolean

/**
* Begins the handshake process for the encryption
* @param callback - Emitted after the handshake process
*/
public abstract handshake(callback: () => void): void

/**
* DeObfuscates the obfuscated message
* @param message - The obfuscated message
*/
public abstract deObfuscate(message: Buffer): Buffer

/**
* Obfuscates the non-obfuscated message
* @param message - The non-obfuscated message
*/
public abstract obfuscate(message: Buffer): Buffer
}

Expand Down
9 changes: 7 additions & 2 deletions src/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,13 @@ export class Server {
return this
}

public useObfs(method: ObfsBuilder): Server {
this.handlers.obfs.push(method)
/**
* Get the handler function, and update this.handlers.userId
* @param handler - Emitted when new request appears
* @returns Server
*/
public useObfs(handler: ObfsBuilder): Server {
this.handlers.obfs.push(handler)
return this
}

Expand Down

0 comments on commit a27e5a9

Please sign in to comment.