@lemonce3/mitm
Version:
HTTP/HTTPS man in the middle proxy server
317 lines (283 loc) • 7.75 kB
TypeScript
import { isStrategy } from "./src/strategy";
import net from 'net';
import stream from 'stream';
declare namespace mitm {
declare class MitmServer extends net.Server {
/**
* Create mitm server instance. Illegal to `new MitmServer()` directly
*
* @param options options for createing
*/
constructor(options: options);
}
/**
* Mitmserver class just be used for `instanceof`
*
* Bad Example,
* ```js
* const mitm = require('@lemonce3/mitm');
*
* new mitm.Server(); // Illegal construction.
* ```
*
* `instanceof` example,
* ```js
* const mitm = require('@lemonce3/mitm');
* const server = new mitm.createServer();
*
* console.log(server instanceof mitm.Server); // true
* ```
*/
export const Server: typeof MitmServer;
namespace ContextInterface {
interface Request {
/**
* A string specifying the HTTP request method
*
* - Getter: get the original HTTP method from client request
* - Setter: set a new valid method
*/
method: string,
/**
* - Getter: get the original target url
* - Setter: set a new url
*/
url: string | URL,
/**
* An object containing request headers
*
* - Getter: get original request headers kv in object type.
* - Setter: replace to a new headers
*/
headers: object,
/**
* - Getter: get original request payload body.
* - Setter: replace to a new payload body(string, buffer, stream accepted)
*/
body: Buffer | string | stream.Readable,
/**
* A number specifying the socket timeout in milliseconds.
* This will set the timeout **before** the socket is connected.
*
* - Getter: get the proxy connect timeout
* - Setter: replace to another number(unsigned int) millisecond.
*
* https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_options_callback
*
* default value is 120000(2 min)
*/
timeout: number
}
interface Response {
/**
* This property controls the status code that will be sent to the client
* when the headers get flushed.
*
* https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_message_statuscode
*
* - Getter: get response status code. Default: from proxy response.
* - Setter: replace to a specified status code.
*/
statusCode: number,
/**
* This property controls the status message that will be sent to the
* client when the headers get flushed. If this is left as undefined
* then the standard message for the status code will be used.
*
* https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_response_statusmessage
*
* - Getter: get response status message. Default: from proxy response.
* - Setter: replace to a specified status message string.
*
* default is `undefined`
*/
statusMessage: string,
/**
* An object containing request headers
*
* - Getter: get response headers kv in object type.
* - Setter: replace to a new headers
*/
headers: object,
/**
* - Getter: get response payload body. Default: proxy ``http.ServerResponse``.
* - Setter: replace to a new payload body(string, buffer, stream accepted)
*/
body: Buffer | string | stream.Readable
}
}
/**
* something
*/
interface ContextInterface {
/**
* request namespace
*/
request: ContextInterface.Request,
/**
* response namespace
*/
response: ContextInterface.Response
/**
* The recommended namespace for passing data between request & response.
*/
state: object
}
type respond = () => void;
type forward = () => void;
namespace options {
interface strategy {
/**
* According to socket and trunk to decide whether to
* proxy & hijacked secure connection.
*
* return,
* - true: With valid certificate options,
* the HTTPS request will be hijacked.
*
* - false: The https request will passthrough.
*
* default handler, passthrough all https request,
* ```js
* const mitm = require('@lemonce3/mitm');
*
* mitm.createServer({
* strategy: {
* sslConnect() {
* return false;
* }
* }
* });
* ```
*
* @param socket the socket on CONNECT
* @param chunk request message data
*/
sslConnect?(
socket?: net.Socket,
chunk?: Buffer
) : boolean | Promise<boolean>
/**
* When a request coming from client,
* to do something to context then respond() or forward().
* Proxy connection can be hijacked here.
*
* @param context A proxy object used to access request & default response
* @param respond Building response and echo client immediately
* @param forward Building request then reqest to target host
*/
request?(
context: mitm.ContextInterface,
respond: respond,
forward: forward
) : void | Promise<void>;
/**
* When a response coming after forward() from target,
* to do something to context then respond().
* Proxy response can be hijacked here.
*
* @param context A proxy object used to access request & forward response
* @param respond Updating response and echo client
*/
response?(
context: mitm.ContextInterface,
respond: respond
) : void | Promise<void>;
/**
* When a pair of ws socket has been established,
* to do something about these 2 socket.
*
* Default is piping each other
*
* @param clientSocket ws from client
* @param proxySocket ws to target
*/
websocket?(
clientSocket: net.Socket,
proxySocket: net.Socket
) : void | Promise<void>
}
interface socket {
/**
* All socket files where to store
*/
path: string,
/**
* How to generate socket file name.
* The final pathname is `${path}${getName()}`
*
* @param protocol url protocol
* @param hostname url hostname
* @param port url port
*/
getName(protocol: string, hostname: string, port: number): string
}
namespace certificate {
interface store {
/**
* The implemention for fetching a server certification created.
*/
get(hostname: string): string | Promise<string>;
/**
* The implemention for saving a server certification.
*/
set(hostname: string, value: string): string | Promise<string>;
}
}
interface certificate {
/**
* Root certificate of certification authority.
*/
cert: string;
/**
* The private key of the root certificate.
*/
key: string;
/**
* Implemention of server certificates getting & setting.
*/
store: certificate.store
}
}
interface options {
/**
* Use to set handler when
*
* - ssl connection establishing
* - request incomming
* - response incomming
* - websocket establishing
*
* to do something.
*/
strategy?: options.strategy,
/**
* Options about socket filename & storage in FS.
*/
socket?: options.socket,
/**
* Options about root ca & server certificate store.
*
* It will be not sslSupported if there is no
* valid certificate options provided.
*/
certificate?: CertificateStore,
/**
* Completely asynchronous processing for error.
* It will not affect any communication process.
*
* @param type error type
* @param message error message
*/
onError?(type: string, message: string): any;
}
/**
* Create mitm server.
* The options should include strategy, socket ,certificateStore and ssl.
* Otherwise, the mitm server will be creaeted and throw the exception.
*
* @param options options for createing
*/
declare function createServer(options: options): MitmServer;
}
export = mitm;