blinksocks/docs/development/architecture
2017-04-12 16:04:43 +08:00
..
architecture.png docs(*): update 2017-03-24 17:09:37 +08:00
README.md feat(socket): add timeout mechanism 2017-04-12 16:04:43 +08:00

Architecture

architecture

Proxy Protocols

To take over data send and receive of applications, we must find a widely used proxy protocol. Http/Socks5/Socks4/Socks4a are ideal, they only work on the client side, so don't worry about being attacked.

Pipe

Pipe is a duplex facility for dealing with data streaming. A pipe is created once a connection was open.

Pipe puts all middlewares in cascade(both upstream and downstream), feeds original data to the first middleware from time to time and gathers processed data from the last layer of all middlewares.

Middleware

Middleware is a class which used for processing input data to output data from/to different middlewares. There are four kind of middlewares:

  • FrameMiddleware

The lowest layer in the middleware stack. It packs data from application, or unpacks data from CryptoMiddleware.

  • CryptoMiddleware

The second layer in the middleware stack. It encrypts data from FrameMiddleware, or decrypts data from ProtocolMiddleware.

  • ProtocolMiddleware

The third layer in the middleware stack. It encapsulates data with additional headers from CryptoMiddleware, or decapsulates data from ObfsMiddleware.

The additional headers may be used for AEAD or other needs.

  • ObfsMiddleware

The last layer in the middleware stack. It encapsulates data with obfuscation headers from ProtocolMiddleware, or decapsulates data from network.

Preset

Preset is the implement of middleware, for examples you can check out src/presets, there are several built-in presets already:

  • frame/*: implement for FrameMiddleware
  • crypto/*: implement for CryptoMiddleware
  • protocol/*: implement for ProtocolMiddleware
  • obfs/*: implement for ObfsMiddleware

Custom Preset

A typical preset must implement four methods of IPreset interface:

// custom.js
export default class CustomPreset extends IPreset {

  clientOut({buffer/* , next, broadcast, fail */}) {
    // next(buffer); async
    return buffer; // sync
  }

  serverIn({buffer/* , next, broadcast, fail */}) {
    return buffer;
  }

  serverOut({buffer/* , next, broadcast, fail */}) {
    return buffer;
  }

  clientIn({buffer/* , next, broadcast, fail */}) {
    return buffer;
  }

}
METHODS DESCRIPTION
clientOut client will send data to server
serverIn server received data from client
serverOut server will send back data to client
clientIn client received data from server

NOTE: server* are used on the server side while client* are used on the client side.

Every method gets an object which contains three parameters you need:

PARAM DESCRIPTION
buffer output from the previous middleware
next call it with a new buffer once async process done
broadcast call it with an action to notify other middlewares
fail call it once handshake failed, connection will be closed in random seconds

Action passed to broadcast is an object which requires a type field:

// action
{
  type: <string>,
  payload: <any>
}

Once a method broadcast, all other middlewares will receive the action in onNotified(action) immediately:

// custom.js
export default class CustomPreset extends IPreset {

  /**
   * how to deal with the action, return false to ignore
   * @returns {boolean}
   */
  onNotified(/* action */) {
    return false;
  }

  // ...

}

Hooks

There are two hooks available:

// custom.js
export default class CustomPreset extends IPreset {

  beforeOut({buffer/* , next, broadcast, fail */}) {
    return buffer;
  }

  beforeIn({buffer/* , next, broadcast, fail */}) {
    return buffer;
  }

  // ...

}
METHODS DESCRIPTION
beforeOut pre-process before *Out()
beforeIn pre-process before *In()