liudong
2023-05-29 340f156319b863525e50e900c58e59b86ecb3d5e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
'use strict'
 
const proxy = require('proxy')
const { readFileSync } = require('fs')
const { join } = require('path')
const http = require('http')
const https = require('https')
const dns = require('dns')
 
/**
 * We've manually created self signed certificates for the proxy
 * and for the server, with the following domains (Subject CN)
 * proxy.hpagent-unit-test.com
 * server.hpagent-unit-test.com
 *
 * This will allow us to properly test the TLS-over-TLS proxy,
 * specifically that the first handshake provides the proxy SNI, not the server SNI.
 *
 * These certs were generated using openssl:
 * openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout key_server.pem -out cert_server.pem
 * openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout key_proxy.pem -out cert_proxy.pem
 *
 * The certs are concatenated to the can be passed to Node.JS as trusted certs:
 * $ cat cert_proxy.pem > certs_unit_test.pem
 * $ cat cert_server.pem >> certs_unit_test.pem
 *
 * using `NODE_EXTRA_CA_CERTS` (https://nodejs.org/api/cli.html#node_extra_ca_certsfile)
 *
 * This allows actual verification of the certs w/ hostname instead of ignoring all errors
 */
 
const sslProxy = {
  key: readFileSync(join(__dirname, 'fixtures/key_proxy.pem')),
  cert: readFileSync(join(__dirname, 'fixtures/cert_proxy.pem'))
}
 
const sslServer = {
  key: readFileSync(join(__dirname, 'fixtures/key_server.pem')),
  cert: readFileSync(join(__dirname, 'fixtures/cert_server.pem'))
}
 
/**
 * We override all DNS requests from the node process (for unit test) to resolve to
 * 127.0.0.1. This allows us to use the self signed certs we made for the fake
 * domains to be verified, and then the connection made to localhost.
 */
dns.lookup = (hostname, opts, cb) => {
  if (typeof opts === 'function') {
    return opts(null, '127.0.0.1', 4)
  }
 
  return cb(null, '127.0.0.1', 4)
}
 
function createProxy () {
  return new Promise((resolve, reject) => {
    const server = proxy(http.createServer())
    server.listen(0, '127.0.0.1', () => {
      resolve(server)
    })
  })
}
 
function createSecureProxy () {
  return new Promise((resolve, reject) => {
    const server = proxy(https.createServer(sslProxy))
    server.listen(0, '127.0.0.1', () => {
      resolve(server)
    })
  })
}
 
function createServer (handler, callback) {
  return new Promise((resolve, reject) => {
    const server = http.createServer()
    server.listen(0, '127.0.0.1', () => {
      resolve(server)
    })
  })
}
 
function createSecureServer (handler, callback) {
  return new Promise((resolve, reject) => {
    const server = https.createServer(sslServer)
    server.listen(0, '127.0.0.1', () => {
      resolve(server)
    })
  })
}
 
const PROXY_HOSTNAME = 'proxy.hpagent-unit-test.com'
const SERVER_HOSTNAME = 'server.hpagent-unit-test.com'
 
module.exports = {
  createProxy,
  createSecureProxy,
  createServer,
  createSecureServer,
  PROXY_HOSTNAME,
  SERVER_HOSTNAME
}