web-sniffer icon indicating copy to clipboard operation
web-sniffer copied to clipboard

Change target https port and allow self signed certificates

Open DrRek opened this issue 3 years ago • 1 comments

Hello,

I'm trying to intercept some https traffic and redirect it to another web service. So far I've managed with:

const fs = require('fs')
const Sniffer = require('web-proxy-sniffer')

const proxy = Sniffer.createServer({
  certAuthority: {
    key: fs.readFileSync(`key.pem`),
    cert: fs.readFileSync(`cert.pem`)
  }
})

proxy.intercept({
    // Intercept before the request is sent
    phase: 'request'
  }, (request, response) => {
    // Redirects the request to localhost
    request.headers.host = "localhost"
    console.log(request)

    return request
})

proxy.listen(8083)

But this doesn't work for two reason:

  • is it possible to specify the port to connect to?
  • is it possible to allow self-signed certificates? This is the error I get when I try to change the hostname to an https server on port 443 with a self signed certificate
node:events:371
      throw er; // Unhandled 'error' event
      ^

ProxyError: Unknown error
    at Function.from (/home/luca/projects/stalker_console/socket/backend/node_modules/web-proxy-sniffer/dist/errors/proxy-error.js:38:29)
    at BridgeServer.<anonymous> (/home/luca/projects/stalker_console/socket/backend/node_modules/web-proxy-sniffer/dist/proxy.js:33:52)
    at BridgeServer.emit (node:events:394:28)
    at HttpsServer.<anonymous> (/home/luca/projects/stalker_console/socket/backend/node_modules/web-proxy-sniffer/dist/bridgeServer.js:65:101)
    at HttpsServer.emit (node:events:394:28)
    at ClientRequest.<anonymous> (/home/luca/projects/stalker_console/socket/backend/node_modules/web-proxy-sniffer/dist/server.js:69:56)
    at ClientRequest.emit (node:events:394:28)
    at TLSSocket.socketErrorListener (node:_http_client:447:9)
    at TLSSocket.emit (node:events:394:28)
    at emitErrorNT (node:internal/streams/destroy:157:8)
Emitted 'error' event on Proxy instance at:
    at BridgeServer.<anonymous> (/home/luca/projects/stalker_console/socket/backend/node_modules/web-proxy-sniffer/dist/proxy.js:34:18)
    at BridgeServer.emit (node:events:394:28)
    [... lines matching original stack trace ...]
    at emitErrorNT (node:internal/streams/destroy:157:8)
    at emitErrorCloseNT (node:internal/streams/destroy:122:3) {
  type: 'Unknown Error',
  original: Error: self signed certificate
      at TLSSocket.onConnectSecure (node:_tls_wrap:1530:34)
      at TLSSocket.emit (node:events:394:28)
      at TLSSocket._finishInit (node:_tls_wrap:944:8)
      at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:725:12) {
    code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
  }
}

DrRek avatar Oct 07 '21 19:10 DrRek

I guess one way to solve this might be to

import http from 'http'
import https from 'https'
import ProxyError, { ErrorType } from './errors/proxy-error'
import { IRequest } from './models'

type RouterCallback = (response: http.IncomingMessage) => void

export default class Router {

  static forward(request: IRequest, callback: RouterCallback) {
    
    const httpRequestOptions: http.RequestOptions = {
      host: request.hostname,
      port: request.port || (request.protocol === 'https:' ? 443 : 80),
      path: request.url,
      method: request.method,
      headers: request.headers
    }

    const httpsRequestOptions: https.RequestOptions = {
      ...httpRequestOptions,
      rejectUnauthorized: false,
      agent: false
    }

    switch (request.protocol) {
      case 'http:': return http.request(httpRequestOptions, (response) => callback(response))
      case 'https:': return https.request(httpsRequestOptions, (response) => callback(response))
      default:  
      throw new ProxyError(
        `Unknown protocol ${request.protocol} received by the Router`,
        ErrorType.inconsistency
      )
    }
  }
}

But I've got no way to test it because I have no idea on how to build ts into node modules

DrRek avatar Oct 07 '21 19:10 DrRek